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