blob: 7ddf92fc7540dcecc9f9228b496a2d9f9a4327ae [file] [log] [blame]
Lei YUaf5abc52017-03-07 17:49:17 +08001#include "config.h"
2
Gunnar Millsab4cc6a2018-09-14 14:42:39 -05003#include "host_epoch.hpp"
4#include "types.hpp"
5#include "utils.hpp"
Lei YU33752c72018-06-07 17:06:58 +08006
7#include <sdbusplus/bus.hpp>
Gunnar Millsab4cc6a2018-09-14 14:42:39 -05008#include <xyz/openbmc_project/Time/error.hpp>
Lei YU33752c72018-06-07 17:06:58 +08009
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050010#include <gtest/gtest.h>
Lei YU33752c72018-06-07 17:06:58 +080011
Lei YUaf5abc52017-03-07 17:49:17 +080012namespace phosphor
13{
14namespace time
15{
16
17using namespace std::chrono;
18using namespace std::chrono_literals;
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050019using NotAllowed = sdbusplus::xyz::openbmc_project::Time::Error::NotAllowed;
Lei YUaf5abc52017-03-07 17:49:17 +080020
Lei YU7b218792017-02-09 12:10:13 +080021const constexpr microseconds USEC_ZERO{0};
22
Lei YUaf5abc52017-03-07 17:49:17 +080023class TestHostEpoch : public testing::Test
24{
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050025 public:
26 sdbusplus::bus::bus bus;
27 HostEpoch hostEpoch;
Lei YUaf5abc52017-03-07 17:49:17 +080028
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050029 static constexpr auto FILE_NOT_EXIST = "path/to/file-not-exist";
30 static constexpr auto FILE_OFFSET = "saved_host_offset";
31 const microseconds delta = 2s;
Lei YUaf5abc52017-03-07 17:49:17 +080032
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050033 TestHostEpoch() :
34 bus(sdbusplus::bus::new_default()), hostEpoch(bus, OBJPATH_HOST)
35 {
36 // Make sure the file does not exist
37 std::remove(FILE_NOT_EXIST);
38 }
39 ~TestHostEpoch()
40 {
41 // Cleanup test file
42 std::remove(FILE_OFFSET);
43 }
Lei YUaf5abc52017-03-07 17:49:17 +080044
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050045 // Proxies for HostEpoch's private members and functions
46 Mode getTimeMode()
47 {
48 return hostEpoch.timeMode;
49 }
50 Owner getTimeOwner()
51 {
52 return hostEpoch.timeOwner;
53 }
54 microseconds getOffset()
55 {
56 return hostEpoch.offset;
57 }
58 void setOffset(microseconds us)
59 {
60 hostEpoch.offset = us;
61 }
62 void setTimeOwner(Owner owner)
63 {
64 hostEpoch.onOwnerChanged(owner);
65 }
66 void setTimeMode(Mode mode)
67 {
68 hostEpoch.onModeChanged(mode);
69 }
Lei YU7b218792017-02-09 12:10:13 +080070
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050071 void checkSettingTimeNotAllowed()
72 {
73 // By default offset shall be 0
74 EXPECT_EQ(0, getOffset().count());
Lei YU7b218792017-02-09 12:10:13 +080075
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050076 // Set time is not allowed,
77 // so verify offset is still 0 after set time
78 microseconds diff = 1min;
79 EXPECT_THROW(hostEpoch.elapsed(hostEpoch.elapsed() + diff.count()),
80 NotAllowed);
81 EXPECT_EQ(0, getOffset().count());
82 }
Lei YU7b218792017-02-09 12:10:13 +080083
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050084 void checkSetSplitTimeInFuture()
85 {
86 // Get current time, and set future +1min time
87 auto t1 = hostEpoch.elapsed();
88 EXPECT_NE(0, t1);
89 microseconds diff = 1min;
90 auto t2 = t1 + diff.count();
91 hostEpoch.elapsed(t2);
Lei YU7b218792017-02-09 12:10:13 +080092
Gunnar Millsab4cc6a2018-09-14 14:42:39 -050093 // Verify that the offset shall be positive,
94 // and less or equal to diff, and shall be not too less.
95 auto offset = getOffset();
96 EXPECT_GT(offset, USEC_ZERO);
97 EXPECT_LE(offset, diff);
98 diff -= delta;
99 EXPECT_GE(offset, diff);
Lei YU7b218792017-02-09 12:10:13 +0800100
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500101 // Now get time shall be around future +1min time
102 auto epochNow =
103 duration_cast<microseconds>(system_clock::now().time_since_epoch())
104 .count();
105 auto elapsedGot = hostEpoch.elapsed();
106 EXPECT_LT(epochNow, elapsedGot);
107 auto epochDiff = elapsedGot - epochNow;
108 diff = 1min;
109 EXPECT_GT(epochDiff, (diff - delta).count());
110 EXPECT_LT(epochDiff, (diff + delta).count());
111 }
112 void checkSetSplitTimeInPast()
113 {
114 // Get current time, and set past -1min time
115 auto t1 = hostEpoch.elapsed();
116 EXPECT_NE(0, t1);
117 microseconds diff = 1min;
118 auto t2 = t1 - diff.count();
119 hostEpoch.elapsed(t2);
Lei YU7b218792017-02-09 12:10:13 +0800120
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500121 // Verify that the offset shall be negative, and the absolute value
122 // shall be equal or greater than diff, and shall not be too greater
123 auto offset = getOffset();
124 EXPECT_LT(offset, USEC_ZERO);
125 offset = -offset;
126 EXPECT_GE(offset, diff);
127 diff += 10s;
128 EXPECT_LE(offset, diff);
Lei YU7b218792017-02-09 12:10:13 +0800129
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500130 // Now get time shall be around past -1min time
131 auto epochNow =
132 duration_cast<microseconds>(system_clock::now().time_since_epoch())
133 .count();
134 auto elapsedGot = hostEpoch.elapsed();
135 EXPECT_LT(elapsedGot, epochNow);
136 auto epochDiff = epochNow - elapsedGot;
137 diff = 1min;
138 EXPECT_GT(epochDiff, (diff - delta).count());
139 EXPECT_LT(epochDiff, (diff + delta).count());
140 }
Lei YUaf5abc52017-03-07 17:49:17 +0800141};
142
143TEST_F(TestHostEpoch, empty)
144{
Lei YU57eab122017-06-16 10:27:30 +0800145 // Default mode/owner is MANUAL/BOTH
Lei YUad143542017-07-25 14:27:07 +0800146 EXPECT_EQ(Mode::Manual, getTimeMode());
147 EXPECT_EQ(Owner::Both, getTimeOwner());
Lei YUaf5abc52017-03-07 17:49:17 +0800148}
149
150TEST_F(TestHostEpoch, readDataFileNotExist)
151{
152 // When file does not exist, the default offset shall be 0
153 microseconds offset(0);
Lei YU7f4fca52017-02-23 15:15:51 +0800154 auto value = utils::readData<decltype(offset)::rep>(FILE_NOT_EXIST);
Lei YUaf5abc52017-03-07 17:49:17 +0800155 EXPECT_EQ(0, value);
156}
157
158TEST_F(TestHostEpoch, writeAndReadData)
159{
160 // Write offset to file
161 microseconds offsetToWrite(1234567);
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500162 utils::writeData<decltype(offsetToWrite)::rep>(FILE_OFFSET,
163 offsetToWrite.count());
Lei YUaf5abc52017-03-07 17:49:17 +0800164
165 // Read it back
166 microseconds offsetToRead;
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500167 offsetToRead =
168 microseconds(utils::readData<decltype(offsetToRead)::rep>(FILE_OFFSET));
Lei YUaf5abc52017-03-07 17:49:17 +0800169 EXPECT_EQ(offsetToWrite, offsetToRead);
170}
171
Lei YU7b218792017-02-09 12:10:13 +0800172TEST_F(TestHostEpoch, setElapsedInNtpBmc)
Lei YUaf5abc52017-03-07 17:49:17 +0800173{
Lei YU7b218792017-02-09 12:10:13 +0800174 // Set time in NTP/BMC is not allowed
175 setTimeMode(Mode::NTP);
176 setTimeOwner(Owner::BMC);
177 checkSettingTimeNotAllowed();
Lei YUaf5abc52017-03-07 17:49:17 +0800178}
179
Lei YU7b218792017-02-09 12:10:13 +0800180TEST_F(TestHostEpoch, setElapsedInNtpHost)
Lei YUaf5abc52017-03-07 17:49:17 +0800181{
Lei YU7b218792017-02-09 12:10:13 +0800182 // Set time in NTP/HOST is not allowed
183 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800184 setTimeOwner(Owner::Host);
Lei YU7b218792017-02-09 12:10:13 +0800185 checkSettingTimeNotAllowed();
186}
187
188TEST_F(TestHostEpoch, setElapsedInNtpSplit)
189{
190 // Set time in NTP/SPLIT, offset will be set
191 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800192 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800193
194 checkSetSplitTimeInFuture();
195
196 // Reset offset
197 setOffset(USEC_ZERO);
198 checkSetSplitTimeInPast();
199}
200
201TEST_F(TestHostEpoch, setElapsedInNtpBoth)
202{
203 // Set time in NTP/BOTH is not allowed
204 setTimeMode(Mode::NTP);
Lei YUad143542017-07-25 14:27:07 +0800205 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800206 checkSettingTimeNotAllowed();
207}
208
209TEST_F(TestHostEpoch, setElapsedInManualBmc)
210{
211 // Set time in MANUAL/BMC is not allowed
Lei YUad143542017-07-25 14:27:07 +0800212 setTimeMode(Mode::Manual);
Lei YU7b218792017-02-09 12:10:13 +0800213 setTimeOwner(Owner::BMC);
214 checkSettingTimeNotAllowed();
215}
216
217TEST_F(TestHostEpoch, setElapsedInManualHost)
218{
219 // Set time in MANUAL/HOST, time will be set to BMC
220 // However it requies gmock to test this case
221 // TODO: when gmock is ready, test this case.
Lei YUad143542017-07-25 14:27:07 +0800222 setTimeMode(Mode::Manual);
223 setTimeOwner(Owner::Host);
Lei YU7b218792017-02-09 12:10:13 +0800224}
225
226TEST_F(TestHostEpoch, setElapsedInManualSplit)
227{
228 // Set to SPLIT owner so that offset will be set
Lei YUad143542017-07-25 14:27:07 +0800229 setTimeMode(Mode::Manual);
230 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800231
232 checkSetSplitTimeInFuture();
233
234 // Reset offset
235 setOffset(USEC_ZERO);
236 checkSetSplitTimeInPast();
237}
238
239TEST_F(TestHostEpoch, setElapsedInManualBoth)
240{
241 // Set time in MANUAL/BOTH, time will be set to BMC
242 // However it requies gmock to test this case
243 // TODO: when gmock is ready, test this case.
Lei YUad143542017-07-25 14:27:07 +0800244 setTimeMode(Mode::Manual);
245 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800246}
247
248TEST_F(TestHostEpoch, setElapsedInSplitAndBmcTimeIsChanged)
249{
250 // Set to SPLIT owner so that offset will be set
Lei YUad143542017-07-25 14:27:07 +0800251 setTimeOwner(Owner::Split);
Lei YUaf5abc52017-03-07 17:49:17 +0800252
253 // Get current time, and set future +1min time
254 auto t1 = hostEpoch.elapsed();
255 EXPECT_NE(0, t1);
256 microseconds diff = 1min;
257 auto t2 = t1 + diff.count();
258 hostEpoch.elapsed(t2);
259
260 // Verify that the offset shall be positive,
261 // and less or equal to diff, and shall be not too less.
262 auto offset = getOffset();
Lei YU7b218792017-02-09 12:10:13 +0800263 EXPECT_GT(offset, USEC_ZERO);
Lei YUaf5abc52017-03-07 17:49:17 +0800264 EXPECT_LE(offset, diff);
265 diff -= delta;
266 EXPECT_GE(offset, diff);
267
Lei YU7b218792017-02-09 12:10:13 +0800268 // Now BMC time is changed to future +1min
269 hostEpoch.onBmcTimeChanged(microseconds(t2));
270
271 // Verify that the offset shall be around zero since it's almost
272 // the same as BMC time
273 offset = getOffset();
274 if (offset.count() < 0)
275 {
276 offset = microseconds(-offset.count());
277 }
278 EXPECT_LE(offset, delta);
Lei YUaf5abc52017-03-07 17:49:17 +0800279}
280
Lei YU7b218792017-02-09 12:10:13 +0800281TEST_F(TestHostEpoch, clearOffsetOnOwnerChange)
Lei YUaf5abc52017-03-07 17:49:17 +0800282{
Lei YU7b218792017-02-09 12:10:13 +0800283 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800284
Lei YUad143542017-07-25 14:27:07 +0800285 setTimeOwner(Owner::Split);
Lei YU7b218792017-02-09 12:10:13 +0800286 hostEpoch.onBmcTimeChanged(microseconds(hostEpoch.elapsed()) + 1min);
Lei YUaf5abc52017-03-07 17:49:17 +0800287
Lei YU7b218792017-02-09 12:10:13 +0800288 // Now offset shall be non zero
289 EXPECT_NE(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800290
Lei YUad143542017-07-25 14:27:07 +0800291 setTimeOwner(Owner::Both);
Lei YU7b218792017-02-09 12:10:13 +0800292
293 // Now owner is BOTH, the offset shall be cleared
294 EXPECT_EQ(USEC_ZERO, getOffset());
Lei YUaf5abc52017-03-07 17:49:17 +0800295}
296
Gunnar Millsab4cc6a2018-09-14 14:42:39 -0500297} // namespace time
298} // namespace phosphor