move the random number generator to the utils package

This commit is contained in:
Marten Seemann
2021-02-17 11:34:19 +08:00
parent c72f05aa41
commit 3c0726e132
3 changed files with 62 additions and 26 deletions

29
internal/utils/rand.go Normal file
View File

@@ -0,0 +1,29 @@
package utils
import (
"crypto/rand"
"encoding/binary"
)
// Rand is a wrapper around crypto/rand that adds some convenience functions known from math/rand.
type Rand struct {
buf [4]byte
}
func (r *Rand) Int31() int32 {
rand.Read(r.buf[:])
return int32(binary.BigEndian.Uint32(r.buf[:]) & ^uint32(1<<31))
}
// copied from the standard library math/rand implementation of Int63n
func (r *Rand) Int31n(n int32) int32 {
if n&(n-1) == 0 { // n is power of two, can mask
return r.Int31() & (n - 1)
}
max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
v := r.Int31()
for v > max {
v = r.Int31()
}
return v % n
}

View File

@@ -0,0 +1,32 @@
package utils
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Rand", func() {
It("generates random numbers", func() {
const (
num = 1000
max = 123456
)
var values [num]int32
var r Rand
for i := 0; i < num; i++ {
v := r.Int31n(max)
Expect(v).To(And(
BeNumerically(">=", 0),
BeNumerically("<", max),
))
values[i] = v
}
var sum uint64
for _, n := range values {
sum += uint64(n)
}
Expect(float64(sum) / num).To(BeNumerically("~", max/2, max/25))
})
})