// 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)
	}
}
