Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>main
parent
a905ce5607
commit
9f1b02699a
@ -0,0 +1,44 @@ |
||||
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package tstime |
||||
|
||||
import ( |
||||
crand "crypto/rand" |
||||
"encoding/binary" |
||||
"math/rand" |
||||
"sync" |
||||
"time" |
||||
) |
||||
|
||||
// crandSource is a rand.Source64 that gets its numbers from
|
||||
// crypto/rand.Reader.
|
||||
type crandSource struct{ sync.Mutex } |
||||
|
||||
var _ rand.Source64 = (*crandSource)(nil) |
||||
|
||||
func (s *crandSource) Int63() int64 { return int64(s.Uint64() >> 1) } |
||||
|
||||
func (s *crandSource) Uint64() uint64 { |
||||
s.Lock() |
||||
defer s.Unlock() |
||||
var buf [8]byte |
||||
crand.Read(buf[:]) |
||||
return binary.BigEndian.Uint64(buf[:]) |
||||
} |
||||
|
||||
func (*crandSource) Seed(seed int64) {} // nope
|
||||
|
||||
var durRand = rand.New(new(crandSource)) |
||||
|
||||
// RandomDurationBetween returns a random duration in range [min,max).
|
||||
// If panics if max < min.
|
||||
func RandomDurationBetween(min, max time.Duration) time.Duration { |
||||
diff := max - min |
||||
if diff == 0 { |
||||
return min |
||||
} |
||||
ns := durRand.Int63n(int64(diff)) |
||||
return min + time.Duration(ns) |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package tstime |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
) |
||||
|
||||
func TestRandomDurationBetween(t *testing.T) { |
||||
if got := RandomDurationBetween(1, 1); got != 1 { |
||||
t.Errorf("between 1 and 1 = %v; want 1", int64(got)) |
||||
} |
||||
const min = 1 * time.Second |
||||
const max = 10 * time.Second |
||||
for i := 0; i < 500; i++ { |
||||
if got := RandomDurationBetween(min, max); got < min || got >= max { |
||||
t.Fatalf("%v (%d) out of range", got, got) |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue