| // Copyright 2013 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package rand_test |
| |
| import ( |
| "bytes" |
| "crypto/rand" |
| "fmt" |
| "io" |
| "math/big" |
| mathrand "math/rand" |
| "testing" |
| "time" |
| ) |
| |
| // https://golang.org/issue/6849. |
| func TestPrimeSmall(t *testing.T) { |
| for n := 2; n < 10; n++ { |
| p, err := rand.Prime(rand.Reader, n) |
| if err != nil { |
| t.Fatalf("Can't generate %d-bit prime: %v", n, err) |
| } |
| if p.BitLen() != n { |
| t.Fatalf("%v is not %d-bit", p, n) |
| } |
| if !p.ProbablyPrime(32) { |
| t.Fatalf("%v is not prime", p) |
| } |
| } |
| } |
| |
| // Test that passing bits < 2 causes Prime to return nil, error |
| func TestPrimeBitsLt2(t *testing.T) { |
| if p, err := rand.Prime(rand.Reader, 1); p != nil || err == nil { |
| t.Errorf("Prime should return nil, error when called with bits < 2") |
| } |
| } |
| |
| func TestInt(t *testing.T) { |
| // start at 128 so the case of (max.BitLen() % 8) == 0 is covered |
| for n := 128; n < 140; n++ { |
| b := new(big.Int).SetInt64(int64(n)) |
| if i, err := rand.Int(rand.Reader, b); err != nil { |
| t.Fatalf("Can't generate random value: %v, %v", i, err) |
| } |
| } |
| } |
| |
| type countingReader struct { |
| r io.Reader |
| n int |
| } |
| |
| func (r *countingReader) Read(p []byte) (n int, err error) { |
| n, err = r.r.Read(p) |
| r.n += n |
| return n, err |
| } |
| |
| // Test that Int reads only the necessary number of bytes from the reader for |
| // max at each bit length |
| func TestIntReads(t *testing.T) { |
| for i := 0; i < 32; i++ { |
| max := int64(1 << uint64(i)) |
| t.Run(fmt.Sprintf("max=%d", max), func(t *testing.T) { |
| reader := &countingReader{r: rand.Reader} |
| |
| _, err := rand.Int(reader, big.NewInt(max)) |
| if err != nil { |
| t.Fatalf("Can't generate random value: %d, %v", max, err) |
| } |
| expected := (i + 7) / 8 |
| if reader.n != expected { |
| t.Errorf("Int(reader, %d) should read %d bytes, but it read: %d", max, expected, reader.n) |
| } |
| }) |
| } |
| } |
| |
| // Test that Int does not mask out valid return values |
| func TestIntMask(t *testing.T) { |
| for max := 1; max <= 256; max++ { |
| t.Run(fmt.Sprintf("max=%d", max), func(t *testing.T) { |
| for i := 0; i < max; i++ { |
| var b bytes.Buffer |
| b.WriteByte(byte(i)) |
| n, err := rand.Int(&b, big.NewInt(int64(max))) |
| if err != nil { |
| t.Fatalf("Can't generate random value: %d, %v", max, err) |
| } |
| if n.Int64() != int64(i) { |
| t.Errorf("Int(reader, %d) should have returned value of %d, but it returned: %v", max, i, n) |
| } |
| } |
| }) |
| } |
| } |
| |
| func testIntPanics(t *testing.T, b *big.Int) { |
| defer func() { |
| if err := recover(); err == nil { |
| t.Errorf("Int should panic when called with max <= 0: %v", b) |
| } |
| }() |
| rand.Int(rand.Reader, b) |
| } |
| |
| // Test that passing a new big.Int as max causes Int to panic |
| func TestIntEmptyMaxPanics(t *testing.T) { |
| b := new(big.Int) |
| testIntPanics(t, b) |
| } |
| |
| // Test that passing a negative value as max causes Int to panic |
| func TestIntNegativeMaxPanics(t *testing.T) { |
| b := new(big.Int).SetInt64(int64(-1)) |
| testIntPanics(t, b) |
| } |
| |
| func BenchmarkPrime(b *testing.B) { |
| r := mathrand.New(mathrand.NewSource(time.Now().UnixNano())) |
| for i := 0; i < b.N; i++ { |
| rand.Prime(r, 1024) |
| } |
| } |