1 #include <sdbusplus/bus.hpp>
2 #include <gtest/gtest.h>
3 #include <memory>
4 
5 #include "bmc_epoch.hpp"
6 #include "config.h"
7 #include "types.hpp"
8 #include "mocked_bmc_time_change_listener.hpp"
9 
10 namespace phosphor
11 {
12 namespace time
13 {
14 
15 using ::testing::_;
16 using namespace std::chrono;
17 
18 class TestBmcEpoch : public testing::Test
19 {
20     public:
21         sdbusplus::bus::bus bus;
22         sd_event* event;
23         MockBmcTimeChangeListener listener;
24         std::unique_ptr<BmcEpoch> bmcEpoch;
25 
26         TestBmcEpoch()
27             : bus(sdbusplus::bus::new_default())
28         {
29             // BmcEpoch requires sd_event to init
30             sd_event_default(&event);
31             bus.attach_event(event, SD_EVENT_PRIORITY_NORMAL);
32             bmcEpoch = std::make_unique<BmcEpoch>(bus, OBJPATH_BMC);
33             bmcEpoch->setBmcTimeChangeListener(&listener);
34         }
35 
36         ~TestBmcEpoch()
37         {
38             bus.detach_event();
39             sd_event_unref(event);
40         }
41 
42         // Proxies for BmcEpoch's private members and functions
43         Mode getTimeMode()
44         {
45             return bmcEpoch->timeMode;
46         }
47         Owner getTimeOwner()
48         {
49             return bmcEpoch->timeOwner;
50         }
51         void setTimeOwner(Owner owner)
52         {
53             bmcEpoch->timeOwner = owner;
54         }
55         void setTimeMode(Mode mode)
56         {
57             bmcEpoch->timeMode = mode;
58         }
59         void triggerTimeChange()
60         {
61             bmcEpoch->onTimeChange(nullptr,
62                                    -1,
63                                    0,
64                                    bmcEpoch.get());
65         }
66 };
67 
68 TEST_F(TestBmcEpoch, empty)
69 {
70     EXPECT_EQ(Mode::NTP, getTimeMode());
71     EXPECT_EQ(Owner::BMC, getTimeOwner());
72 }
73 
74 TEST_F(TestBmcEpoch, getElapsed)
75 {
76     auto t1 = bmcEpoch->elapsed();
77     EXPECT_NE(0, t1);
78     auto t2 = bmcEpoch->elapsed();
79     EXPECT_GE(t2, t1);
80 }
81 
82 TEST_F(TestBmcEpoch, setElapsedNotAllowed)
83 {
84     auto epochNow = duration_cast<microseconds>(
85         system_clock::now().time_since_epoch()).count();
86     // In NTP mode, setting time is not allowed
87     auto ret = bmcEpoch->elapsed(epochNow);
88     EXPECT_EQ(0, ret);
89 
90     // In Host owner, setting time is not allowed
91     setTimeMode(Mode::MANUAL);
92     setTimeOwner(Owner::HOST);
93     ret = bmcEpoch->elapsed(epochNow);
94     EXPECT_EQ(0, ret);
95 }
96 
97 TEST_F(TestBmcEpoch, setElapsedOK)
98 {
99     // TODO: setting time will call sd-bus functions and it will fail on host
100     // if we have gmock for sdbusplus::bus, we can test setElapsed.
101     // But for now we can not test it
102 }
103 
104 TEST_F(TestBmcEpoch, onTimeChange)
105 {
106     // On BMC time change, the listner is expected to be notified
107     EXPECT_CALL(listener, onBmcTimeChanged(_)).Times(1);
108     triggerTimeChange();
109 }
110 
111 }
112 }
113