From cdc798882326a722040706a87ec0397e7c91d517 Mon Sep 17 00:00:00 2001 From: Emmanuel Odeke Date: Fri, 15 Dec 2017 02:14:05 -0700 Subject: [PATCH] common: use genius simplification of tests from @ebuchman Massive test simplication for more reliable tests from @ebuchman --- common/random.go | 8 ++- common/random_test.go | 111 +++++++++++++++--------------------------- 2 files changed, 45 insertions(+), 74 deletions(-) diff --git a/common/random.go b/common/random.go index b8304e89..37b8b277 100644 --- a/common/random.go +++ b/common/random.go @@ -18,14 +18,20 @@ var prng struct { *mrand.Rand } -func init() { +func reset() { b := cRandBytes(8) var seed uint64 for i := 0; i < 8; i++ { seed |= uint64(b[i]) seed <<= 8 } + prng.Lock() prng.Rand = mrand.New(mrand.NewSource(int64(seed))) + prng.Unlock() +} + +func init() { + reset() } // Constructs an alphanumeric string of given length. diff --git a/common/random_test.go b/common/random_test.go index 3fe0bbc0..bed8e765 100644 --- a/common/random_test.go +++ b/common/random_test.go @@ -1,34 +1,34 @@ -package common_test +package common import ( - "io/ioutil" - "os" - "os/exec" - "path/filepath" + "bytes" + "encoding/json" + "fmt" + "io" + mrand "math/rand" "sync" "testing" "time" "github.com/stretchr/testify/assert" - "github.com/tendermint/tmlibs/common" ) func TestRandStr(t *testing.T) { l := 243 - s := common.RandStr(l) + s := RandStr(l) assert.Equal(t, l, len(s)) } func TestRandBytes(t *testing.T) { l := 243 - b := common.RandBytes(l) + b := RandBytes(l) assert.Equal(t, l, len(b)) } func TestRandIntn(t *testing.T) { n := 243 for i := 0; i < 100; i++ { - x := common.RandIntn(n) + x := RandIntn(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/tendermint/issues/973 func TestUniqueRng(t *testing.T) { - if os.Getenv("TENDERMINT_INTEGRATION_TESTS") == "" { - 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) - } - + buf := new(bytes.Buffer) outputs := make(map[string][]int) for i := 0; i < 100; i++ { - cmd := exec.Command("go", "run", outpath) - bOutput, err := cmd.CombinedOutput() - if err != nil { - t.Errorf("Run #%d: err: %v output: %s", i, err, bOutput) - continue - } - output := string(bOutput) + testThemAll(buf) + output := buf.String() + buf.Reset() runs, seen := outputs[output] if seen { 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 = ` -package main +func testThemAll(out io.Writer) { + // Reset the internal PRNG + reset() -import ( - "encoding/json" - "fmt" - "math/rand" + // Set math/rand's Seed so that any direct invocations + // of math/rand will reveal themselves. + mrand.Seed(1) + perm := RandPerm(10) + blob, _ := json.Marshal(perm) + fmt.Fprintf(out, "perm: %s\n", blob) - "github.com/tendermint/tmlibs/common" -) - -func main() { - // Set math/rand's Seed so that any direct invocations - // of math/rand will reveal themselves. - rand.Seed(1) - perm := common.RandPerm(10) - blob, _ := json.Marshal(perm) - fmt.Printf("perm: %s\n", blob) - - fmt.Printf("randInt: %d\n", common.RandInt()) - fmt.Printf("randUint: %d\n", common.RandUint()) - fmt.Printf("randIntn: %d\n", common.RandIntn(97)) - fmt.Printf("randInt31: %d\n", common.RandInt31()) - fmt.Printf("randInt32: %d\n", common.RandInt32()) - fmt.Printf("randInt63: %d\n", common.RandInt63()) - fmt.Printf("randInt64: %d\n", common.RandInt64()) - fmt.Printf("randUint32: %d\n", common.RandUint32()) - fmt.Printf("randUint64: %d\n", common.RandUint64()) - fmt.Printf("randUint16Exp: %d\n", common.RandUint16Exp()) - fmt.Printf("randUint32Exp: %d\n", common.RandUint32Exp()) - fmt.Printf("randUint64Exp: %d\n", common.RandUint64Exp()) -}` + fmt.Fprintf(out, "randInt: %d\n", RandInt()) + fmt.Fprintf(out, "randUint: %d\n", RandUint()) + fmt.Fprintf(out, "randIntn: %d\n", RandIntn(97)) + fmt.Fprintf(out, "randInt31: %d\n", RandInt31()) + fmt.Fprintf(out, "randInt32: %d\n", RandInt32()) + fmt.Fprintf(out, "randInt63: %d\n", RandInt63()) + fmt.Fprintf(out, "randInt64: %d\n", RandInt64()) + fmt.Fprintf(out, "randUint32: %d\n", RandUint32()) + fmt.Fprintf(out, "randUint64: %d\n", RandUint64()) + fmt.Fprintf(out, "randUint16Exp: %d\n", RandUint16Exp()) + fmt.Fprintf(out, "randUint32Exp: %d\n", RandUint32Exp()) + fmt.Fprintf(out, "randUint64Exp: %d\n", RandUint64Exp()) +} func TestRngConcurrencySafety(t *testing.T) { var wg sync.WaitGroup @@ -120,9 +85,9 @@ func TestRngConcurrencySafety(t *testing.T) { go func() { defer wg.Done() - _ = common.RandUint64() - <-time.After(time.Millisecond * time.Duration(common.RandIntn(100))) - _ = common.RandPerm(3) + _ = RandUint64() + <-time.After(time.Millisecond * time.Duration(RandIntn(100))) + _ = RandPerm(3) }() } wg.Wait()