1 // Copied from https://cs.opensource.google/go/x/exp/+/24438e51023af3bfc1db8aed43c1342817e8cfcd:rand/modulo_test.go 2 3 // Copyright 2017 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // This file validates that the calculation in Uint64n corrects for 8 // possible bias. 9 10 package rand 11 12 import ( 13 "testing" 14 ) 15 16 // modSource is used to probe the upper region of uint64 space. It 17 // generates values sequentially in [maxUint64-15,maxUint64]. With 18 // modEdge == 15 and maxUint64 == 1<<64-1 == 18446744073709551615, 19 // this means that Uint64n(10) will repeatedly probe the top range. 20 // We thus expect a bias to result unless the calculation in Uint64n 21 // gets the edge condition right. We test this by calling Uint64n 100 22 // times; the results should be perfectly evenly distributed across 23 // [0,10). 24 type modSource uint64 25 26 const modEdge = 15 27 28 func (m *modSource) Seed(uint64) {} 29 30 // Uint64 returns a non-pseudo-random 64-bit unsigned integer as a uint64. 31 func (m *modSource) Uint64() uint64 { 32 if *m > modEdge { 33 *m = 0 34 } 35 r := maxUint64 - *m 36 *m++ 37 return uint64(r) 38 } 39 40 func TestUint64Modulo(t *testing.T) { 41 var src modSource 42 rng := New(&src) 43 var result [10]uint64 44 for i := 0; i < 100; i++ { 45 result[rng.Uint64n(10)]++ 46 } 47 for _, r := range result { 48 if r != 10 { 49 t.Fatal(result) 50 } 51 } 52 } 53