common: use genius simplification of tests from @ebuchman

Massive test simplication for more reliable tests from @ebuchman
This commit is contained in:
Emmanuel Odeke 2017-12-15 02:14:05 -07:00
parent b5f465b4ec
commit cdc7988823
No known key found for this signature in database
GPG Key ID: 1CA47A292F89DD40
2 changed files with 45 additions and 74 deletions

View File

@ -18,14 +18,20 @@ var prng struct {
*mrand.Rand *mrand.Rand
} }
func init() { func reset() {
b := cRandBytes(8) b := cRandBytes(8)
var seed uint64 var seed uint64
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
seed |= uint64(b[i]) seed |= uint64(b[i])
seed <<= 8 seed <<= 8
} }
prng.Lock()
prng.Rand = mrand.New(mrand.NewSource(int64(seed))) prng.Rand = mrand.New(mrand.NewSource(int64(seed)))
prng.Unlock()
}
func init() {
reset()
} }
// Constructs an alphanumeric string of given length. // Constructs an alphanumeric string of given length.

View File

@ -1,34 +1,34 @@
package common_test package common
import ( import (
"io/ioutil" "bytes"
"os" "encoding/json"
"os/exec" "fmt"
"path/filepath" "io"
mrand "math/rand"
"sync" "sync"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tendermint/tmlibs/common"
) )
func TestRandStr(t *testing.T) { func TestRandStr(t *testing.T) {
l := 243 l := 243
s := common.RandStr(l) s := RandStr(l)
assert.Equal(t, l, len(s)) assert.Equal(t, l, len(s))
} }
func TestRandBytes(t *testing.T) { func TestRandBytes(t *testing.T) {
l := 243 l := 243
b := common.RandBytes(l) b := RandBytes(l)
assert.Equal(t, l, len(b)) assert.Equal(t, l, len(b))
} }
func TestRandIntn(t *testing.T) { func TestRandIntn(t *testing.T) {
n := 243 n := 243
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
x := common.RandIntn(n) x := RandIntn(n)
assert.True(t, x < n) assert.True(t, x < n)
} }
} }
@ -39,39 +39,12 @@ func TestRandIntn(t *testing.T) {
// * https://github.com/tendermint/tmlibs/issues/99 // * https://github.com/tendermint/tmlibs/issues/99
// * https://github.com/tendermint/tendermint/issues/973 // * https://github.com/tendermint/tendermint/issues/973
func TestUniqueRng(t *testing.T) { func TestUniqueRng(t *testing.T) {
if os.Getenv("TENDERMINT_INTEGRATION_TESTS") == "" { buf := new(bytes.Buffer)
t.Skipf("Can only be run as an integration test")
}
// The goal of this test is to invoke the
// Rand* tests externally with no repeating results, booted up.
// Any repeated results indicate that the seed is the same or that
// perhaps we are using math/rand directly.
tmpDir, err := ioutil.TempDir("", "rng-tests")
if err != nil {
t.Fatalf("Creating tempDir: %v", err)
}
defer os.RemoveAll(tmpDir)
outpath := filepath.Join(tmpDir, "main.go")
f, err := os.Create(outpath)
if err != nil {
t.Fatalf("Setting up %q err: %v", outpath, err)
}
f.Write([]byte(integrationTestProgram))
if err := f.Close(); err != nil {
t.Fatalf("Closing: %v", err)
}
outputs := make(map[string][]int) outputs := make(map[string][]int)
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
cmd := exec.Command("go", "run", outpath) testThemAll(buf)
bOutput, err := cmd.CombinedOutput() output := buf.String()
if err != nil { buf.Reset()
t.Errorf("Run #%d: err: %v output: %s", i, err, bOutput)
continue
}
output := string(bOutput)
runs, seen := outputs[output] runs, seen := outputs[output]
if seen { if seen {
t.Errorf("Run #%d's output was already seen in previous runs: %v", i, runs) t.Errorf("Run #%d's output was already seen in previous runs: %v", i, runs)
@ -80,38 +53,30 @@ func TestUniqueRng(t *testing.T) {
} }
} }
const integrationTestProgram = ` func testThemAll(out io.Writer) {
package main // Reset the internal PRNG
reset()
import (
"encoding/json"
"fmt"
"math/rand"
"github.com/tendermint/tmlibs/common"
)
func main() {
// Set math/rand's Seed so that any direct invocations // Set math/rand's Seed so that any direct invocations
// of math/rand will reveal themselves. // of math/rand will reveal themselves.
rand.Seed(1) mrand.Seed(1)
perm := common.RandPerm(10) perm := RandPerm(10)
blob, _ := json.Marshal(perm) blob, _ := json.Marshal(perm)
fmt.Printf("perm: %s\n", blob) fmt.Fprintf(out, "perm: %s\n", blob)
fmt.Printf("randInt: %d\n", common.RandInt()) fmt.Fprintf(out, "randInt: %d\n", RandInt())
fmt.Printf("randUint: %d\n", common.RandUint()) fmt.Fprintf(out, "randUint: %d\n", RandUint())
fmt.Printf("randIntn: %d\n", common.RandIntn(97)) fmt.Fprintf(out, "randIntn: %d\n", RandIntn(97))
fmt.Printf("randInt31: %d\n", common.RandInt31()) fmt.Fprintf(out, "randInt31: %d\n", RandInt31())
fmt.Printf("randInt32: %d\n", common.RandInt32()) fmt.Fprintf(out, "randInt32: %d\n", RandInt32())
fmt.Printf("randInt63: %d\n", common.RandInt63()) fmt.Fprintf(out, "randInt63: %d\n", RandInt63())
fmt.Printf("randInt64: %d\n", common.RandInt64()) fmt.Fprintf(out, "randInt64: %d\n", RandInt64())
fmt.Printf("randUint32: %d\n", common.RandUint32()) fmt.Fprintf(out, "randUint32: %d\n", RandUint32())
fmt.Printf("randUint64: %d\n", common.RandUint64()) fmt.Fprintf(out, "randUint64: %d\n", RandUint64())
fmt.Printf("randUint16Exp: %d\n", common.RandUint16Exp()) fmt.Fprintf(out, "randUint16Exp: %d\n", RandUint16Exp())
fmt.Printf("randUint32Exp: %d\n", common.RandUint32Exp()) fmt.Fprintf(out, "randUint32Exp: %d\n", RandUint32Exp())
fmt.Printf("randUint64Exp: %d\n", common.RandUint64Exp()) fmt.Fprintf(out, "randUint64Exp: %d\n", RandUint64Exp())
}` }
func TestRngConcurrencySafety(t *testing.T) { func TestRngConcurrencySafety(t *testing.T) {
var wg sync.WaitGroup var wg sync.WaitGroup
@ -120,9 +85,9 @@ func TestRngConcurrencySafety(t *testing.T) {
go func() { go func() {
defer wg.Done() defer wg.Done()
_ = common.RandUint64() _ = RandUint64()
<-time.After(time.Millisecond * time.Duration(common.RandIntn(100))) <-time.After(time.Millisecond * time.Duration(RandIntn(100)))
_ = common.RandPerm(3) _ = RandPerm(3)
}() }()
} }
wg.Wait() wg.Wait()