blob: 54f3aa839b6a6b6a016b14af31499ec238e3fdf3 [file] [log] [blame]
// Copyright 2015 The Vanadium 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 vclock
import (
"testing"
"time"
)
// ** Test Setup **
// Local: no NTP info
// Remote: no NTP info
// Result: VClock not synced
func TestVClockCheckLocalVClock1(t *testing.T) {
localSkew := 3 * time.Second
data := newSyncVClockData(localSkew, time.Time{}, 0, 0)
remoteDelta := 5 * time.Second
psd := newPeerSyncData(remoteDelta, time.Time{}, 0, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err == nil {
t.Errorf("expected no update, got %v", *newData)
}
}
// ** Test Setup **
// Local: no NTP info
// Remote: has NTP info with acceptable {numReboots, numHops}
// Result: VClock synced
func TestVClockCheckLocalVClock2(t *testing.T) {
localSkew := 3 * time.Second
data := newSyncVClockData(localSkew, time.Time{}, 0, 0)
remoteDelta := 5 * time.Second
remoteNtpTs := time.Now().Add(-30 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 0, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err != nil {
t.Errorf("expected update, got err: %v", err)
} else {
checkEqSubsetOfVClockData(t, *newData, *newSyncVClockData(remoteDelta+localSkew, remoteNtpTs, 0, 1))
}
}
// ** Test Setup **
// Local: has with NTP info
// Remote: no NTP info
// Result: VClock not synced
func TestVClockCheckLocalVClock3(t *testing.T) {
localSkew := 3 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 0, 0)
remoteDelta := 5 * time.Second
psd := newPeerSyncData(remoteDelta, time.Time{}, 0, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err == nil {
t.Errorf("expected no update, got %v", *newData)
}
}
// ** Test Setup **
// Local & Remote have NTP info.
// LocalNtp > RemoteNtp, acceptable values for {reboot,hop}
// Result: VClock not synced
func TestVClockCheckLocalVClock4(t *testing.T) {
localSkew := 3 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 1, 1)
remoteDelta := 5 * time.Second
remoteNtpTs := localNtpTs.Add(-10 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 0, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err == nil {
t.Errorf("expected no update, got %v", *newData)
}
}
// ** Test Setup **
// Local & Remote have NTP info.
// LocalNtp < RemoteNtp, Remote-numReboots = 0, Remote-numHops = 1
// Result: VClock synced, skew = oldSkew + offset, numReboots = 0, numHops = 2
func TestVClockCheckLocalVClock5(t *testing.T) {
localSkew := 5 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 0, 0)
remoteDelta := 8 * time.Second
remoteNtpTs := localNtpTs.Add(10 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 0, 1)
if newData, err := maybeUpdateFromPeerData(data, psd); err != nil {
t.Errorf("expected update, got err: %v", err)
} else {
checkEqSubsetOfVClockData(t, *newData, *newSyncVClockData(remoteDelta+localSkew, remoteNtpTs, 0, 2))
}
}
// ** Test Setup **
// Local & Remote have NTP info.
// LocalNtp < RemoteNtp, unacceptable value for numHops
// Result: VClock not synced
func TestVClockCheckLocalVClock6(t *testing.T) {
localSkew := 3 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 1, 1)
remoteDelta := 5 * time.Second
remoteNtpTs := localNtpTs.Add(10 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 0, 2)
if newData, err := maybeUpdateFromPeerData(data, psd); err == nil {
t.Errorf("expected no update, got %v", *newData)
}
}
// ** Test Setup **
// Local & Remote have NTP info.
// LocalNtp < RemoteNtp, Remote-numReboots > 0 but Diff between two vclocks < 1
// minute
// Result: VClock synced, skew = oldSkew + offset,
// numReboots = Remote-numReboots+1, numHops = 1
func TestVClockCheckLocalVClock7(t *testing.T) {
localSkew := 3 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 0, 0)
remoteDelta := 5 * time.Second
remoteNtpTs := localNtpTs.Add(10 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 3, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err != nil {
t.Errorf("expected update, got err: %v", err)
} else {
checkEqSubsetOfVClockData(t, *newData, *newSyncVClockData(remoteDelta+localSkew, remoteNtpTs, 3, 1))
}
}
// ** Test Setup **
// Local & Remote have NTP info.
// LocalNtp < RemoteNtp, Remote-numReboots > 0 and difference between two
// vclocks > 1 minute
// Result: VClock not synced
func TestVClockCheckLocalVClock8(t *testing.T) {
localSkew := 3 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 0, 0)
remoteDelta := 5 * time.Hour
remoteNtpTs := localNtpTs.Add(10 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 3, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err == nil {
t.Errorf("expected no update, got %v", *newData)
}
}
// ** Test Setup **
// Local & Remote have NTP info.
// LocalNtp < RemoteNtp, but the difference between the two vclocks is too small
// Result: VClock not synced
func TestVClockCheckLocalVClock9(t *testing.T) {
localSkew := 3 * time.Second
localNtpTs := time.Now().Add(-30 * time.Minute)
data := newSyncVClockData(localSkew, localNtpTs, 1, 1)
remoteDelta := 1 * time.Second
remoteNtpTs := localNtpTs.Add(10 * time.Minute)
psd := newPeerSyncData(remoteDelta, remoteNtpTs, 0, 0)
if newData, err := maybeUpdateFromPeerData(data, psd); err == nil {
t.Errorf("expected no update, got %v", *newData)
}
}
////////////////////////////////////////////////////////////////////////////////
// Helper functions
func maybeUpdateFromPeerData(data *VClockData, psd *PeerSyncData) (*VClockData, error) {
return MaybeUpdateFromPeerData(NewVClockForTests(nil), data, psd)
}
func toRemoteTime(t time.Time, remoteDelta time.Duration) time.Time {
return t.Add(remoteDelta)
}
func toLocalTime(t time.Time, remoteDelta time.Duration) time.Time {
return t.Add(-remoteDelta)
}
func newPeerSyncData(remoteDelta time.Duration, lastNtpTs time.Time, numReboots, numHops uint16) *PeerSyncData {
oTs := time.Now()
rTs := toRemoteTime(oTs.Add(time.Second), remoteDelta)
sTs := rTs.Add(time.Millisecond)
clientRecvTs := toLocalTime(sTs, remoteDelta).Add(time.Second)
return &PeerSyncData{
MySendTs: oTs,
RecvTs: rTs,
SendTs: sTs,
MyRecvTs: clientRecvTs,
LastNtpTs: lastNtpTs,
NumReboots: numReboots,
NumHops: numHops,
}
}
func newSyncVClockData(skew time.Duration, lastNtpTs time.Time, numReboots, numHops uint16) *VClockData {
return newVClockData(time.Time{}, skew, 0, lastNtpTs, numReboots, numHops)
}