diff options
author | Lei YU <mine260309@gmail.com> | 2017-02-09 12:10:13 +0800 |
---|---|---|
committer | Lei YU <mine260309@gmail.com> | 2017-10-16 20:40:01 +0800 |
commit | 7b21879622a974d4ca92da760be7c7008732b6c3 (patch) | |
tree | 601a054f428ddcff726fa314064119326f678c34 /test/TestHostEpoch.cpp | |
parent | 7f4fca554b250d40230d5735d1d0ddf9ac6af801 (diff) | |
download | phosphor-time-manager-7b21879622a974d4ca92da760be7c7008732b6c3.tar.gz phosphor-time-manager-7b21879622a974d4ca92da760be7c7008732b6c3.zip |
Implement HostEpoch set time logic
1. When setting host epoch, follow below logic:
Mode | Owner | Set Host Time
----- | ----- | -------------
NTP | BMC | Not allowed
NTP | HOST | Not allowed
NTP | SPLIT | OK, and just save offset
NTP | BOTH | Not allowed
MANUAL| BMC | Not allowed
MANUAL| HOST | OK, and set time to BMC
MANUAL| SPLIT | OK, and just save offset
MANUAL| BOTH | OK, and set time to BMC
2. If owner is SPLIT and BMC time is changed, update the offset accordinly;
3. Use timerfd to get notified on BMC time change, and update host time
diff accordingly;
4. Add unit test cases.
Change-Id: I2d60a821f7da9b689c579ae7ab672cc37967322c
Signed-off-by: Lei YU <mine260309@gmail.com>
Diffstat (limited to 'test/TestHostEpoch.cpp')
-rw-r--r-- | test/TestHostEpoch.cpp | 227 |
1 files changed, 178 insertions, 49 deletions
diff --git a/test/TestHostEpoch.cpp b/test/TestHostEpoch.cpp index 0ff8a11..13d604d 100644 --- a/test/TestHostEpoch.cpp +++ b/test/TestHostEpoch.cpp @@ -14,6 +14,8 @@ namespace time using namespace std::chrono; using namespace std::chrono_literals; +const constexpr microseconds USEC_ZERO{0}; + class TestHostEpoch : public testing::Test { public: @@ -22,7 +24,7 @@ class TestHostEpoch : public testing::Test static constexpr auto FILE_NOT_EXIST = "path/to/file-not-exist"; static constexpr auto FILE_OFFSET = "saved_host_offset"; - static constexpr auto delta = 2s; + const microseconds delta = 2s; TestHostEpoch() : bus(sdbusplus::bus::new_default()), @@ -50,9 +52,86 @@ class TestHostEpoch : public testing::Test { return hostEpoch.offset; } + void setOffset(microseconds us) + { + hostEpoch.offset = us; + } void setTimeOwner(Owner owner) { - hostEpoch.timeOwner = owner; + hostEpoch.onOwnerChanged(owner); + } + void setTimeMode(Mode mode) + { + hostEpoch.onModeChanged(mode); + } + + void checkSettingTimeNotAllowed() + { + // By default offset shall be 0 + EXPECT_EQ(0, getOffset().count()); + + // Set time is not allowed, + // so verify offset is still 0 after set time + microseconds diff = 1min; + hostEpoch.elapsed(hostEpoch.elapsed() + diff.count()); + EXPECT_EQ(0, getOffset().count()); + // TODO: when gmock is ready, check there is no call to timedatectl + } + + void checkSetSplitTimeInFuture() + { + // Get current time, and set future +1min time + auto t1 = hostEpoch.elapsed(); + EXPECT_NE(0, t1); + microseconds diff = 1min; + auto t2 = t1 + diff.count(); + hostEpoch.elapsed(t2); + + // Verify that the offset shall be positive, + // and less or equal to diff, and shall be not too less. + auto offset = getOffset(); + EXPECT_GT(offset, USEC_ZERO); + EXPECT_LE(offset, diff); + diff -= delta; + EXPECT_GE(offset, diff); + + // Now get time shall be around future +1min time + auto epochNow = duration_cast<microseconds>( + system_clock::now().time_since_epoch()).count(); + auto elapsedGot = hostEpoch.elapsed(); + EXPECT_LT(epochNow, elapsedGot); + auto epochDiff = elapsedGot - epochNow; + diff = 1min; + EXPECT_GT(epochDiff, (diff - delta).count()); + EXPECT_LT(epochDiff, (diff + delta).count()); + } + void checkSetSplitTimeInPast() + { + // Get current time, and set past -1min time + auto t1 = hostEpoch.elapsed(); + EXPECT_NE(0, t1); + microseconds diff = 1min; + auto t2 = t1 - diff.count(); + hostEpoch.elapsed(t2); + + // Verify that the offset shall be negative, and the absolute value + // shall be equal or greater than diff, and shall not be too greater + auto offset = getOffset(); + EXPECT_LT(offset, USEC_ZERO); + offset = -offset; + EXPECT_GE(offset, diff); + diff += 10s; + EXPECT_LE(offset, diff); + + // Now get time shall be around past -1min time + auto epochNow = duration_cast<microseconds>( + system_clock::now().time_since_epoch()).count(); + auto elapsedGot = hostEpoch.elapsed(); + EXPECT_LT(elapsedGot, epochNow); + auto epochDiff = epochNow - elapsedGot; + diff = 1min; + EXPECT_GT(epochDiff, (diff - delta).count()); + EXPECT_LT(epochDiff, (diff + delta).count()); } }; @@ -80,26 +159,90 @@ TEST_F(TestHostEpoch, writeAndReadData) // Read it back microseconds offsetToRead; offsetToRead = microseconds( - utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET)); + utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET)); EXPECT_EQ(offsetToWrite, offsetToRead); } -TEST_F(TestHostEpoch, setElapsedNotAllowed) +TEST_F(TestHostEpoch, setElapsedInNtpBmc) { - // By default offset shall be 0 - EXPECT_EQ(0, getOffset().count()); + // Set time in NTP/BMC is not allowed + setTimeMode(Mode::NTP); + setTimeOwner(Owner::BMC); + checkSettingTimeNotAllowed(); +} - // Set time in BMC mode is not allowed, - // so verify offset is still 0 after set time - microseconds diff = 1min; - hostEpoch.elapsed(hostEpoch.elapsed() + diff.count()); - EXPECT_EQ(0, getOffset().count()); +TEST_F(TestHostEpoch, setElapsedInNtpHost) +{ + // Set time in NTP/HOST is not allowed + setTimeMode(Mode::NTP); + setTimeOwner(Owner::HOST); + checkSettingTimeNotAllowed(); +} + +TEST_F(TestHostEpoch, setElapsedInNtpSplit) +{ + // Set time in NTP/SPLIT, offset will be set + setTimeMode(Mode::NTP); + setTimeOwner(Owner::SPLIT); + + checkSetSplitTimeInFuture(); + + // Reset offset + setOffset(USEC_ZERO); + checkSetSplitTimeInPast(); } -TEST_F(TestHostEpoch, setElapsedInFutureAndGet) +TEST_F(TestHostEpoch, setElapsedInNtpBoth) { - // Set to HOST owner so that we can set elapsed + // Set time in NTP/BOTH is not allowed + setTimeMode(Mode::NTP); + setTimeOwner(Owner::BOTH); + checkSettingTimeNotAllowed(); +} + +TEST_F(TestHostEpoch, setElapsedInManualBmc) +{ + // Set time in MANUAL/BMC is not allowed + setTimeMode(Mode::MANUAL); + setTimeOwner(Owner::BMC); + checkSettingTimeNotAllowed(); +} + +TEST_F(TestHostEpoch, setElapsedInManualHost) +{ + // Set time in MANUAL/HOST, time will be set to BMC + // However it requies gmock to test this case + // TODO: when gmock is ready, test this case. + setTimeMode(Mode::MANUAL); setTimeOwner(Owner::HOST); +} + +TEST_F(TestHostEpoch, setElapsedInManualSplit) +{ + // Set to SPLIT owner so that offset will be set + setTimeMode(Mode::MANUAL); + setTimeOwner(Owner::SPLIT); + + checkSetSplitTimeInFuture(); + + // Reset offset + setOffset(USEC_ZERO); + checkSetSplitTimeInPast(); +} + +TEST_F(TestHostEpoch, setElapsedInManualBoth) +{ + // Set time in MANUAL/BOTH, time will be set to BMC + // However it requies gmock to test this case + // TODO: when gmock is ready, test this case. + setTimeMode(Mode::MANUAL); + setTimeOwner(Owner::BOTH); +} + +TEST_F(TestHostEpoch, setElapsedInSplitAndBmcTimeIsChanged) +{ + // Set to SPLIT owner so that offset will be set + setTimeOwner(Owner::SPLIT); // Get current time, and set future +1min time auto t1 = hostEpoch.elapsed(); @@ -111,52 +254,38 @@ TEST_F(TestHostEpoch, setElapsedInFutureAndGet) // Verify that the offset shall be positive, // and less or equal to diff, and shall be not too less. auto offset = getOffset(); - EXPECT_GT(offset, microseconds(0)); + EXPECT_GT(offset, USEC_ZERO); EXPECT_LE(offset, diff); diff -= delta; EXPECT_GE(offset, diff); - // Now get time shall be around future +1min time - auto epochNow = duration_cast<microseconds>( - system_clock::now().time_since_epoch()).count(); - auto elapsedGot = hostEpoch.elapsed(); - EXPECT_LT(epochNow, elapsedGot); - auto epochDiff = elapsedGot - epochNow; - diff = 1min; - EXPECT_GT(epochDiff, (diff - delta).count()); - EXPECT_LT(epochDiff, (diff + delta).count()); + // Now BMC time is changed to future +1min + hostEpoch.onBmcTimeChanged(microseconds(t2)); + + // Verify that the offset shall be around zero since it's almost + // the same as BMC time + offset = getOffset(); + if (offset.count() < 0) + { + offset = microseconds(-offset.count()); + } + EXPECT_LE(offset, delta); } -TEST_F(TestHostEpoch, setElapsedInPastAndGet) +TEST_F(TestHostEpoch, clearOffsetOnOwnerChange) { - // Set to HOST owner so that we can set elapsed - setTimeOwner(Owner::HOST); + EXPECT_EQ(USEC_ZERO, getOffset()); - // Get current time, and set past -1min time - auto t1 = hostEpoch.elapsed(); - EXPECT_NE(0, t1); - microseconds diff = 1min; - auto t2 = t1 - diff.count(); - hostEpoch.elapsed(t2); + setTimeOwner(Owner::SPLIT); + hostEpoch.onBmcTimeChanged(microseconds(hostEpoch.elapsed()) + 1min); - // Verify that the offset shall be negative, and the absolute value - // shall be equal or greater than diff, and shall not be too greater - auto offset = getOffset(); - EXPECT_LT(offset, microseconds(0)); - offset = -offset; - EXPECT_GE(offset, diff); - diff += 10s; - EXPECT_LE(offset, diff); + // Now offset shall be non zero + EXPECT_NE(USEC_ZERO, getOffset()); + + setTimeOwner(Owner::BOTH); - // Now get time shall be around past -1min time - auto epochNow = duration_cast<microseconds>( - system_clock::now().time_since_epoch()).count(); - auto elapsedGot = hostEpoch.elapsed(); - EXPECT_LT(elapsedGot, epochNow); - auto epochDiff = epochNow - elapsedGot; - diff = 1min; - EXPECT_GT(epochDiff, (diff - delta).count()); - EXPECT_LT(epochDiff, (diff + delta).count()); + // Now owner is BOTH, the offset shall be cleared + EXPECT_EQ(USEC_ZERO, getOffset()); } } |