Skip to content

Commit 4d6d410

Browse files
🧪 Add tests for isInRollout algorithm (#544)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com>
1 parent 9317f66 commit 4d6d410

3 files changed

Lines changed: 90 additions & 1 deletion

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { describe, expect, it, mock } from 'bun:test';
2+
3+
// Use the preload setup file instead of inline mocks since bun resolves
4+
// dynamic imports relative to the test runner's context and caching.
5+
import './setup';
6+
7+
let mockUuid = '';
8+
mock.module('../core', () => {
9+
return {
10+
cInfo: {
11+
get uuid() { return mockUuid; }
12+
}
13+
};
14+
});
15+
16+
import { murmurhash3_32_gc } from '../isInRollout';
17+
18+
describe('murmurhash3_32_gc', () => {
19+
it('should be deterministic (return the same output for the same input)', () => {
20+
const input1 = '123e4567-e89b-12d3-a456-426614174000';
21+
const input2 = 'test-string';
22+
23+
expect(murmurhash3_32_gc(input1)).toBe(murmurhash3_32_gc(input1));
24+
expect(murmurhash3_32_gc(input2)).toBe(murmurhash3_32_gc(input2));
25+
});
26+
27+
it('should return different outputs for different inputs', () => {
28+
const input1 = '123e4567-e89b-12d3-a456-426614174000';
29+
const input2 = '123e4567-e89b-12d3-a456-426614174001';
30+
31+
expect(murmurhash3_32_gc(input1)).not.toBe(murmurhash3_32_gc(input2));
32+
});
33+
34+
it('should handle empty string correctly', () => {
35+
expect(typeof murmurhash3_32_gc('')).toBe('number');
36+
});
37+
38+
it('should return known outputs for known inputs', () => {
39+
expect(murmurhash3_32_gc('test1') % 100).toBe(24);
40+
expect(murmurhash3_32_gc('test2') % 100).toBe(69);
41+
expect(murmurhash3_32_gc('test3') % 100).toBe(0);
42+
expect(murmurhash3_32_gc('123e4567-e89b-12d3-a456-426614174000') % 100).toBe(36);
43+
expect(murmurhash3_32_gc('123e4567-e89b-12d3-a456-426614174001') % 100).toBe(94);
44+
});
45+
});
46+
47+
describe('isInRollout', () => {
48+
it('should return true when the rollout is greater than the hash modulo', async () => {
49+
mockUuid = 'test1';
50+
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
51+
expect(isInRollout(25)).toBe(true);
52+
});
53+
54+
it('should return false when the rollout is equal to the hash modulo', async () => {
55+
mockUuid = 'test1';
56+
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
57+
expect(isInRollout(24)).toBe(false);
58+
});
59+
60+
it('should return false when the rollout is less than the hash modulo', async () => {
61+
mockUuid = 'test1';
62+
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
63+
expect(isInRollout(23)).toBe(false);
64+
});
65+
66+
it('should evaluate correctly for a different uuid', async () => {
67+
mockUuid = 'test3';
68+
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
69+
expect(isInRollout(1)).toBe(true);
70+
expect(isInRollout(0)).toBe(false);
71+
expect(isInRollout(-1)).toBe(false);
72+
});
73+
74+
it('should always return false for 0% rollout', async () => {
75+
mockUuid = 'test1';
76+
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
77+
expect(isInRollout(0)).toBe(false);
78+
});
79+
80+
it('should always return true for 100% rollout', async () => {
81+
mockUuid = 'test1';
82+
const { isInRollout } = await import(`../isInRollout?id=${Date.now()}`);
83+
expect(isInRollout(100)).toBe(true);
84+
});
85+
});

‎src/__tests__/setup.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,7 @@ mock.module('../i18n', () => {
3838
},
3939
};
4040
});
41+
42+
mock.module('react-native/Libraries/Core/ReactNativeVersion', () => ({
43+
version: { major: 0, minor: 73, patch: 0 },
44+
}));

‎src/isInRollout.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { cInfo } from './core';
44

55
/* eslint-disable no-bitwise */
6-
function murmurhash3_32_gc(key: string, seed = 0) {
6+
export function murmurhash3_32_gc(key: string, seed = 0) {
77
let remainder, bytes, h1, h1b, c1, c2, k1, i;
88

99
remainder = key.length & 3; // key.length % 4

0 commit comments

Comments
 (0)