aboutsummaryrefslogtreecommitdiff
path: root/test/utils
diff options
context:
space:
mode:
authorDivisionByZero <[email protected]>2024-09-26 17:50:05 +0200
committerGitHub <[email protected]>2024-09-26 17:50:05 +0200
commit9537dfddba882bd93d9a429697fd44bc72428426 (patch)
treef60b5b694d5e4e8ddab228aeb20c7b7746685edc /test/utils
parent424b120a4d94b15b6e77c04a0aaffd0016a9c870 (diff)
downloadfaker-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.snap25
-rw-r--r--test/utils/mersenne-test-utils.ts17
-rw-r--r--test/utils/mersenne.spec.ts140
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);
+ });
+ });
+ });
+});