Implement HostEpoch set time logic

1. When setting host epoch, follow below logic:

        Mode  | Owner | Set Host Time
        ----- | ----- | -------------
        NTP   | BMC   | Not allowed
        NTP   | HOST  | Not allowed
        NTP   | SPLIT | OK, and just save offset
        NTP   | BOTH  | Not allowed
        MANUAL| BMC   | Not allowed
        MANUAL| HOST  | OK, and set time to BMC
        MANUAL| SPLIT | OK, and just save offset
        MANUAL| BOTH  | OK, and set time to BMC

2. If owner is SPLIT and BMC time is changed, update the offset accordinly;
3. Use timerfd to get notified on BMC time change, and update host time
diff accordingly;
4. Add unit test cases.

Change-Id: I2d60a821f7da9b689c579ae7ab672cc37967322c
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/test/TestBmcEpoch.cpp b/test/TestBmcEpoch.cpp
index 2fd55a5..4661e20 100644
--- a/test/TestBmcEpoch.cpp
+++ b/test/TestBmcEpoch.cpp
@@ -1,45 +1,67 @@
 #include <sdbusplus/bus.hpp>
 #include <gtest/gtest.h>
+#include <memory>
 
 #include "bmc_epoch.hpp"
 #include "config.h"
 #include "types.hpp"
+#include "mocked_bmc_time_change_listener.hpp"
 
 namespace phosphor
 {
 namespace time
 {
 
+using ::testing::_;
 using namespace std::chrono;
+
 class TestBmcEpoch : public testing::Test
 {
     public:
         sdbusplus::bus::bus bus;
-        BmcEpoch bmcEpoch;
+        sd_event* event;
+        MockBmcTimeChangeListener listener;
+        std::unique_ptr<BmcEpoch> bmcEpoch;
 
         TestBmcEpoch()
-            : bus(sdbusplus::bus::new_default()),
-              bmcEpoch(bus, OBJPATH_BMC)
+            : bus(sdbusplus::bus::new_default())
         {
-            // Empty
+            // BmcEpoch requires sd_event to init
+            sd_event_default(&event);
+            bus.attach_event(event, SD_EVENT_PRIORITY_NORMAL);
+            bmcEpoch = std::make_unique<BmcEpoch>(bus, OBJPATH_BMC);
+            bmcEpoch->setBmcTimeChangeListener(&listener);
+        }
+
+        ~TestBmcEpoch()
+        {
+            bus.detach_event();
+            sd_event_unref(event);
         }
 
         // Proxies for BmcEpoch's private members and functions
         Mode getTimeMode()
         {
-            return bmcEpoch.timeMode;
+            return bmcEpoch->timeMode;
         }
         Owner getTimeOwner()
         {
-            return bmcEpoch.timeOwner;
+            return bmcEpoch->timeOwner;
         }
         void setTimeOwner(Owner owner)
         {
-            bmcEpoch.timeOwner = owner;
+            bmcEpoch->timeOwner = owner;
         }
         void setTimeMode(Mode mode)
         {
-            bmcEpoch.timeMode = mode;
+            bmcEpoch->timeMode = mode;
+        }
+        void triggerTimeChange()
+        {
+            bmcEpoch->onTimeChange(nullptr,
+                                   -1,
+                                   0,
+                                   bmcEpoch.get());
         }
 };
 
@@ -51,9 +73,9 @@
 
 TEST_F(TestBmcEpoch, getElapsed)
 {
-    auto t1 = bmcEpoch.elapsed();
+    auto t1 = bmcEpoch->elapsed();
     EXPECT_NE(0, t1);
-    auto t2 = bmcEpoch.elapsed();
+    auto t2 = bmcEpoch->elapsed();
     EXPECT_GE(t2, t1);
 }
 
@@ -62,13 +84,13 @@
     auto epochNow = duration_cast<microseconds>(
         system_clock::now().time_since_epoch()).count();
     // In NTP mode, setting time is not allowed
-    auto ret = bmcEpoch.elapsed(epochNow);
+    auto ret = bmcEpoch->elapsed(epochNow);
     EXPECT_EQ(0, ret);
 
     // In Host owner, setting time is not allowed
     setTimeMode(Mode::MANUAL);
     setTimeOwner(Owner::HOST);
-    ret = bmcEpoch.elapsed(epochNow);
+    ret = bmcEpoch->elapsed(epochNow);
     EXPECT_EQ(0, ret);
 }
 
@@ -79,5 +101,12 @@
     // But for now we can not test it
 }
 
+TEST_F(TestBmcEpoch, onTimeChange)
+{
+    // On BMC time change, the listner is expected to be notified
+    EXPECT_CALL(listener, onBmcTimeChanged(_)).Times(1);
+    triggerTimeChange();
+}
+
 }
 }