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