UNPKG

auth0-id-generator

Version:

Generates random ids with a prefix (a la Stripe)

120 lines (96 loc) 4.67 kB
var expect = require('chai').expect; var {assert} = require('chai'); var randomInteger = require('../lib/randomInteger'); describe("randomInteger", function () { it("should throw when passed a negative value", function () { expect(function () { randomInteger(-10); }).to.throw(Error, /must be a natural number/); }); it("should throw when passed an unsafe integer", function () { expect(function () { randomInteger(Number.MAX_VALUE); }).to.throw(Error, /must be a safe integer/); }); it("should return a random number less than the specified maximum and greater than 0", function () { var randomInts = []; for (var i = 0; i <= 1000; i++) { randomInts.push(randomInteger(16)); } randomInts.forEach(e => { assert.isAtMost(e, 16); assert.isAtLeast(e, 0); }); }); it("number returned should be exclusive of maximum", function () { var randomInts = []; for (var i = 0; i <= 1000; i++) { randomInts.push(randomInteger(1)); } expect(randomInts).not.to.include.members([1]); }); it("number returned should be inclusive of 0", function () { var randomInts = []; for (var i = 0; i <= 1000; i++) { randomInts.push(randomInteger(1)); } expect(randomInts).to.include.members([0]); }); it("probability distribution should be highly uniform for our preferred dictionary length", function () { /* We want to ensure that there's a fairly uniform probability distribution across a given range, and that the generated values are not weighted too far from the mean value. We use the mean of the sample to determine whether there is a bias towards the start or end of the distribution (modulo bias would introduce a bias towards the start of the sample). We use the variance of the probability distribution to determine the 'spread' of probabilities from the mean - in our case, the more uniform the better - there should be a lower variance. */ var SAMPLE_SIZE = 1000000; var SAMPLE_RANGE = 1000; // This value originates from testing the unbiased sample-discarding // method - the mean value fluctuates by this range. var ALLOWED_MEAN_DIVERGENCE = (SAMPLE_RANGE / 2) * 0.002; // The tolerable variance of the probability density - what's the biggest // difference in probability that we want to tolerate? // This value, like mean divergence, is derived from testing - this was the variance figure's observed // ceiling. Changing the sample size and range will likely require a change in this variance var ALLOWED_PDF_VARIANCE = 1.67e-7 function getMeanValue(array) { return array.reduce((acc, val) => acc + val) / array.length; } this.timeout(5000); var sample = []; // Generate a sample of randomly generated numbers within our test range for (var i = 0; i <= SAMPLE_SIZE; i++) { sample.push(randomInteger(SAMPLE_RANGE)); } // Get the mean generated value, and check that there's minimal movement from the mean value var mean = getMeanValue(sample); expect(mean).to.lessThan((SAMPLE_RANGE / 2) + ALLOWED_MEAN_DIVERGENCE) expect(mean).to.greaterThan((SAMPLE_RANGE / 2) - ALLOWED_MEAN_DIVERGENCE) // Work out the probability distribution of the randomInteger function var variance = getMeanValue(sample.map(function (num) { return Math.pow(num - mean, 2); })); var stdDev = Math.sqrt(variance) var pdfDistribution = new Array(SAMPLE_RANGE); // Generate a sample of probability distributions // for each value in the range, what is the probability that it will // be generated by our randomInteger function? for (var i = 0; i <= SAMPLE_RANGE; i++) { // calculate the probability density var m = stdDev * Math.sqrt(2 * Math.PI); var e = Math.exp(-Math.pow(i - mean, 2) / (2 * variance)); pdfDistribution.push(e / m); } // get the variance in probabilities of our distribution var pdfMean = getMeanValue(pdfDistribution); var pdfVariance = getMeanValue(pdfDistribution.map(function (num) { return Math.pow(num - pdfMean, 2); })); expect(pdfVariance).is.lessThan(ALLOWED_PDF_VARIANCE) }); });