pgregory.net/rand@v1.0.3-0.20230808192358-a0b8ce02f4da/rand_test.go (about) 1 // Copyright 2022 Gregory Petrosyan <gregory.petrosyan@gmail.com> 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, v. 2.0. If a copy of the MPL was not distributed with this 5 // file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 7 package rand_test 8 9 import ( 10 "bytes" 11 "math" 12 "math/bits" 13 "pgregory.net/rand" 14 "pgregory.net/rapid" 15 "testing" 16 ) 17 18 func TestRand_Read(t *testing.T) { 19 rapid.Check(t, func(t *rapid.T) { 20 const N = 32 21 s := rapid.Uint64().Draw(t, "s").(uint64) 22 r := rand.New(s) 23 buf := make([]byte, N) 24 _, _ = r.Read(buf) 25 r.Seed(s) 26 buf2 := make([]byte, N) 27 for n := 0; n < N; { 28 c := rapid.IntRange(0, N-n).Draw(t, "c").(int) 29 _, _ = r.Read(buf2[n : n+c]) 30 n += c 31 } 32 if !bytes.Equal(buf, buf2) { 33 t.Fatalf("got %q instead of %q when reading in chunks", buf2, buf) 34 } 35 }) 36 } 37 38 func TestRand_Float32(t *testing.T) { 39 rapid.Check(t, func(t *rapid.T) { 40 s := rapid.Uint64().Draw(t, "s").(uint64) 41 r := rand.New(s) 42 f := r.Float32() 43 if f < 0 || f >= 1 { 44 t.Fatalf("got %v outside of [0, 1)", f) 45 } 46 }) 47 } 48 49 func TestRand_Float64(t *testing.T) { 50 rapid.Check(t, func(t *rapid.T) { 51 s := rapid.Uint64().Draw(t, "s").(uint64) 52 r := rand.New(s) 53 f := r.Float64() 54 if f < 0 || f >= 1 { 55 t.Fatalf("got %v outside of [0, 1)", f) 56 } 57 }) 58 } 59 60 func TestRand_Int31n(t *testing.T) { 61 rapid.Check(t, func(t *rapid.T) { 62 s := rapid.Uint64().Draw(t, "s").(uint64) 63 r := rand.New(s) 64 n := rapid.Int32Range(1, math.MaxInt32).Draw(t, "n").(int32) 65 v := r.Int31n(n) 66 if v < 0 || v >= n { 67 t.Fatalf("got %v outside of [0, %v)", v, n) 68 } 69 }) 70 } 71 72 func TestRand_Int63n(t *testing.T) { 73 rapid.Check(t, func(t *rapid.T) { 74 s := rapid.Uint64().Draw(t, "s").(uint64) 75 r := rand.New(s) 76 n := rapid.Int64Range(1, math.MaxInt64).Draw(t, "n").(int64) 77 v := r.Int63n(n) 78 if v < 0 || v >= n { 79 t.Fatalf("got %v outside of [0, %v)", v, n) 80 } 81 }) 82 } 83 84 func TestRand_Intn(t *testing.T) { 85 rapid.Check(t, func(t *rapid.T) { 86 s := rapid.Uint64().Draw(t, "s").(uint64) 87 r := rand.New(s) 88 n := rapid.IntRange(1, math.MaxInt).Draw(t, "n").(int) 89 v := r.Intn(n) 90 if v < 0 || v >= n { 91 t.Fatalf("got %v outside of [0, %v)", v, n) 92 } 93 }) 94 } 95 96 func TestRand_Uint32n(t *testing.T) { 97 rapid.Check(t, func(t *rapid.T) { 98 s := rapid.Uint64().Draw(t, "s").(uint64) 99 r := rand.New(s) 100 n := rapid.Uint32Range(1, math.MaxUint32).Draw(t, "n").(uint32) 101 v := r.Uint32n(n) 102 if v >= n { 103 t.Fatalf("got %v outside of [0, %v)", v, n) 104 } 105 }) 106 } 107 108 func TestRand_Uint64n(t *testing.T) { 109 rapid.Check(t, func(t *rapid.T) { 110 s := rapid.Uint64().Draw(t, "s").(uint64) 111 r := rand.New(s) 112 n := rapid.Uint64Range(1, math.MaxUint64).Draw(t, "n").(uint64) 113 v := r.Uint64n(n) 114 if v >= n { 115 t.Fatalf("got %v outside of [0, %v)", v, n) 116 } 117 }) 118 } 119 120 func TestRand_MarshalBinary_Roundtrip(t *testing.T) { 121 rapid.Check(t, func(t *rapid.T) { 122 s := rapid.Uint64().Draw(t, "s").(uint64) 123 r1 := rand.New(s) 124 data1, err := r1.MarshalBinary() 125 if err != nil { 126 t.Fatalf("got unexpected marshal error: %v", err) 127 } 128 var r2 rand.Rand 129 err = r2.UnmarshalBinary(data1) 130 if err != nil { 131 t.Fatalf("got unexpected unmarshal error: %v", err) 132 } 133 data2, err := r2.MarshalBinary() 134 if err != nil { 135 t.Fatalf("got unexpected marshal error: %v", err) 136 } 137 if !bytes.Equal(data1, data2) { 138 t.Fatalf("data %q / %q after marshal/unmarshal", data1, data2) 139 } 140 }) 141 } 142 143 func TestRand_Uint32nOpt(t *testing.T) { 144 rapid.Check(t, func(t *rapid.T) { 145 n := rapid.Uint32().Draw(t, "n").(uint32) 146 v := rapid.Uint64().Draw(t, "v").(uint64) 147 148 res, frac := bits.Mul32(n, uint32(v>>32)) 149 hi, _ := bits.Mul32(n, uint32(v)) 150 _, carry := bits.Add32(frac, hi, 0) 151 res += carry 152 153 res2, _ := bits.Mul64(uint64(n), v) 154 155 if uint32(res2) != res { 156 t.Fatalf("got %v instead of %v", res2, res) 157 } 158 }) 159 }