diff options
| author | DivisionByZero <[email protected]> | 2024-09-26 17:50:05 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-09-26 17:50:05 +0200 |
| commit | 9537dfddba882bd93d9a429697fd44bc72428426 (patch) | |
| tree | f60b5b694d5e4e8ddab228aeb20c7b7746685edc /test/utils | |
| parent | 424b120a4d94b15b6e77c04a0aaffd0016a9c870 (diff) | |
| download | faker-9537dfddba882bd93d9a429697fd44bc72428426.tar.xz faker-9537dfddba882bd93d9a429697fd44bc72428426.zip | |
infra: update file structure for util/internal (#3141)
Diffstat (limited to 'test/utils')
| -rw-r--r-- | test/utils/__snapshots__/mersenne.spec.ts.snap | 25 | ||||
| -rw-r--r-- | test/utils/mersenne-test-utils.ts | 17 | ||||
| -rw-r--r-- | test/utils/mersenne.spec.ts | 140 |
3 files changed, 182 insertions, 0 deletions
diff --git a/test/utils/__snapshots__/mersenne.spec.ts.snap b/test/utils/__snapshots__/mersenne.spec.ts.snap new file mode 100644 index 00000000..c045e2e7 --- /dev/null +++ b/test/utils/__snapshots__/mersenne.spec.ts.snap @@ -0,0 +1,25 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`generateMersenne32Randomizer() > seed: [42,1,2] > should return deterministic value for next() 1`] = `0.8562037434894592`; + +exports[`generateMersenne32Randomizer() > seed: [1211,1,2] > should return deterministic value for next() 1`] = `0.8916433283593506`; + +exports[`generateMersenne32Randomizer() > seed: [1337,1,2] > should return deterministic value for next() 1`] = `0.17990487208589911`; + +exports[`generateMersenne32Randomizer() > seed: 42 > should return deterministic value for next() 1`] = `0.37454011430963874`; + +exports[`generateMersenne32Randomizer() > seed: 1211 > should return deterministic value for next() 1`] = `0.9285201537422836`; + +exports[`generateMersenne32Randomizer() > seed: 1337 > should return deterministic value for next() 1`] = `0.2620246761944145`; + +exports[`generateMersenne53Randomizer() > seed: [42,1,2] > should return deterministic value for next() 1`] = `0.8562037477947296`; + +exports[`generateMersenne53Randomizer() > seed: [1211,1,2] > should return deterministic value for next() 1`] = `0.8916433279801969`; + +exports[`generateMersenne53Randomizer() > seed: [1337,1,2] > should return deterministic value for next() 1`] = `0.17990487224060836`; + +exports[`generateMersenne53Randomizer() > seed: 42 > should return deterministic value for next() 1`] = `0.3745401188473625`; + +exports[`generateMersenne53Randomizer() > seed: 1211 > should return deterministic value for next() 1`] = `0.9285201539025842`; + +exports[`generateMersenne53Randomizer() > seed: 1337 > should return deterministic value for next() 1`] = `0.2620246750155817`; diff --git a/test/utils/mersenne-test-utils.ts b/test/utils/mersenne-test-utils.ts new file mode 100644 index 00000000..ee7a43da --- /dev/null +++ b/test/utils/mersenne-test-utils.ts @@ -0,0 +1,17 @@ +// Moved to a separate file to avoid importing the tests + +/** + * The maximum value that can be returned by `MersenneTwister19937.genrandReal2()`. + * This is the max possible value with 32 bits of precision that is less than 1. + */ +export const TWISTER_32CO_MAX_VALUE = 0.9999999997671694; +/** + * The maximum value that can be returned by `MersenneTwister19937.genrandRes53()`. + * This is the max possible value with 53 bits of precision that is less than 1. + */ +export const TWISTER_53CO_MAX_VALUE = 0.9999999999999999; +// Re-exported because the value might change in the future +/** + * The maximum value that can be returned by `next()`. + */ +export const MERSENNE_MAX_VALUE = TWISTER_32CO_MAX_VALUE; diff --git a/test/utils/mersenne.spec.ts b/test/utils/mersenne.spec.ts new file mode 100644 index 00000000..5e9e4c27 --- /dev/null +++ b/test/utils/mersenne.spec.ts @@ -0,0 +1,140 @@ +import { beforeAll, beforeEach, describe, expect, it } from 'vitest'; +import { MersenneTwister19937 } from '../../src/internal/mersenne'; +import type { Randomizer } from '../../src/randomizer'; +import { + generateMersenne32Randomizer, + generateMersenne53Randomizer, +} from '../../src/utils/mersenne'; +import { seededRuns } from '../support/seeded-runs'; +import { times } from '../support/times'; +import { + MERSENNE_MAX_VALUE, + TWISTER_32CO_MAX_VALUE, + TWISTER_53CO_MAX_VALUE, +} from './mersenne-test-utils'; + +const NON_SEEDED_BASED_RUN = 25; + +function newTwister( + seed: number = Math.random() * Number.MAX_SAFE_INTEGER +): MersenneTwister19937 { + const twister = new MersenneTwister19937(); + twister.initGenrand(seed); + return twister; +} + +describe('MersenneTwister19937', () => { + describe('genrandInt32()', () => { + it('should be able to return 0', () => { + const twister = newTwister(257678572); + + // There is no single value seed that can produce 0 in the first call + for (let i = 0; i < 5; i++) { + twister.genrandInt32(); + } + + const actual = twister.genrandInt32(); + expect(actual).toBe(0); + }); + + it('should be able to return 2^32-1', () => { + const twister = newTwister(2855577693); + const actual = twister.genrandInt32(); + expect(actual).toBe(2 ** 32 - 1); + }); + }); + + describe('genrandReal2()', () => { + it('should be able to return 0', () => { + const twister = newTwister(); + // shortcut to return minimal value + // the test above shows that it is possible to return 0 + twister.genrandInt32 = () => 0; + const actual = twister.genrandReal2(); + expect(actual).toBe(0); + }); + + it('should be able to return almost 1', () => { + const twister = newTwister(); + // shortcut to return maximal value + // the test above shows that it is possible to return 2^32-1 + twister.genrandInt32 = () => 2 ** 32 - 1; + const actual = twister.genrandReal2(); + expect(actual).toBe(TWISTER_32CO_MAX_VALUE); + }); + }); + + describe('genrandRes53()', () => { + it('should be able to return 0', () => { + const twister = newTwister(); + // shortcut to return minimal value + // the test above shows that it is possible to return 0 + twister.genrandInt32 = () => 0; + const actual = twister.genrandRes53(); + expect(actual).toBe(0); + }); + + it('should be able to return almost 1', () => { + const twister = newTwister(); + // shortcut to return maximal value + // the test above shows that it is possible to return 2^32-1 + twister.genrandInt32 = () => 2 ** 32 - 1; + const actual = twister.genrandRes53(); + expect(actual).toBe(TWISTER_53CO_MAX_VALUE); + }); + }); +}); + +describe.each([ + ['generateMersenne32Randomizer()', generateMersenne32Randomizer], + ['generateMersenne53Randomizer()', generateMersenne53Randomizer], +])('%s', (_, factory) => { + const randomizer: Randomizer = factory(); + + it('should return a result matching the interface', () => { + expect(randomizer).toBeDefined(); + expect(randomizer).toBeTypeOf('object'); + expect(randomizer.next).toBeTypeOf('function'); + expect(randomizer.seed).toBeTypeOf('function'); + }); + + describe.each( + [...seededRuns, ...seededRuns.map((v) => [v, 1, 2])].map((v) => [v]) + )('seed: %j', (seed) => { + beforeEach(() => { + randomizer.seed(seed); + }); + + it('should return deterministic value for next()', () => { + const actual = randomizer.next(); + + expect(actual).toMatchSnapshot(); + }); + }); + + function randomSeed(): number { + return Math.ceil(Math.random() * 1_000_000_000); + } + + // Create and log-back the seed for debug purposes + describe.each( + times(NON_SEEDED_BASED_RUN).flatMap(() => [ + [randomSeed()], + [[randomSeed(), randomSeed()]], + ]) + )('random seeded tests %j', (seed) => { + beforeAll(() => { + randomizer.seed(seed); + }); + + describe('next', () => { + it('should return random number from interval [0, 1)', () => { + const actual = randomizer.next(); + + expect(actual).toBeGreaterThanOrEqual(0); + expect(actual).toBeLessThanOrEqual(MERSENNE_MAX_VALUE); + expect(actual).toBeLessThan(1); + }); + }); + }); +}); |
