Source file src/crypto/rand/rand_test.go

     1  // Copyright 2010 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     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  // These tests are mostly duplicates of the tests in crypto/internal/sysrand,
    20  // and testing both the Reader and Read is pretty redundant when one calls the
    21  // other, but better safe than sorry.
    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  	// 40MiB, more than the documented maximum of 32Mi-1 on Linux 32-bit.
    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  	// We run this test in a subprocess because it's expected to crash.
   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