blob: e505e016dc8f238115785c99ddfe1eeca4a4a00f [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 clock
import (
"net"
"testing"
"time"
)
func TestWithMockNtpForErr(t *testing.T) {
sysClock := MockSystemClock(time.Now(), 0)
stAdapter := MockStorageAdapter()
ntpSource := MockNtpSource()
ntpSource.Err = net.UnknownNetworkError("network err")
vclock := NewVClockWithMockServices(stAdapter, sysClock, ntpSource)
if err := vclock.runNtpCheck(nil); err == nil {
t.Error("Network error expected but not found")
}
if stAdapter.clockData != nil {
t.Error("Non-nil clock data found.")
}
}
func TestWithMockNtpForDiffBelowThreshold(t *testing.T) {
sysClock := MockSystemClock(time.Now(), 0) // not used
stAdapter := MockStorageAdapter()
originalData := NewClockData(0)
stAdapter.SetClockData(nil, &originalData)
ntpSource := MockNtpSource()
offset := 1800 * time.Millisecond // error threshold is 2 seconds
ntpSource.Data = &NtpData{offset: offset, delay: 5 * time.Millisecond}
vclock := NewVClockWithMockServices(stAdapter, sysClock, ntpSource)
if err := vclock.runNtpCheck(nil); err != nil {
t.Errorf("Unexpected err: %v", err)
}
if isClockDataChanged(stAdapter, &originalData) {
t.Error("ClockData expected to be unchanged but found updated")
}
}
func TestWithMockNtpForDiffAboveThreshold(t *testing.T) {
sysTs := time.Now()
elapsedTime := 10 * time.Minute
sysClock := MockSystemClock(sysTs, elapsedTime)
stAdapter := MockStorageAdapter()
originalData := NewClockData(0)
stAdapter.SetClockData(nil, &originalData)
ntpSource := MockNtpSource()
skew := 2100 * time.Millisecond // error threshold is 2 seconds
ntpSource.Data = &NtpData{offset: skew, delay: 5 * time.Millisecond}
vclock := NewVClockWithMockServices(stAdapter, sysClock, ntpSource)
if err := vclock.runNtpCheck(nil); err != nil {
t.Errorf("Unexpected err: %v", err)
}
if !isClockDataChanged(stAdapter, &originalData) {
t.Error("ClockData expected to be updated but found unchanged")
}
expectedBootTime := sysTs.Add(-elapsedTime).UnixNano()
if stAdapter.clockData.Skew != skew.Nanoseconds() {
t.Errorf("Skew expected to be %d but found %d",
skew.Nanoseconds(), stAdapter.clockData.Skew)
}
if stAdapter.clockData.ElapsedTimeSinceBoot != elapsedTime.Nanoseconds() {
t.Errorf("ElapsedTime expected to be %d but found %d",
elapsedTime.Nanoseconds(), stAdapter.clockData.ElapsedTimeSinceBoot)
}
if stAdapter.clockData.SystemTimeAtBoot != expectedBootTime {
t.Errorf("Skew expected to be %d but found %d",
expectedBootTime, stAdapter.clockData.SystemTimeAtBoot)
}
}
func TestWithMockNtpForDiffBelowThresholdAndExistingLargeSkew(t *testing.T) {
sysTs := time.Now()
elapsedTime := 10 * time.Minute
sysClock := MockSystemClock(sysTs, elapsedTime)
stAdapter := MockStorageAdapter()
originalData := NewClockData(2300 * time.Millisecond.Nanoseconds()) // large skew
stAdapter.SetClockData(nil, &originalData)
ntpSource := MockNtpSource()
skew := 200 * time.Millisecond // error threshold is 2 seconds
ntpSource.Data = &NtpData{offset: skew, delay: 5 * time.Millisecond}
vclock := NewVClockWithMockServices(stAdapter, sysClock, ntpSource)
if err := vclock.runNtpCheck(nil); err != nil {
t.Errorf("Unexpected err: %v", err)
}
if !isClockDataChanged(stAdapter, &originalData) {
t.Error("ClockData expected to be updated but found unchanged")
}
expectedBootTime := sysTs.Add(-elapsedTime).UnixNano()
if stAdapter.clockData.Skew != skew.Nanoseconds() {
t.Errorf("Skew expected to be %d but found %d",
skew.Nanoseconds(), stAdapter.clockData.Skew)
}
if stAdapter.clockData.ElapsedTimeSinceBoot != elapsedTime.Nanoseconds() {
t.Errorf("ElapsedTime expected to be %d but found %d",
elapsedTime.Nanoseconds(), stAdapter.clockData.ElapsedTimeSinceBoot)
}
if stAdapter.clockData.SystemTimeAtBoot != expectedBootTime {
t.Errorf("Skew expected to be %d but found %d",
expectedBootTime, stAdapter.clockData.SystemTimeAtBoot)
}
}
func TestWithMockNtpForDiffBelowThresholdWithNoStoredClockData(t *testing.T) {
sysTs := time.Now()
elapsedTime := 10 * time.Minute
sysClock := MockSystemClock(sysTs, elapsedTime)
stAdapter := MockStorageAdapter() // no skew data stored
ntpSource := MockNtpSource()
skew := 200 * time.Millisecond // error threshold is 2 seconds
ntpSource.Data = &NtpData{offset: skew, delay: 5 * time.Millisecond}
vclock := NewVClockWithMockServices(stAdapter, sysClock, ntpSource)
if err := vclock.runNtpCheck(nil); err != nil {
t.Errorf("Unexpected err: %v", err)
}
if !isClockDataChanged(stAdapter, nil) {
t.Error("ClockData expected to be updated but found unchanged")
}
expectedBootTime := sysTs.Add(-elapsedTime).UnixNano()
if stAdapter.clockData.Skew != skew.Nanoseconds() {
t.Errorf("Skew expected to be %d but found %d",
skew.Nanoseconds(), stAdapter.clockData.Skew)
}
if stAdapter.clockData.ElapsedTimeSinceBoot != elapsedTime.Nanoseconds() {
t.Errorf("ElapsedTime expected to be %d but found %d",
elapsedTime.Nanoseconds(), stAdapter.clockData.ElapsedTimeSinceBoot)
}
if stAdapter.clockData.SystemTimeAtBoot != expectedBootTime {
t.Errorf("Skew expected to be %d but found %d",
expectedBootTime, stAdapter.clockData.SystemTimeAtBoot)
}
}
/*
Following two tests are commented out as they hit the real NTP servers
and can resut into being flaky if the clock of the machine running continuous
test has a skew more than 2 seconds.
func TestWithRealNtp(t *testing.T) {
stAdapter := MockStorageAdapter()
originalData := NewClockData(100 * time.Millisecond.Nanoseconds()) // small skew
stAdapter.SetClockData(nil, &originalData)
vclock := NewVClockWithMockServices(stAdapter, nil, nil)
if err := vclock.runNtpCheck(nil); err != nil {
t.Errorf("Unexpected err: %v", err)
}
if isClockDataChanged(stAdapter, &originalData) {
t.Error("ClockData expected to be unchanged but found updated")
}
}
func TestWithRealNtpForNoClockData(t *testing.T) {
stAdapter := MockStorageAdapter()
vclock := NewVClockWithMockServices(stAdapter, nil, nil)
if err := vclock.runNtpCheck(nil); err != nil {
t.Errorf("Unexpected err: %v", err)
}
if !isClockDataChanged(stAdapter, nil) {
t.Error("ClockData expected to be updated but found unchanged")
}
}
*/
func NewClockData(skew int64) ClockData {
return ClockData{
SystemTimeAtBoot: 0,
Skew: skew,
ElapsedTimeSinceBoot: 0,
}
}
func isClockDataChanged(stAdapter *storageAdapterMockImpl, originalData *ClockData) bool {
return stAdapter.clockData != originalData // check for same pointer
}