tai64n: make the test deterministic

In the presence of preemption, the current test may fail transiently.
This uses static test data instead to ensure consistent behavior.

Signed-off-by: Dmytro Shynkevych <dmytro@tailscale.com>
This commit is contained in:
Dmytro Shynkevych 2020-05-05 18:37:54 -04:00 committed by David Crawshaw
parent da9d300cf8
commit f60b3919be
2 changed files with 32 additions and 19 deletions

View File

@ -17,16 +17,19 @@ const whitenerMask = uint32(0x1000000 - 1)
type Timestamp [TimestampSize]byte
func Now() Timestamp {
func stamp(t time.Time) Timestamp {
var tai64n Timestamp
now := time.Now()
secs := base + uint64(now.Unix())
nano := uint32(now.Nanosecond()) &^ whitenerMask
secs := base + uint64(t.Unix())
nano := uint32(t.Nanosecond()) &^ whitenerMask
binary.BigEndian.PutUint64(tai64n[:], secs)
binary.BigEndian.PutUint32(tai64n[8:], nano)
return tai64n
}
func Now() Timestamp {
return stamp(time.Now())
}
func (t1 Timestamp) After(t2 Timestamp) bool {
return bytes.Compare(t1[:], t2[:]) > 0
}

View File

@ -10,21 +10,31 @@ import (
"time"
)
/* Testing the essential property of the timestamp
* as used by WireGuard.
*/
// Test that timestamps are monotonic as required by Wireguard and that
// nanosecond-level information is whitened to prevent side channel attacks.
func TestMonotonic(t *testing.T) {
old := Now()
for i := 0; i < 50; i++ {
next := Now()
if next.After(old) {
t.Error("Whitening insufficient")
}
time.Sleep(time.Duration(whitenerMask)/time.Nanosecond + 1)
next = Now()
if !next.After(old) {
t.Error("Not monotonically increasing on whitened nano-second scale")
}
old = next
startTime := time.Unix(0, 123456789) // a nontrivial bit pattern
// Whitening should reduce timestamp granularity
// to more than 10 but fewer than 20 milliseconds.
tests := []struct {
name string
t1, t2 time.Time
wantAfter bool
}{
{"after_10_ns", startTime, startTime.Add(10 * time.Nanosecond), false},
{"after_10_us", startTime, startTime.Add(10 * time.Microsecond), false},
{"after_1_ms", startTime, startTime.Add(time.Millisecond), false},
{"after_10_ms", startTime, startTime.Add(10 * time.Millisecond), false},
{"after_20_ms", startTime, startTime.Add(20 * time.Millisecond), true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts1, ts2 := stamp(tt.t1), stamp(tt.t2)
got := ts2.After(ts1)
if got != tt.wantAfter {
t.Errorf("after = %v; want %v", got, tt.wantAfter)
}
})
}
}