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 "errors"
12 "internal/testenv"
13 "io"
14 "os"
15 "sync"
16 "testing"
17 )
18
19
20
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 cryptotest.SkipTestAllocations(t)
157 n := int(testing.AllocsPerRun(10, func() {
158 buf := make([]byte, 32)
159 Read(buf)
160 sink ^= buf[0]
161 }))
162 if n > 0 {
163 t.Errorf("allocs = %d, want 0", n)
164 }
165 }
166
167 func TestReadError(t *testing.T) {
168 if testing.Short() {
169 t.Skip("skipping test in short mode")
170 }
171 testenv.MustHaveExec(t)
172
173
174 if os.Getenv("GO_TEST_READ_ERROR") == "1" {
175 defer func(r io.Reader) { Reader = r }(Reader)
176 Reader = readerFunc(func([]byte) (int, error) {
177 return 0, errors.New("error")
178 })
179 Read(make([]byte, 32))
180 t.Error("Read did not crash")
181 return
182 }
183
184 cmd := testenv.Command(t, os.Args[0], "-test.run=TestReadError")
185 cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1")
186 out, err := cmd.CombinedOutput()
187 if err == nil {
188 t.Error("subprocess succeeded unexpectedly")
189 }
190 exp := "fatal error: crypto/rand: failed to read random data"
191 if !bytes.Contains(out, []byte(exp)) {
192 t.Errorf("subprocess output does not contain %q: %s", exp, out)
193 }
194 }
195
196 func BenchmarkRead(b *testing.B) {
197 b.Run("4", func(b *testing.B) {
198 benchmarkRead(b, 4)
199 })
200 b.Run("32", func(b *testing.B) {
201 benchmarkRead(b, 32)
202 })
203 b.Run("4K", func(b *testing.B) {
204 benchmarkRead(b, 4<<10)
205 })
206 }
207
208 func benchmarkRead(b *testing.B, size int) {
209 b.SetBytes(int64(size))
210 buf := make([]byte, size)
211 for i := 0; i < b.N; i++ {
212 if _, err := Read(buf); err != nil {
213 b.Fatal(err)
214 }
215 }
216 }
217
View as plain text