Skip to content

[Go] Add test coverage for the rand package#427

Open
tauptlab wants to merge 1 commit into
google:mainfrom
tauptlab:main
Open

[Go] Add test coverage for the rand package#427
tauptlab wants to merge 1 commit into
google:mainfrom
tauptlab:main

Conversation

@tauptlab
Copy link
Copy Markdown

Closes the test-coverage TODO at the top of rand.go. The package only had a test for Boolean's bit-shifting before this.

The tests are in three layers. Byte-stream tests swap randBuf for a bytes.NewReader and check exact outputs - this is where the targeted edge cases live: I63n's rejection loop at (MaxInt64/n)*n, the sign-bit mask, Geometric's leading-zero counting, and Uniform's r==0 fallback. The fallback can't be reached from crypto/rand at any realistic call count, but it's reachable by feeding 128 zero bytes (forces Geometric()>=1024 so math.Pow(2,k) overflows to +Inf).

Range tests verify that outputs sit in the documented range, 10k samples each. Moment tests sample 1M times and compare mean and variance against population values, with 5-sigma tolerances derived from each distribution's variance and 4th central moment. The helper skips the variance check on Bernoulli-shaped distributions where mu_4 == sigma^4.

TestNormal_FourthMoment is a separate explicit check because Normal and Laplace at the same variance both pass the regular moment test - they only differ at mu_4 (3 vs 6). The library uses both for the Gaussian and Laplace mechanisms.

TestConcurrent stresses the package locks with 8 goroutines, plus a Boolean mean check so it has signal even without -race. testing.Short() skips the moment tests.

rand.go

Dropped the test-coverage TODO. One-line comment above randBuf saying it must wrap crypto/rand.

Two new TODO comments for bugs I bumped into while writing the tests:

  • I63n doesn't validate n. n=0 panics with divide-by-zero, n<0 returns values in [0, |n|) instead of failing.
  • randSource.Int63 returns math.MinInt64 when the byte stream gives 0x8000000000000000 (since -math.MinInt64 == math.MinInt64 in two's complement). Probability 2^-64 per call so it's a contract violation rather than an attack vector. One-character fix.

Will send separate PRs.

Testing

go test ./go/... clean. -count=10 clean. -short skips the moments. Couldn't run -race - no gcc on this Windows machine.

Closes the TODO that asked for tests of the exported noise-generating
functions. Includes deterministic byte-level tests, range invariants,
5-sigma moment checks, and a concurrent stress test.

Also adds in-place TODO comments for two pre-existing bugs surfaced
while writing the tests (I63n input validation, randSource.Int63
math.MinInt64 overflow), to be fixed in follow-up PRs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant