Inject randomness and time

Rule

Library code does not call Math.random() or Date.now(). Functions that need randomness or the current time take it as a parameter (rng: () => number, now: () => number), so tests pass fixed sequences and get the same result on every run.

Do

export type Rng = () => number;
 
export function pickIndex(length: number, rng: Rng): number {
  return Math.floor(rng() * length);
}

Don’t

export function pickIndex(length: number): number {
  return Math.floor(Math.random() * length);
}

Exceptions

Security-sensitive randomness uses crypto.getRandomValues, which this rule does not restrict.

Rationale

Hidden randomness and clock reads make tests flaky and golden vectors impossible. The A7 kernel requires deterministic property tests. Severity is WARN while the rule’s false-positive rate is unknown. Source: Testing Practices.