From 719c7b03ba5d8bdea937a6b21564fa82539d3661 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 31 Mar 2017 12:46:35 -0400 Subject: [PATCH] testing/quick: generate all possible int64, uint64 values MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When generating a random int8, uint8, int16, uint16, int32, uint32, quick.Value chooses among all possible values. But when generating a random int64 or uint64, it only chooses values in the range [-2⁶², 2⁶²) (even for uint64). It should, like for all the other integers, use the full range. If it had, this would have caught #19807 earlier. Instead it let us discover the presence of #19809. While we are here, also make the default source of randomness not completely deterministic. Fixes #19808. Change-Id: I070f852531c92b3670bd76523326c9132bfc9416 Reviewed-on: https://go-review.googlesource.com/39152 Run-TryBot: Russ Cox TryBot-Result: Gobot Gobot Reviewed-by: Rob Pike --- src/go/build/deps_test.go | 2 +- src/testing/quick/quick.go | 13 ++++++++++--- src/time/format_test.go | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 043f9f2832..53d129c23f 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -183,7 +183,7 @@ var pkgDeps = map[string][]string{ "testing": {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"}, "testing/iotest": {"L2", "log"}, - "testing/quick": {"L2", "flag", "fmt", "reflect"}, + "testing/quick": {"L2", "flag", "fmt", "reflect", "time"}, "internal/testenv": {"L2", "OS", "flag", "testing", "syscall"}, // L4 is defined as L3+fmt+log+time, because in general once diff --git a/src/testing/quick/quick.go b/src/testing/quick/quick.go index 95860fda0f..6415e50d65 100644 --- a/src/testing/quick/quick.go +++ b/src/testing/quick/quick.go @@ -14,6 +14,7 @@ import ( "math/rand" "reflect" "strings" + "time" ) var defaultMaxCount *int = flag.Int("quickchecks", 100, "The default number of iterations for each check") @@ -43,8 +44,14 @@ func randFloat64(rand *rand.Rand) float64 { return f } -// randInt64 returns a random integer taking half the range of an int64. -func randInt64(rand *rand.Rand) int64 { return rand.Int63() - 1<<62 } +// randInt64 returns a random int64. +func randInt64(rand *rand.Rand) int64 { + x := rand.Int63() - 1<<62 + // x in [-2⁶²,2⁶²), so top two bits are 00 or 11, never 10 or 01. + // Mix in some bits from the middle. + x ^= x<<29 ^ x<<43 + return x +} // complexSize is the maximum length of arbitrary values that contain other // values. @@ -193,7 +200,7 @@ var defaultConfig Config // getRand returns the *rand.Rand to use for a given Config. func (c *Config) getRand() *rand.Rand { if c.Rand == nil { - return rand.New(rand.NewSource(0)) + return rand.New(rand.NewSource(time.Now().UnixNano())) } return c.Rand } diff --git a/src/time/format_test.go b/src/time/format_test.go index d0013bc3e3..710de594a0 100644 --- a/src/time/format_test.go +++ b/src/time/format_test.go @@ -378,8 +378,8 @@ func checkTime(time Time, test *ParseTest, t *testing.T) { func TestFormatAndParse(t *testing.T) { const fmt = "Mon MST " + RFC3339 // all fields f := func(sec int64) bool { - t1 := Unix(sec, 0) - if t1.Year() < 1000 || t1.Year() > 9999 { + t1 := Unix(sec/2, 0) + if t1.Year() < 1000 || t1.Year() > 9999 || t1.Unix() != sec { // not required to work return true } -- 2.48.1