blob: 86650c1dc58eaa7c050abf4819298db28b9e981e [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 (
"testing"
"time"
)
const (
constElapsedTime int64 = 50
)
func TestWriteNewClockData(t *testing.T) {
sysTs := time.Now()
sysClock := MockSystemClock(sysTs, time.Duration(constElapsedTime))
stAdapter := MockStorageAdapter()
clock := NewVClockWithMockServices(stAdapter, sysClock, nil)
writeNewClockData(nil, clock, 0)
expectedSystemTimeAtBoot := sysTs.UnixNano() - constElapsedTime
verifyClockData(t, stAdapter, 0, expectedSystemTimeAtBoot, constElapsedTime)
}
// This test runs the following scenarios
// 1) Run checkSystemRebooted() with no ClockData stored
// Result: no op.
// 2) Run checkSystemRebooted() with ClockData that has SystemTimeAtBoot higher
// than the current elapsed time.
// Result: A new ClockData is written with updated SystemTimeAtBoot and
// elapsed time.
// 3) Run checkSystemRebooted() again after moving the sysClock forward
// Result: no op.
func TestCheckSystemRebooted(t *testing.T) {
sysTs := time.Now()
sysClock := MockSystemClock(sysTs, time.Duration(constElapsedTime))
stAdapter := MockStorageAdapter()
clock := NewVClockWithMockServices(stAdapter, sysClock, nil)
// stAdapter will return ErrNoExist while fetching ClockData
// checkSystemRebooted should return false.
if checkSystemRebooted(nil, clock) {
t.Error("Unexpected return value")
}
// Set clock data with elapsed time greater than constElapsedTime
clockData := &ClockData{25003, 25, 34569}
stAdapter.SetClockData(nil, clockData)
if !checkSystemRebooted(nil, clock) {
t.Error("Unexpected return value")
}
expectedSystemTimeAtBoot := sysTs.UnixNano() - constElapsedTime
verifyClockData(t, stAdapter, 25, expectedSystemTimeAtBoot, constElapsedTime)
// move clock forward without reboot and run checkSystemRebooted again
var timePassed int64 = 200
newSysTs := sysTs.Add(time.Duration(timePassed))
sysClock.SetNow(newSysTs)
sysClock.SetElapsedTime(time.Duration(constElapsedTime + timePassed))
if checkSystemRebooted(nil, clock) {
t.Error("Unexpected return value")
}
expectedSystemTimeAtBoot = sysTs.UnixNano() - constElapsedTime
verifyClockData(t, stAdapter, 25, expectedSystemTimeAtBoot, constElapsedTime)
}
// Setup: No prior ClockData present.
// Result: A new ClockData value gets set.
func TestRunClockCheck1(t *testing.T) {
sysTs := time.Now()
sysClock := MockSystemClock(sysTs, time.Duration(constElapsedTime))
stAdapter := MockStorageAdapter()
clock := NewVClockWithMockServices(stAdapter, sysClock, nil)
clock.runClockCheck(nil)
expectedSystemTimeAtBoot := sysTs.UnixNano() - constElapsedTime
verifyClockData(t, stAdapter, 0, expectedSystemTimeAtBoot, constElapsedTime)
}
// Setup: ClockData present, system clock elapsed time is lower than whats
// stored in clock data.
// Result: A new ClockData value gets set with new system boot time and elapsed
// time, skew remains the same.
func TestRunClockCheck2(t *testing.T) {
sysTs := time.Now()
sysClock := MockSystemClock(sysTs, time.Duration(constElapsedTime))
stAdapter := MockStorageAdapter()
// Set clock data with elapsed time greater than constElapsedTime
clockData := &ClockData{25003, 25, 34569}
stAdapter.SetClockData(nil, clockData)
clock := NewVClockWithMockServices(stAdapter, sysClock, nil)
clock.runClockCheck(nil)
expectedSystemTimeAtBoot := sysTs.UnixNano() - constElapsedTime
verifyClockData(t, stAdapter, 25, expectedSystemTimeAtBoot, constElapsedTime)
}
// Setup: ClockData present, system clock gets a skew of 10 seconds
// Result: A new ClockData value gets set with new elapsed time and skew,
// system boot time remains the same.
func TestRunClockCheck3(t *testing.T) {
sysTs := time.Now()
sysClock := MockSystemClock(sysTs, time.Duration(constElapsedTime))
stAdapter := MockStorageAdapter()
bootTs := sysTs.Add(time.Duration(-constElapsedTime))
oldSkew := 25 * time.Second
clockData := &ClockData{bootTs.UnixNano(), oldSkew.Nanoseconds(), 40}
stAdapter.SetClockData(nil, clockData)
clock := NewVClockWithMockServices(stAdapter, sysClock, nil)
// introduce a change in sys clock
extraSkew := 10 * time.Second // moves clock closer to UTC
changedSysTs := sysTs.Add(extraSkew)
sysClock.SetNow(changedSysTs)
newSkew := 15 * time.Second
clock.runClockCheck(nil)
expectedSystemTimeAtBoot := bootTs.UnixNano() + extraSkew.Nanoseconds()
verifyClockData(t, stAdapter, newSkew.Nanoseconds(), expectedSystemTimeAtBoot, constElapsedTime)
}
func TestWithRealSysClock(t *testing.T) {
stAdapter := MockStorageAdapter()
clock := NewVClockWithMockServices(stAdapter, nil, nil)
writeNewClockData(nil, clock, 0)
// Verify if clock data was written to StorageAdapter
clockData := &ClockData{}
if err := stAdapter.GetClockData(nil, clockData); err != nil {
t.Errorf("Expected to find clockData, received error: %v", err)
}
// Verify that calling checkSystemRebooted() does nothing
if checkSystemRebooted(nil, clock) {
t.Error("Unexpected return value")
}
// sleep for 1 second more than the skew threshold
time.Sleep(1800 * time.Millisecond)
// Verify that calling runClockCheck() only updates elapsed time
clock.runClockCheck(nil)
newClockData := &ClockData{}
if err := stAdapter.GetClockData(nil, newClockData); err != nil {
t.Errorf("Expected to find clockData, received error: %v", err)
}
if newClockData.Skew != clockData.Skew {
t.Errorf("Unexpected value for skew: %d", newClockData.Skew)
}
if newClockData.ElapsedTimeSinceBoot <= clockData.ElapsedTimeSinceBoot {
t.Errorf("Unexpected value for elapsed time: %d",
newClockData.ElapsedTimeSinceBoot)
}
if newClockData.SystemTimeAtBoot != clockData.SystemTimeAtBoot {
t.Errorf("SystemTimeAtBoot expected: %d, found: %d",
clockData.SystemTimeAtBoot, newClockData.SystemTimeAtBoot)
}
}
func verifyClockData(t *testing.T, stAdapter StorageAdapter, skew int64,
sysTimeAtBoot int64, elapsedTime int64) {
// verify ClockData
clockData := &ClockData{}
if err := stAdapter.GetClockData(nil, clockData); err != nil {
t.Errorf("Expected to find clockData, found error: %v", err)
}
if clockData.Skew != skew {
t.Errorf("Expected value for skew: %d, found: %d", skew, clockData.Skew)
}
if clockData.ElapsedTimeSinceBoot != elapsedTime {
t.Errorf("Expected value for elapsed time: %d, found: %d", elapsedTime,
clockData.ElapsedTimeSinceBoot)
}
if clockData.SystemTimeAtBoot != sysTimeAtBoot {
t.Errorf("Expected value for SystemTimeAtBoot: %d, found: %d",
sysTimeAtBoot, clockData.SystemTimeAtBoot)
}
}