<commit_before>// Test that we do hit the default login rate limit.
// XXX Removed to fix testing as other packages currently hit the default rate
// limit.
testAsyncMulti("ddp rate limiter - default rate limit", [
  function (test, expect) {
    // Add in the default rate limiter rule
    Meteor.call('addDefaultAccountsRateLimitRule');
    _.extend(this, createTestUser(test, expect));
  },
  function (test, expect) {
    Meteor.logout(expect(function (error) {
      test.equal(error, undefined);
      test.equal(Meteor.user(), null);
    }));
  },
  function (test, expect) {
    var self = this;

    callFnMultipleTimesThenExpectResult(test, expect,
      Meteor.loginWithPassword.bind(Meteor, self.username, '<PASSWORD>'),
      {
        expectedError: 403,
        expectedResult: undefined,
        expectedRateLimitWillBeHit: true,
        expectedIntervalTimeInMs: 10000
      }
    );
  },
  function (test, expect) {
    Meteor.call("removeUserByUsername", this.username, expect(function () {}));
    // Remove the default rate limiter rule
    Meteor.call('removeDefaultAccountsRateLimitRule');
  }
]);

testAsyncMulti("ddp rate limiter - matchers get passed correct arguments", [
  function (test, expect) {
    _.extend(this, createTestUser(test, expect));
  },
  function (test, expect) {
    var self = this;
    Meteor.call("addRuleToDDPRateLimiter", expect(function(error, result) {
     self.ruleId = result;
    }));
  },
  function (test, expect) {
    callFnMultipleTimesThenExpectResult(test, expect,
      Meteor.call.bind(Meteor, 'dummyMethod'),
      {
        expectedError: undefined,
        expectedResult: "yup",
        expectedRateLimitWillBeHit: true
      }
    );
  },
  function (test, expect) {
    var self = this;
    Meteor.call(
      "getLastRateLimitEvent", expect(function (error, result) {
        test.equal(error, undefined);
        test.equal(result.userId, Meteor.userId());
        test.equal(result.type, "method");
        test.equal(result.name, "dummyMethod");
        test.isNotUndefined(result.clientAddress, "clientAddress is not defined");
      }));
  },
  function (test, expect) {
    Meteor.call("removeUserByUsername", this.username, expect(function () {}));
  },
  function (test, expect) {
    var self = this;
    // Cleanup
    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,
      expect(function(error, result) {
        test.equal(result,true);
    }));
  }
]);

