blob: 6c460ad1ede788cc45cf5e91e5cff056fe4f43ae [file] [log] [blame]
Lei YUaf5abc52017-03-07 17:49:17 +08001#include "host_epoch.hpp"
Lei YU7f4fca52017-02-23 15:15:51 +08002#include "utils.hpp"
Lei YUaf5abc52017-03-07 17:49:17 +08003#include "config.h"
Lei YU415b9642017-02-09 11:37:26 +08004#include "types.hpp"
Lei YUaf5abc52017-03-07 17:49:17 +08005
Lei YU33752c72018-06-07 17:06:58 +08006#include <xyz/openbmc_project/Common/error.hpp>
7
8#include <sdbusplus/bus.hpp>
9#include <gtest/gtest.h>
10
11
Lei YUaf5abc52017-03-07 17:49:17 +080012namespace phosphor
13{
14namespace time
15{
16
17using namespace std::chrono;
18using namespace std::chrono_literals;
Lei YU33752c72018-06-07 17:06:58 +080019using InsufficientPermission =
20 sdbusplus::xyz::openbmc_project::Common::Error::InsufficientPermission;
Lei YUaf5abc52017-03-07 17:49:17 +080021
Lei YU7b218792017-02-09 12:10:13 +080022const constexpr microseconds USEC_ZERO{0};
23
Lei YUaf5abc52017-03-07 17:49:17 +080024class TestHostEpoch : public testing::Test
25{
26 public:
Lei YUaf5abc52017-03-07 17:49:17 +080027 sdbusplus::bus::bus bus;
28 HostEpoch hostEpoch;
29
30 static constexpr auto FILE_NOT_EXIST = "path/to/file-not-exist";
31 static constexpr auto FILE_OFFSET = "saved_host_offset";
Lei YU7b218792017-02-09 12:10:13 +080032 const microseconds delta = 2s;
Lei YUaf5abc52017-03-07 17:49:17 +080033
34 TestHostEpoch()
35 : bus(sdbusplus::bus::new_default()),
36 hostEpoch(bus, OBJPATH_HOST)
37 {
38 // Make sure the file does not exist
39 std::remove(FILE_NOT_EXIST);
40 }
41 ~TestHostEpoch()
42 {
43 // Cleanup test file
44 std::remove(FILE_OFFSET);
45 }
46
47 // Proxies for HostEpoch's private members and functions
48 Mode getTimeMode()
49 {
50 return hostEpoch.timeMode;
51 }
52 Owner getTimeOwner()
53 {
54 return hostEpoch.timeOwner;
55 }
Lei YUaf5abc52017-03-07 17:49:17 +080056 microseconds getOffset()
57 {
58 return hostEpoch.offset;
59 }
Lei YU7b218792017-02-09 12:10:13 +080060 void setOffset(microseconds us)
61 {
62 hostEpoch.offset = us;
63 }
Lei YUaf5abc52017-03-07 17:49:17 +080064 void setTimeOwner(Owner owner)
65 {
Lei YU7b218792017-02-09 12:10:13 +080066 hostEpoch.onOwnerChanged(owner);
67 }
68 void setTimeMode(Mode mode)
69 {
70 hostEpoch.onModeChanged(mode);
71 }
72
73 void checkSettingTimeNotAllowed()
74 {
75 // By default offset shall be 0
76 EXPECT_EQ(0, getOffset().count());
77
78 // Set time is not allowed,
79 // so verify offset is still 0 after set time
80 microseconds diff = 1min;
Lei YU33752c72018-06-07 17:06:58 +080081 EXPECT_THROW(
82 hostEpoch.elapsed(hostEpoch.elapsed() + diff.count()),
83 InsufficientPermission);
Lei YU7b218792017-02-09 12:10:13 +080084 EXPECT_EQ(0, getOffset().count());
Lei YU7b218792017-02-09 12:10:13 +080085 }
86
87 void checkSetSplitTimeInFuture()
88 {
89 // Get current time, and set future +1min time
90 auto t1 = hostEpoch.elapsed();
91 EXPECT_NE(0, t1);
92 microseconds diff = 1min;
93 auto t2 = t1 + diff.count();
94 hostEpoch.elapsed(t2);
95
96 // Verify that the offset shall be positive,
97 // and less or equal to diff, and shall be not too less.
98 auto offset = getOffset();
99 EXPECT_GT(offset, USEC_ZERO);
100 EXPECT_LE(offset, diff);
101 diff -= delta;
102 EXPECT_GE(offset, diff);
103
104 // Now get time shall be around future +1min time
105 auto epochNow = duration_cast<microseconds>(
106 system_clock::now().time_since_epoch()).count();
107 auto elapsedGot = hostEpoch.elapsed();
108 EXPECT_LT(epochNow, elapsedGot);
109 auto epochDiff = elapsedGot - epochNow;
110 diff = 1min;
111 EXPECT_GT(epochDiff, (diff - delta).count());
112 EXPECT_LT(epochDiff, (diff + delta).count());
113 }
114 void checkSetSplitTimeInPast()
115 {
116 // Get current time, and set past -1min time
117 auto t1 = hostEpoch.elapsed();
118 EXPECT_NE(0, t1);
119 microseconds diff = 1min;
120 auto t2 = t1 - diff.count();
121 hostEpoch.elapsed(t2);
122
123 // Verify that the offset shall be negative, and the absolute value
124 // shall be equal or greater than diff, and shall not be too greater
125 auto offset = getOffset();
126 EXPECT_LT(offset, USEC_ZERO);
127 offset = -offset;
128 EXPECT_GE(offset, diff);
129 diff += 10s;
130 EXPECT_LE(offset, diff);
131
132 // Now get time shall be around past -1min time
133 auto epochNow = duration_cast<microseconds>(
134 system_clock::now().time_since_epoch()).count();
135 auto elapsedGot = hostEpoch.elapsed();
136 EXPECT_LT(elapsedGot, epochNow);
137 auto epochDiff = epochNow - elapsedGot;
138 diff = 1min;
139 EXPECT_GT(epochDiff, (diff - delta).count());
140 EXPECT_LT(epochDiff, (diff + delta).count());
Lei YUaf5abc52017-03-07 17:49:17 +0800141 }
142};
143
144TEST_F(TestHostEpoch, empty)
145{
Lei YU57eab122017-06-16 10:27:30 +0800146 // Default mode/owner is MANUAL/BOTH
Lei YUad143542017-07-25 14:27:07 +0800147 EXPECT_EQ(Mode::Manual, getTimeMode());
148 EXPECT_EQ(Owner::Both, getTimeOwner());
Lei YUaf5abc52017-03-07 17:49:17 +0800149}
150
151TEST_F(TestHostEpoch, readDataFileNotExist)
152{
153 // When file does not exist, the default offset shall be 0
154 microseconds offset(0);
Lei YU7f4fca52017-02-23 15:15:51 +0800155 auto value = utils::readData<decltype(offset)::rep>(FILE_NOT_EXIST);
Lei YUaf5abc52017-03-07 17:49:17 +0800156 EXPECT_EQ(0, value);
157}
158
159TEST_F(TestHostEpoch, writeAndReadData)
160{
161 // Write offset to file
162 microseconds offsetToWrite(1234567);
Lei YU7f4fca52017-02-23 15:15:51 +0800163 utils::writeData<decltype(offsetToWrite)::rep>(
164 FILE_OFFSET, offsetToWrite.count());
Lei YUaf5abc52017-03-07 17:49:17 +0800165
166 // Read it back
167 microseconds offsetToRead;
168 offsetToRead = microseconds(
Lei YU7b218792017-02-09 12:10:13 +0800169 utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET));
Lei YUaf5abc52017-03-07 17:49:17 +0800170 EXPECT_EQ(offsetToWrite, offsetToRead);
171}
172
Lei YU7b218792017-02-09 12:10:13 +0800173TEST_F(TestHostEpoch, setElapsedInNtpBmc)
Lei YUaf5abc52017-03-07 17:49:17 +0800174{
Lei YU7b218792017-02-09 12:10:13 +0800175 // Set time in NTP/BMC is not allowed
176 setTimeMode(Mode::NTP);
177 setTimeOwner(Owner::BMC);
178 checkSettingTimeNotAllowed();
Lei YUaf5abc52017-03-07 17:49:17 +0800179}
180
Lei YU7b218792017-02-09 12:10:13 +0800181TEST_F(TestHostEpoch, setElapsedInNtpHost)
Lei YUaf5abc52017-03-07 17:49:17 +0800182{
Lei YU7b218792017-02-09 12:10:13 +0800183 // Set time in NTP/HOST is not allowed
184 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800185 setTimeOwner(Owner::Host);
Lei YU7b218792017-02-09 12:10:13 +0800186 checkSettingTimeNotAllowed();
187}
188
189TEST_F(TestHostEpoch, setElapsedInNtpSplit)
190{
191 // Set time in NTP/SPLIT, offset will be set
192 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800193 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800194
195 checkSetSplitTimeInFuture();
196
197 // Reset offset
198 setOffset(USEC_ZERO);
199 checkSetSplitTimeInPast();
200}
201
202TEST_F(TestHostEpoch, setElapsedInNtpBoth)
203{
204 // Set time in NTP/BOTH is not allowed
205 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800206 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800207 checkSettingTimeNotAllowed();
208}
209
210TEST_F(TestHostEpoch, setElapsedInManualBmc)
211{
212 // Set time in MANUAL/BMC is not allowed
Lei YUad143542017-07-25 14:27:07 +0800213 setTimeMode(Mode::Manual);
Lei YU7b218792017-02-09 12:10:13 +0800214 setTimeOwner(Owner::BMC);
215 checkSettingTimeNotAllowed();
216}
217
218TEST_F(TestHostEpoch, setElapsedInManualHost)
219{
220 // Set time in MANUAL/HOST, time will be set to BMC
221 // However it requies gmock to test this case
222 // TODO: when gmock is ready, test this case.
Lei YUad143542017-07-25 14:27:07 +0800223 setTimeMode(Mode::Manual);
224 setTimeOwner(Owner::Host);
Lei YU7b218792017-02-09 12:10:13 +0800225}
226
227TEST_F(TestHostEpoch, setElapsedInManualSplit)
228{
229 // Set to SPLIT owner so that offset will be set
Lei YUad143542017-07-25 14:27:07 +0800230 setTimeMode(Mode::Manual);
231 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800232
233 checkSetSplitTimeInFuture();
234
235 // Reset offset
236 setOffset(USEC_ZERO);
237 checkSetSplitTimeInPast();
238}
239
240TEST_F(TestHostEpoch, setElapsedInManualBoth)
241{
242 // Set time in MANUAL/BOTH, time will be set to BMC
243 // However it requies gmock to test this case
244 // TODO: when gmock is ready, test this case.
Lei YUad143542017-07-25 14:27:07 +0800245 setTimeMode(Mode::Manual);
246 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800247}
248
249TEST_F(TestHostEpoch, setElapsedInSplitAndBmcTimeIsChanged)
250{
251 // Set to SPLIT owner so that offset will be set
Lei YUad143542017-07-25 14:27:07 +0800252 setTimeOwner(Owner::Split);
Lei YUaf5abc52017-03-07 17:49:17 +0800253
254 // Get current time, and set future +1min time
255 auto t1 = hostEpoch.elapsed();
256 EXPECT_NE(0, t1);
257 microseconds diff = 1min;
258 auto t2 = t1 + diff.count();
259 hostEpoch.elapsed(t2);
260
261 // Verify that the offset shall be positive,
262 // and less or equal to diff, and shall be not too less.
263 auto offset = getOffset();
Lei YU7b218792017-02-09 12:10:13 +0800264 EXPECT_GT(offset, USEC_ZERO);
Lei YUaf5abc52017-03-07 17:49:17 +0800265 EXPECT_LE(offset, diff);
266 diff -= delta;
267 EXPECT_GE(offset, diff);
268
Lei YU7b218792017-02-09 12:10:13 +0800269 // Now BMC time is changed to future +1min
270 hostEpoch.onBmcTimeChanged(microseconds(t2));
271
272 // Verify that the offset shall be around zero since it's almost
273 // the same as BMC time
274 offset = getOffset();
275 if (offset.count() < 0)
276 {
277 offset = microseconds(-offset.count());
278 }
279 EXPECT_LE(offset, delta);
Lei YUaf5abc52017-03-07 17:49:17 +0800280}
281
Lei YU7b218792017-02-09 12:10:13 +0800282TEST_F(TestHostEpoch, clearOffsetOnOwnerChange)
Lei YUaf5abc52017-03-07 17:49:17 +0800283{
Lei YU7b218792017-02-09 12:10:13 +0800284 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800285
Lei YUad143542017-07-25 14:27:07 +0800286 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800287 hostEpoch.onBmcTimeChanged(microseconds(hostEpoch.elapsed()) + 1min);
Lei YUaf5abc52017-03-07 17:49:17 +0800288
Lei YU7b218792017-02-09 12:10:13 +0800289 // Now offset shall be non zero
290 EXPECT_NE(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800291
Lei YUad143542017-07-25 14:27:07 +0800292 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800293
294 // Now owner is BOTH, the offset shall be cleared
295 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800296}
297
298}
299}