mirror of https://github.com/tailscale/tailscale/
tstime: add RandomDurationBetween helper
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>pull/1186/head
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