testAsyncMulti("ddp rate limiter - callbacks get passed correct arguments", [
  function (test, expect) {
    _.extend(this, createTestUser(test, expect));
  },
  function (test, expect) {
    var self = this;
    Meteor.call("addRuleToDDPRateLimiter", expect(function(error, result) {
     self.ruleId = result;
    }));
  },
  function (test, expect) {
    Meteor.call('dummyMethod', expect(function() {}));
  },
  function (test, expect) {
    var self = this;
    Meteor.call(
      "getLastRateLimitEvent", expect(function (error, result) {
        test.isTrue(result.reply.allowed);
        test.isTrue(result.reply.timeToReset < RATE_LIMIT_INTERVAL_TIME_MS);
        test.equal(result.reply.numInvocationsLeft, 4);

        test.equal(result.ruleInput.userId, Meteor.userId());
        test.equal(result.ruleInput.type, 'method');
        test.equal(result.ruleInput.name, 'dummyMethod');
      }));
  },
  function (test, expect) {
    // Wait for the rule to reset
    Meteor.setTimeout(expect(), RATE_LIMIT_INTERVAL_TIME_MS);
  },
  function (test, expect) {
    // Call RATE_LIMIT_NUM_CALLS + 1 times to make the rule exceed limit and reject the execution
    for (var i = 0; i < RATE_LIMIT_NUM_CALLS + 1; i++) {
      Meteor.call('dummyMethod', expect(function() {}));
    }
  },
  function (test, expect) {
    var self = this;
    Meteor.call(
      "getLastRateLimitEvent", expect(function (error, result) {
        test.isFalse(result.reply.allowed);
        test.isTrue(result.reply.timeToReset < RATE_LIMIT_INTERVAL_TIME_MS);
        test.equal(result.reply.numInvocationsLeft, 0);

        test.equal(result.ruleInput.userId, Meteor.userId());
        test.equal(result.ruleInput.type, 'method');
        test.equal(result.ruleInput.name, 'dummyMethod');
      }));
  },
  function (test, expect) {
    Meteor.call("removeUserByUsername", this.username, expect(function () {}));
  },
  function (test, expect) {
    var self = this;<commit_msg>Make rate limiter tests more tolerant of slight timing variations.<commit_after>// Test that we do hit the default login rate limit.
// XXX Removed to fix testing as other packages currently hit the default rate
// limit.
testAsyncMulti("ddp rate limiter - default rate limit", [
  function (test, expect) {
    // Add in the default rate limiter rule
    Meteor.call('addDefaultAccountsRateLimitRule');
    _.extend(this, createTestUser(test, expect));
  },
  function (test, expect) {
    Meteor.logout(expect(function (error) {
      test.equal(error, undefined);
      test.equal(Meteor.user(), null);
    }));
  },
  function (test, expect) {
    var self = this;

    callFnMultipleTimesThenExpectResult(test, expect,
      Meteor.loginWithPassword.bind(Meteor, self.username, '<PASSWORD>'),
      {
        expectedError: 403,
        expectedResult: undefined,
        expectedRateLimitWillBeHit: true,
        expectedIntervalTimeInMs: 10000
      }
    );
  },
  function (test, expect) {
    Meteor.call("removeUserByUsername", this.username, expect(function () {}));
    // Remove the default rate limiter rule
    Meteor.call('removeDefaultAccountsRateLimitRule');
  }
]);

testAsyncMulti("ddp rate limiter - matchers get passed correct arguments", [
  function (test, expect) {
    _.extend(this, createTestUser(test, expect));
  },
  function (test, expect) {
    var self = this;
    Meteor.call("addRuleToDDPRateLimiter", expect(function(error, result) {
     self.ruleId = result;
    }));
  },
  function (test, expect) {
    callFnMultipleTimesThenExpectResult(test, expect,
      Meteor.call.bind(Meteor, 'dummyMethod'),
      {
        expectedError: undefined,
        expectedResult: "yup",
        expectedRateLimitWillBeHit: true
      }
    );
  },
  function (test, expect) {
    var self = this;
    Meteor.call(
      "getLastRateLimitEvent", expect(function (error, result) {
        test.equal(error, undefined);
        test.equal(result.userId, Meteor.userId());
        test.equal(result.type, "method");
        test.equal(result.name, "dummyMethod");
        test.isNotUndefined(result.clientAddress, "clientAddress is not defined");
      }));
  },
  function (test, expect) {
    Meteor.call("removeUserByUsername", this.username, expect(function () {}));
  },
  function (test, expect) {
    var self = this;
    // Cleanup
    Meteor.call('removeRuleFromDDPRateLimiter', self.ruleId,
      expect(function(error, result) {
        test.equal(result,true);
    }));
  }
]);

testAsyncMulti("ddp rate limiter - callbacks get passed correct arguments", [
  function (test, expect) {
    _.extend(this, createTestUser(test, expect));
  },
  function (test, expect) {
    var self = this;
    Meteor.call("addRuleToDDPRateLimiter", expect(function(error, result) {
     self.ruleId = result;
    }));
  },
  function (test, expect) {
    Meteor.call('dummyMethod', expect(function() {}));
  },
  function (test, expect) {
    var self = this;
    Meteor.call(
      "getLastRateLimitEvent", expect(function (error, result) {
        test.isTrue(result.reply.allowed);
        test.isTrue(result.reply.timeToReset < RATE_LIMIT_INTERVAL_TIME_MS + 100);
        test.equal(result.reply.numInvocationsLeft, 4);

        test.equal(result.ruleInput.userId, Meteor.userId());
        test.equal(result.ruleInput.type, 'method');
        test.equal(result.ruleInput.name, 'dummyMethod');
      }));
  },
  function (test, expect) {
    // Wait for the rule to reset
    Meteor.setTimeout(expect(), RATE_LIMIT_INTERVAL_TIME_MS);
  },
  function (test, expect) {
    // Call RATE_LIMIT_NUM_CALLS + 1 times to make the rule exceed limit and reject the execution
    for (var i = 0; i < RATE_LIMIT_NUM_CALLS + 1; i++) {
      Meteor.call('dummyMethod', expect(function() {}));
    }
  },
  function (test, expect) {
    var self = this;
    Meteor.call(
      "getLastRateLimitEvent", expect(function (error, result) {
        test.isFalse(result.reply.allowed);
        test.isTrue(result.reply.timeToReset < RATE_LIMIT_INTERVAL_TIME_MS + 100);
        test.equal(result.reply.numInvocationsLeft, 0);

        test.equal(result.ruleInput.userId, Meteor.userId());
        test.equal(result.ruleInput.type, 'method');
        test.equal(result.ruleInput.name, 'dummyMethod');
      }));
  },
  function (test, expect) {
    Meteor.call("removeUserByUsername", this.username, expect(function () {}));
  },
  function (test, expect) {
    var self = this;
{'fraction_non_alphanumeric': 0.13508041840062984, 'fraction_numerical': 0.003599145203014284, 'mean_word_length': 3.268843014882381, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '973843', 'n_tokens_mistral': 2792, 'n_tokens_neox': 2747, 'n_words': 590}