Source file
src/crypto/rand/rand_test.go
1
2
3
4
5 package rand
6
7 import (
8 "bytes"
9 "compress/flate"
10 "crypto/internal/boring"
11 "errors"
12 "internal/asan"
13 "internal/msan"
14 "internal/race"
15 "internal/testenv"
16 "io"
17 "os"
18 "runtime"
19 "sync"
20 "testing"
21 )
22
23 func testReadAndReader(t *testing.T, f func(*testing.T, func([]byte) (int, error))) {
24 t.Run("Read", func(t *testing.T) {
25 f(t, Read)
26 })
27 t.Run("Reader.Read", func(t *testing.T) {
28 f(t, Reader.Read)
29 })
30 }
31
32 func TestRead(t *testing.T) {
33 testReadAndReader(t, testRead)
34 }
35
36 func testRead(t *testing.T, Read func([]byte) (int, error)) {
37 var n int = 4e6
38 if testing.Short() {
39 n = 1e5
40 }
41 b := make([]byte, n)
42 n, err := Read(b)
43 if n != len(b) || err != nil {
44 t.Fatalf("Read(buf) = %d, %s", n, err)
45 }
46
47 var z bytes.Buffer
48 f, _ := flate.NewWriter(&z, 5)
49 f.Write(b)
50 f.Close()
51 if z.Len() < len(b)*99/100 {
52 t.Fatalf("Compressed %d -> %d", len(b), z.Len())
53 }
54 }
55
56 func TestReadByteValues(t *testing.T) {
57 testReadAndReader(t, testReadByteValues)
58 }
59
60 func testReadByteValues(t *testing.T, Read func([]byte) (int, error)) {
61 b := make([]byte, 1)
62 v := make(map[byte]bool)
63 for {
64 n, err := Read(b)
65 if n != 1 || err != nil {
66 t.Fatalf("Read(b) = %d, %v", n, err)
67 }
68 v[b[0]] = true
69 if len(v) == 256 {
70 break
71 }
72 }
73 }
74
75 func TestLargeRead(t *testing.T) {
76 testReadAndReader(t, testLargeRead)
77 }
78
79 func testLargeRead(t *testing.T, Read func([]byte) (int, error)) {
80
81 b := make([]byte, 40<<20)
82 if n, err := Read(b); err != nil {
83 t.Fatal(err)
84 } else if n != len(b) {
85 t.Fatalf("Read(b) = %d, want %d", n, len(b))
86 }
87 }
88
89 func TestReadEmpty(t *testing.T) {
90 testReadAndReader(t, testReadEmpty)
91 }
92
93 func testReadEmpty(t *testing.T, Read func([]byte) (int, error)) {
94 n, err := Read(make([]byte, 0))
95 if n != 0 || err != nil {
96 t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err)
97 }
98 n, err = Read(nil)
99 if n != 0 || err != nil {
100 t.Fatalf("Read(nil) = %d, %v", n, err)
101 }
102 }
103
104 type readerFunc func([]byte) (int, error)
105
106 func (f readerFunc) Read(b []byte) (int, error) {
107 return f(b)
108 }
109
110 func TestReadUsesReader(t *testing.T) {
111 var called bool
112 defer func(r io.Reader) { Reader = r }(Reader)
113 Reader = readerFunc(func(b []byte) (int, error) {
114 called = true
115 return len(b), nil
116 })
117 n, err := Read(make([]byte, 32))
118 if n != 32 || err != nil {
119 t.Fatalf("Read(make([]byte, 32)) = %d, %v", n, err)
120 }
121 if !called {
122 t.Error("Read did not use Reader")
123 }
124 }
125
126 func TestConcurrentRead(t *testing.T) {
127 testReadAndReader(t, testConcurrentRead)
128 }
129
130 func testConcurrentRead(t *testing.T, Read func([]byte) (int, error)) {
131 if testing.Short() {
132 t.Skip("skipping in short mode")
133 }
134 const N = 100
135 const M = 1000
136 var wg sync.WaitGroup
137 wg.Add(N)
138 for i := 0; i < N; i++ {
139 go func() {
140 defer wg.Done()
141 for i := 0; i < M; i++ {
142 b := make([]byte, 32)
143 n, err := Read(b)
144 if n != 32 || err != nil {
145 t.Errorf("Read = %d, %v", n, err)
146 }
147 }
148 }()
149 }
150 wg.Wait()
151 }
152
153 var sink byte
154
155 func TestAllocations(t *testing.T) {
156 if boring.Enabled {
157
158 t.Skip("boringcrypto allocates")
159 }
160 if race.Enabled || msan.Enabled || asan.Enabled {
161 t.Skip("urandomRead allocates under -race, -asan, and -msan")
162 }
163 if runtime.GOOS == "plan9" {
164 t.Skip("plan9 allocates")
165 }
166 testenv.SkipIfOptimizationOff(t)
167
168 n := int(testing.AllocsPerRun(10, func() {
169 buf := make([]byte, 32)
170 Read(buf)
171 sink ^= buf[0]
172 }))
173 if n > 0 {
174 t.Errorf("allocs = %d, want 0", n)
175 }
176 }
177
178
179
180 func TestNoUrandomFallback(t *testing.T) {
181 expectFallback := false
182 if runtime.GOOS == "aix" {
183
184 expectFallback = true
185 }
186 if os.Getenv("GO_GETRANDOM_DISABLED") == "1" {
187
188 expectFallback = true
189 }
190 Read(make([]byte, 1))
191 if urandomFile != nil && !expectFallback {
192 t.Error("/dev/urandom fallback used unexpectedly")
193 t.Log("note: if this test fails, it may be because the system does not have getrandom(2)")
194 }
195 if urandomFile == nil && expectFallback {
196 t.Error("/dev/urandom fallback not used as expected")
197 }
198 }
199
200 func TestReadError(t *testing.T) {
201 if testing.Short() {
202 t.Skip("skipping test in short mode")
203 }
204 testenv.MustHaveExec(t)
205
206
207 if os.Getenv("GO_TEST_READ_ERROR") == "1" {
208 defer func(r io.Reader) { Reader = r }(Reader)
209 Reader = readerFunc(func([]byte) (int, error) {
210 return 0, errors.New("error")
211 })
212 if _, err := Read(make([]byte, 32)); err == nil {
213 t.Error("Read did not return error")
214 }
215 return
216 }
217
218 cmd := testenv.Command(t, os.Args[0], "-test.run=TestReadError")
219 cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1")
220 out, err := cmd.CombinedOutput()
221 if err == nil {
222 t.Error("subprocess succeeded unexpectedly")
223 }
224 exp := "fatal error: crypto/rand: failed to read random data"
225 if !bytes.Contains(out, []byte(exp)) {
226 t.Errorf("subprocess output does not contain %q: %s", exp, out)
227 }
228 }
229
230 func BenchmarkRead(b *testing.B) {
231 b.Run("4", func(b *testing.B) {
232 benchmarkRead(b, 4)
233 })
234 b.Run("32", func(b *testing.B) {
235 benchmarkRead(b, 32)
236 })
237 b.Run("4K", func(b *testing.B) {
238 benchmarkRead(b, 4<<10)
239 })
240 }
241
242 func benchmarkRead(b *testing.B, size int) {
243 b.SetBytes(int64(size))
244 buf := make([]byte, size)
245 for i := 0; i < b.N; i++ {
246 if _, err := Read(buf); err != nil {
247 b.Fatal(err)
248 }
249 }
250 }
251
View as plain text