blob: 13d604d56a5dce67ed6145dc6f27b55c66c65dd0 [file] [log] [blame]
Lei YUaf5abc52017-03-07 17:49:17 +08001#include <sdbusplus/bus.hpp>
2#include <gtest/gtest.h>
3
4#include "host_epoch.hpp"
Lei YU7f4fca52017-02-23 15:15:51 +08005#include "utils.hpp"
Lei YUaf5abc52017-03-07 17:49:17 +08006#include "config.h"
Lei YU415b9642017-02-09 11:37:26 +08007#include "types.hpp"
Lei YUaf5abc52017-03-07 17:49:17 +08008
9namespace phosphor
10{
11namespace time
12{
13
14using namespace std::chrono;
15using namespace std::chrono_literals;
16
Lei YU7b218792017-02-09 12:10:13 +080017const constexpr microseconds USEC_ZERO{0};
18
Lei YUaf5abc52017-03-07 17:49:17 +080019class TestHostEpoch : public testing::Test
20{
21 public:
Lei YUaf5abc52017-03-07 17:49:17 +080022 sdbusplus::bus::bus bus;
23 HostEpoch hostEpoch;
24
25 static constexpr auto FILE_NOT_EXIST = "path/to/file-not-exist";
26 static constexpr auto FILE_OFFSET = "saved_host_offset";
Lei YU7b218792017-02-09 12:10:13 +080027 const microseconds delta = 2s;
Lei YUaf5abc52017-03-07 17:49:17 +080028
29 TestHostEpoch()
30 : bus(sdbusplus::bus::new_default()),
31 hostEpoch(bus, OBJPATH_HOST)
32 {
33 // Make sure the file does not exist
34 std::remove(FILE_NOT_EXIST);
35 }
36 ~TestHostEpoch()
37 {
38 // Cleanup test file
39 std::remove(FILE_OFFSET);
40 }
41
42 // Proxies for HostEpoch's private members and functions
43 Mode getTimeMode()
44 {
45 return hostEpoch.timeMode;
46 }
47 Owner getTimeOwner()
48 {
49 return hostEpoch.timeOwner;
50 }
Lei YUaf5abc52017-03-07 17:49:17 +080051 microseconds getOffset()
52 {
53 return hostEpoch.offset;
54 }
Lei YU7b218792017-02-09 12:10:13 +080055 void setOffset(microseconds us)
56 {
57 hostEpoch.offset = us;
58 }
Lei YUaf5abc52017-03-07 17:49:17 +080059 void setTimeOwner(Owner owner)
60 {
Lei YU7b218792017-02-09 12:10:13 +080061 hostEpoch.onOwnerChanged(owner);
62 }
63 void setTimeMode(Mode mode)
64 {
65 hostEpoch.onModeChanged(mode);
66 }
67
68 void checkSettingTimeNotAllowed()
69 {
70 // By default offset shall be 0
71 EXPECT_EQ(0, getOffset().count());
72
73 // Set time is not allowed,
74 // so verify offset is still 0 after set time
75 microseconds diff = 1min;
76 hostEpoch.elapsed(hostEpoch.elapsed() + diff.count());
77 EXPECT_EQ(0, getOffset().count());
78 // TODO: when gmock is ready, check there is no call to timedatectl
79 }
80
81 void checkSetSplitTimeInFuture()
82 {
83 // Get current time, and set future +1min time
84 auto t1 = hostEpoch.elapsed();
85 EXPECT_NE(0, t1);
86 microseconds diff = 1min;
87 auto t2 = t1 + diff.count();
88 hostEpoch.elapsed(t2);
89
90 // Verify that the offset shall be positive,
91 // and less or equal to diff, and shall be not too less.
92 auto offset = getOffset();
93 EXPECT_GT(offset, USEC_ZERO);
94 EXPECT_LE(offset, diff);
95 diff -= delta;
96 EXPECT_GE(offset, diff);
97
98 // Now get time shall be around future +1min time
99 auto epochNow = duration_cast<microseconds>(
100 system_clock::now().time_since_epoch()).count();
101 auto elapsedGot = hostEpoch.elapsed();
102 EXPECT_LT(epochNow, elapsedGot);
103 auto epochDiff = elapsedGot - epochNow;
104 diff = 1min;
105 EXPECT_GT(epochDiff, (diff - delta).count());
106 EXPECT_LT(epochDiff, (diff + delta).count());
107 }
108 void checkSetSplitTimeInPast()
109 {
110 // Get current time, and set past -1min time
111 auto t1 = hostEpoch.elapsed();
112 EXPECT_NE(0, t1);
113 microseconds diff = 1min;
114 auto t2 = t1 - diff.count();
115 hostEpoch.elapsed(t2);
116
117 // Verify that the offset shall be negative, and the absolute value
118 // shall be equal or greater than diff, and shall not be too greater
119 auto offset = getOffset();
120 EXPECT_LT(offset, USEC_ZERO);
121 offset = -offset;
122 EXPECT_GE(offset, diff);
123 diff += 10s;
124 EXPECT_LE(offset, diff);
125
126 // Now get time shall be around past -1min time
127 auto epochNow = duration_cast<microseconds>(
128 system_clock::now().time_since_epoch()).count();
129 auto elapsedGot = hostEpoch.elapsed();
130 EXPECT_LT(elapsedGot, epochNow);
131 auto epochDiff = epochNow - elapsedGot;
132 diff = 1min;
133 EXPECT_GT(epochDiff, (diff - delta).count());
134 EXPECT_LT(epochDiff, (diff + delta).count());
Lei YUaf5abc52017-03-07 17:49:17 +0800135 }
136};
137
138TEST_F(TestHostEpoch, empty)
139{
140 EXPECT_EQ(Mode::NTP, getTimeMode());
141 EXPECT_EQ(Owner::BMC, getTimeOwner());
142}
143
144TEST_F(TestHostEpoch, readDataFileNotExist)
145{
146 // When file does not exist, the default offset shall be 0
147 microseconds offset(0);
Lei YU7f4fca52017-02-23 15:15:51 +0800148 auto value = utils::readData<decltype(offset)::rep>(FILE_NOT_EXIST);
Lei YUaf5abc52017-03-07 17:49:17 +0800149 EXPECT_EQ(0, value);
150}
151
152TEST_F(TestHostEpoch, writeAndReadData)
153{
154 // Write offset to file
155 microseconds offsetToWrite(1234567);
Lei YU7f4fca52017-02-23 15:15:51 +0800156 utils::writeData<decltype(offsetToWrite)::rep>(
157 FILE_OFFSET, offsetToWrite.count());
Lei YUaf5abc52017-03-07 17:49:17 +0800158
159 // Read it back
160 microseconds offsetToRead;
161 offsetToRead = microseconds(
Lei YU7b218792017-02-09 12:10:13 +0800162 utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET));
Lei YUaf5abc52017-03-07 17:49:17 +0800163 EXPECT_EQ(offsetToWrite, offsetToRead);
164}
165
Lei YU7b218792017-02-09 12:10:13 +0800166TEST_F(TestHostEpoch, setElapsedInNtpBmc)
Lei YUaf5abc52017-03-07 17:49:17 +0800167{
Lei YU7b218792017-02-09 12:10:13 +0800168 // Set time in NTP/BMC is not allowed
169 setTimeMode(Mode::NTP);
170 setTimeOwner(Owner::BMC);
171 checkSettingTimeNotAllowed();
Lei YUaf5abc52017-03-07 17:49:17 +0800172}
173
Lei YU7b218792017-02-09 12:10:13 +0800174TEST_F(TestHostEpoch, setElapsedInNtpHost)
Lei YUaf5abc52017-03-07 17:49:17 +0800175{
Lei YU7b218792017-02-09 12:10:13 +0800176 // Set time in NTP/HOST is not allowed
177 setTimeMode(Mode::NTP);
Lei YUaf5abc52017-03-07 17:49:17 +0800178 setTimeOwner(Owner::HOST);
Lei YU7b218792017-02-09 12:10:13 +0800179 checkSettingTimeNotAllowed();
180}
181
182TEST_F(TestHostEpoch, setElapsedInNtpSplit)
183{
184 // Set time in NTP/SPLIT, offset will be set
185 setTimeMode(Mode::NTP);
186 setTimeOwner(Owner::SPLIT);
187
188 checkSetSplitTimeInFuture();
189
190 // Reset offset
191 setOffset(USEC_ZERO);
192 checkSetSplitTimeInPast();
193}
194
195TEST_F(TestHostEpoch, setElapsedInNtpBoth)
196{
197 // Set time in NTP/BOTH is not allowed
198 setTimeMode(Mode::NTP);
199 setTimeOwner(Owner::BOTH);
200 checkSettingTimeNotAllowed();
201}
202
203TEST_F(TestHostEpoch, setElapsedInManualBmc)
204{
205 // Set time in MANUAL/BMC is not allowed
206 setTimeMode(Mode::MANUAL);
207 setTimeOwner(Owner::BMC);
208 checkSettingTimeNotAllowed();
209}
210
211TEST_F(TestHostEpoch, setElapsedInManualHost)
212{
213 // Set time in MANUAL/HOST, time will be set to BMC
214 // However it requies gmock to test this case
215 // TODO: when gmock is ready, test this case.
216 setTimeMode(Mode::MANUAL);
217 setTimeOwner(Owner::HOST);
218}
219
220TEST_F(TestHostEpoch, setElapsedInManualSplit)
221{
222 // Set to SPLIT owner so that offset will be set
223 setTimeMode(Mode::MANUAL);
224 setTimeOwner(Owner::SPLIT);
225
226 checkSetSplitTimeInFuture();
227
228 // Reset offset
229 setOffset(USEC_ZERO);
230 checkSetSplitTimeInPast();
231}
232
233TEST_F(TestHostEpoch, setElapsedInManualBoth)
234{
235 // Set time in MANUAL/BOTH, time will be set to BMC
236 // However it requies gmock to test this case
237 // TODO: when gmock is ready, test this case.
238 setTimeMode(Mode::MANUAL);
239 setTimeOwner(Owner::BOTH);
240}
241
242TEST_F(TestHostEpoch, setElapsedInSplitAndBmcTimeIsChanged)
243{
244 // Set to SPLIT owner so that offset will be set
245 setTimeOwner(Owner::SPLIT);
Lei YUaf5abc52017-03-07 17:49:17 +0800246
247 // Get current time, and set future +1min time
248 auto t1 = hostEpoch.elapsed();
249 EXPECT_NE(0, t1);
250 microseconds diff = 1min;
251 auto t2 = t1 + diff.count();
252 hostEpoch.elapsed(t2);
253
254 // Verify that the offset shall be positive,
255 // and less or equal to diff, and shall be not too less.
256 auto offset = getOffset();
Lei YU7b218792017-02-09 12:10:13 +0800257 EXPECT_GT(offset, USEC_ZERO);
Lei YUaf5abc52017-03-07 17:49:17 +0800258 EXPECT_LE(offset, diff);
259 diff -= delta;
260 EXPECT_GE(offset, diff);
261
Lei YU7b218792017-02-09 12:10:13 +0800262 // Now BMC time is changed to future +1min
263 hostEpoch.onBmcTimeChanged(microseconds(t2));
264
265 // Verify that the offset shall be around zero since it's almost
266 // the same as BMC time
267 offset = getOffset();
268 if (offset.count() < 0)
269 {
270 offset = microseconds(-offset.count());
271 }
272 EXPECT_LE(offset, delta);
Lei YUaf5abc52017-03-07 17:49:17 +0800273}
274
Lei YU7b218792017-02-09 12:10:13 +0800275TEST_F(TestHostEpoch, clearOffsetOnOwnerChange)
Lei YUaf5abc52017-03-07 17:49:17 +0800276{
Lei YU7b218792017-02-09 12:10:13 +0800277 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800278
Lei YU7b218792017-02-09 12:10:13 +0800279 setTimeOwner(Owner::SPLIT);
280 hostEpoch.onBmcTimeChanged(microseconds(hostEpoch.elapsed()) + 1min);
Lei YUaf5abc52017-03-07 17:49:17 +0800281
Lei YU7b218792017-02-09 12:10:13 +0800282 // Now offset shall be non zero
283 EXPECT_NE(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800284
Lei YU7b218792017-02-09 12:10:13 +0800285 setTimeOwner(Owner::BOTH);
286
287 // Now owner is BOTH, the offset shall be cleared
288 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800289}
290
291}
292}