veyron/lib/testutil: Make the source of randomness thread-safe.
This fixes a bunch of races observed in the continuous build with "go test
-race", introduced in
https://veyron-review.googlesource.com/#/q/Ie7e0f1622c64a11fb787d95e30b62c9f264f110d
That said, I'm not sure whether it is better to make testutil.Rand
"thread-safe", or is it better to avoid locks there and have clients that need
safety implement their own locks. Will leave that call up to the reviewer.
Change-Id: I4dfbd11e6ab7e4f25c9b79364145f552a37d9286
diff --git a/lib/testutil/init.go b/lib/testutil/init.go
index 8ba55c7..188291c 100644
--- a/lib/testutil/init.go
+++ b/lib/testutil/init.go
@@ -11,6 +11,7 @@
"os"
"runtime"
"strconv"
+ "sync"
// Need to import all of the packages that could possibly
// define flags that we care about. In practice, this is the
// flags defined by the testing package, the logging library
@@ -28,8 +29,35 @@
SeedEnv = "VEYRON_RNG_SEED"
)
+// Random is a concurrent-access friendly source of randomness.
+type Random struct {
+ mu sync.Mutex
+ rand *rand.Rand
+}
+
+// Int returns a non-negative pseudo-random int.
+func (r *Random) Int() int {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ return r.rand.Int()
+}
+
+// Intn returns a non-negative pseudo-random int in the range [0, n).
+func (r *Random) Intn(n int) int {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ return r.rand.Intn(n)
+}
+
+// Int63 returns a non-negative 63-bit pseudo-random integer as an int64.
+func (r *Random) Int63() int64 {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ return r.rand.Int63()
+}
+
var (
- Rand *rand.Rand
+ Rand *Random
)
func init() {
@@ -54,5 +82,5 @@
}
}
vlog.Infof("Seeding pseudo-random number generator with %v", seed)
- Rand = rand.New(rand.NewSource(seed))
+ Rand = &Random{rand: rand.New(rand.NewSource(seed))}
}