blob: a492b9a17aa860be7081b74b4bd4fb0dce88995b [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{
Lei YU57eab122017-06-16 10:27:30 +0800140 // Default mode/owner is MANUAL/BOTH
Lei YUad143542017-07-25 14:27:07 +0800141 EXPECT_EQ(Mode::Manual, getTimeMode());
142 EXPECT_EQ(Owner::Both, getTimeOwner());
Lei YUaf5abc52017-03-07 17:49:17 +0800143}
144
145TEST_F(TestHostEpoch, readDataFileNotExist)
146{
147 // When file does not exist, the default offset shall be 0
148 microseconds offset(0);
Lei YU7f4fca52017-02-23 15:15:51 +0800149 auto value = utils::readData<decltype(offset)::rep>(FILE_NOT_EXIST);
Lei YUaf5abc52017-03-07 17:49:17 +0800150 EXPECT_EQ(0, value);
151}
152
153TEST_F(TestHostEpoch, writeAndReadData)
154{
155 // Write offset to file
156 microseconds offsetToWrite(1234567);
Lei YU7f4fca52017-02-23 15:15:51 +0800157 utils::writeData<decltype(offsetToWrite)::rep>(
158 FILE_OFFSET, offsetToWrite.count());
Lei YUaf5abc52017-03-07 17:49:17 +0800159
160 // Read it back
161 microseconds offsetToRead;
162 offsetToRead = microseconds(
Lei YU7b218792017-02-09 12:10:13 +0800163 utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET));
Lei YUaf5abc52017-03-07 17:49:17 +0800164 EXPECT_EQ(offsetToWrite, offsetToRead);
165}
166
Lei YU7b218792017-02-09 12:10:13 +0800167TEST_F(TestHostEpoch, setElapsedInNtpBmc)
Lei YUaf5abc52017-03-07 17:49:17 +0800168{
Lei YU7b218792017-02-09 12:10:13 +0800169 // Set time in NTP/BMC is not allowed
170 setTimeMode(Mode::NTP);
171 setTimeOwner(Owner::BMC);
172 checkSettingTimeNotAllowed();
Lei YUaf5abc52017-03-07 17:49:17 +0800173}
174
Lei YU7b218792017-02-09 12:10:13 +0800175TEST_F(TestHostEpoch, setElapsedInNtpHost)
Lei YUaf5abc52017-03-07 17:49:17 +0800176{
Lei YU7b218792017-02-09 12:10:13 +0800177 // Set time in NTP/HOST is not allowed
178 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800179 setTimeOwner(Owner::Host);
Lei YU7b218792017-02-09 12:10:13 +0800180 checkSettingTimeNotAllowed();
181}
182
183TEST_F(TestHostEpoch, setElapsedInNtpSplit)
184{
185 // Set time in NTP/SPLIT, offset will be set
186 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800187 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800188
189 checkSetSplitTimeInFuture();
190
191 // Reset offset
192 setOffset(USEC_ZERO);
193 checkSetSplitTimeInPast();
194}
195
196TEST_F(TestHostEpoch, setElapsedInNtpBoth)
197{
198 // Set time in NTP/BOTH is not allowed
199 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800200 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800201 checkSettingTimeNotAllowed();
202}
203
204TEST_F(TestHostEpoch, setElapsedInManualBmc)
205{
206 // Set time in MANUAL/BMC is not allowed
Lei YUad143542017-07-25 14:27:07 +0800207 setTimeMode(Mode::Manual);
Lei YU7b218792017-02-09 12:10:13 +0800208 setTimeOwner(Owner::BMC);
209 checkSettingTimeNotAllowed();
210}
211
212TEST_F(TestHostEpoch, setElapsedInManualHost)
213{
214 // Set time in MANUAL/HOST, time will be set to BMC
215 // However it requies gmock to test this case
216 // TODO: when gmock is ready, test this case.
Lei YUad143542017-07-25 14:27:07 +0800217 setTimeMode(Mode::Manual);
218 setTimeOwner(Owner::Host);
Lei YU7b218792017-02-09 12:10:13 +0800219}
220
221TEST_F(TestHostEpoch, setElapsedInManualSplit)
222{
223 // Set to SPLIT owner so that offset will be set
Lei YUad143542017-07-25 14:27:07 +0800224 setTimeMode(Mode::Manual);
225 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800226
227 checkSetSplitTimeInFuture();
228
229 // Reset offset
230 setOffset(USEC_ZERO);
231 checkSetSplitTimeInPast();
232}
233
234TEST_F(TestHostEpoch, setElapsedInManualBoth)
235{
236 // Set time in MANUAL/BOTH, time will be set to BMC
237 // However it requies gmock to test this case
238 // TODO: when gmock is ready, test this case.
Lei YUad143542017-07-25 14:27:07 +0800239 setTimeMode(Mode::Manual);
240 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800241}
242
243TEST_F(TestHostEpoch, setElapsedInSplitAndBmcTimeIsChanged)
244{
245 // Set to SPLIT owner so that offset will be set
Lei YUad143542017-07-25 14:27:07 +0800246 setTimeOwner(Owner::Split);
Lei YUaf5abc52017-03-07 17:49:17 +0800247
248 // Get current time, and set future +1min time
249 auto t1 = hostEpoch.elapsed();
250 EXPECT_NE(0, t1);
251 microseconds diff = 1min;
252 auto t2 = t1 + diff.count();
253 hostEpoch.elapsed(t2);
254
255 // Verify that the offset shall be positive,
256 // and less or equal to diff, and shall be not too less.
257 auto offset = getOffset();
Lei YU7b218792017-02-09 12:10:13 +0800258 EXPECT_GT(offset, USEC_ZERO);
Lei YUaf5abc52017-03-07 17:49:17 +0800259 EXPECT_LE(offset, diff);
260 diff -= delta;
261 EXPECT_GE(offset, diff);
262
Lei YU7b218792017-02-09 12:10:13 +0800263 // Now BMC time is changed to future +1min
264 hostEpoch.onBmcTimeChanged(microseconds(t2));
265
266 // Verify that the offset shall be around zero since it's almost
267 // the same as BMC time
268 offset = getOffset();
269 if (offset.count() < 0)
270 {
271 offset = microseconds(-offset.count());
272 }
273 EXPECT_LE(offset, delta);
Lei YUaf5abc52017-03-07 17:49:17 +0800274}
275
Lei YU7b218792017-02-09 12:10:13 +0800276TEST_F(TestHostEpoch, clearOffsetOnOwnerChange)
Lei YUaf5abc52017-03-07 17:49:17 +0800277{
Lei YU7b218792017-02-09 12:10:13 +0800278 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800279
Lei YUad143542017-07-25 14:27:07 +0800280 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800281 hostEpoch.onBmcTimeChanged(microseconds(hostEpoch.elapsed()) + 1min);
Lei YUaf5abc52017-03-07 17:49:17 +0800282
Lei YU7b218792017-02-09 12:10:13 +0800283 // Now offset shall be non zero
284 EXPECT_NE(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800285
Lei YUad143542017-07-25 14:27:07 +0800286 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800287
288 // Now owner is BOTH, the offset shall be cleared
289 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800290}
291
292}
293}