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