Add time Manager to handle property changes callback
1. Implement time::Manager who registers property change signal for time
mode and owner;
2. Add PropertyChangeListner interface to handle the callback;
3. Make EpochBase to implement the interface.
Change-Id: I185580ae37353e1ed82a47e4905fb22e269ac09d
Signed-off-by: Lei YU <mine260309@gmail.com>
diff --git a/Makefile.am b/Makefile.am
index 0af260f..066dd33 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,8 @@
libtimemanager_la_SOURCES = \
epoch_base.cpp \
bmc_epoch.cpp \
- host_epoch.cpp
+ host_epoch.cpp \
+ manager.cpp
phosphor_timemanager_SOURCES = \
main.cpp
diff --git a/epoch_base.cpp b/epoch_base.cpp
index 06232bb..07b3113 100644
--- a/epoch_base.cpp
+++ b/epoch_base.cpp
@@ -5,15 +5,6 @@
#include <iomanip>
#include <sstream>
-namespace // anonymous
-{
-constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host";
-constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
-constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
-constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
-constexpr auto METHOD_GET = "Get";
-}
-
namespace phosphor
{
namespace time
@@ -21,90 +12,21 @@
using namespace phosphor::logging;
-const std::map<std::string, EpochBase::Owner>
-EpochBase::ownerMap = {
- { "BMC", EpochBase::Owner::BMC },
- { "HOST", EpochBase::Owner::HOST },
- { "SPLIT", EpochBase::Owner::SPLIT },
- { "BOTH", EpochBase::Owner::BOTH },
-};
-
EpochBase::EpochBase(sdbusplus::bus::bus& bus,
const char* objPath)
- : sdbusplus::server::object::object<EpochTime>(bus, objPath, true),
+ : sdbusplus::server::object::object<EpochTime>(bus, objPath),
bus(bus)
{
- initialize();
- // Deferred this until we could get our property correct
- emit_object_added();
}
-void EpochBase::setCurrentTimeMode(const std::string& mode)
+void EpochBase::onModeChanged(Mode mode)
{
- log<level::INFO>("Time mode is changed",
- entry("MODE=%s", mode.c_str()));
- timeMode = convertToMode(mode);
+ timeMode = mode;
}
-void EpochBase::setCurrentTimeOwner(const std::string& owner)
+void EpochBase::onOwnerChanged(Owner owner)
{
- log<level::INFO>("Time owner is changed",
- entry("OWNER=%s", owner.c_str()));
- timeOwner = convertToOwner(owner);
-}
-
-void EpochBase::initialize()
-{
- setCurrentTimeMode(getSettings("time_mode"));
- setCurrentTimeOwner(getSettings("time_owner"));
- // TODO: subscribe settingsd's property changes callback
-}
-
-std::string EpochBase::getSettings(const char* value) const
-{
- sdbusplus::message::variant<std::string> mode;
- auto method = bus.new_method_call(SETTINGS_SERVICE,
- SETTINGS_PATH,
- PROPERTY_INTERFACE,
- METHOD_GET);
- method.append(SETTINGS_INTERFACE, value);
- auto reply = bus.call(method);
- if (reply)
- {
- reply.read(mode);
- }
-
- return mode.get<std::string>();
-}
-
-EpochBase::Mode EpochBase::convertToMode(const std::string& mode)
-{
- if (mode == "NTP")
- {
- return Mode::NTP;
- }
- else if (mode == "MANUAL")
- {
- return Mode::MANUAL;
- }
- else
- {
- log<level::ERR>("Unrecognized mode",
- entry("%s", mode.c_str()));
- return Mode::NTP;
- }
-}
-
-EpochBase::Owner EpochBase::convertToOwner(const std::string& owner)
-{
- auto it = ownerMap.find(owner);
- if (it == ownerMap.end())
- {
- log<level::ERR>("Unrecognized owner",
- entry("%s", owner.c_str()));
- return Owner::BMC;
- }
- return it->second;
+ timeOwner = owner;
}
using namespace std::chrono;
diff --git a/epoch_base.hpp b/epoch_base.hpp
index fc505d0..f31a32b 100644
--- a/epoch_base.hpp
+++ b/epoch_base.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "property_change_listener.hpp"
+
#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/Time/EpochTime/server.hpp>
@@ -16,64 +18,30 @@
* DBus API for epoch time.
*/
class EpochBase : public sdbusplus::server::object::object <
- sdbusplus::xyz::openbmc_project::Time::server::EpochTime >
+ sdbusplus::xyz::openbmc_project::Time::server::EpochTime >,
+ public PropertyChangeListner
{
public:
friend class TestEpochBase;
- /** @brief Supported time modes
- * NTP Time sourced by Network Time Server
- * MANUAL User of the system need to set the time
- */
- enum class Mode
- {
- NTP,
- MANUAL,
- };
-
- /** @brief Supported time owners
- * BMC Time source may be NTP or MANUAL but it has to be set natively
- * on the BMC. Meaning, host can not set the time. What it also
- * means is that when BMC gets IPMI_SET_SEL_TIME, then its ignored.
- * similarly, when BMC gets IPMI_GET_SEL_TIME, then the BMC's time
- * is returned.
- *
- * HOST Its only IPMI_SEL_SEL_TIME that will set the time on BMC.
- * Meaning, IPMI_GET_SEL_TIME and request to get BMC time will
- * result in same value.
- *
- * SPLIT Both BMC and HOST will maintain their individual clocks but then
- * the time information is stored in BMC. BMC can have either NTP
- * or MANUAL as it's source of time and will set the time directly
- * on the BMC. When IPMI_SET_SEL_TIME is received, then the delta
- * between that and BMC's time is calculated and is stored.
- * When BMC reads the time, the current time is returned.
- * When IPMI_GET_SEL_TIME is received, BMC's time is retrieved and
- * then the delta offset is factored in prior to returning.
- *
- * BOTH: BMC's time is set with whoever that sets the time. Similarly,
- * BMC's time is returned to whoever that asks the time.
- */
- enum class Owner
- {
- BMC,
- HOST,
- SPLIT,
- BOTH,
- };
-
EpochBase(sdbusplus::bus::bus& bus,
const char* objPath);
+ /** @brief Notified on time mode changed */
+ void onModeChanged(Mode mode) override;
+
+ /** @brief Notified on time owner changed */
+ void onOwnerChanged(Owner owner) override;
+
protected:
/** @brief Persistent sdbusplus DBus connection */
sdbusplus::bus::bus& bus;
/** @brief The current time mode */
- Mode timeMode;
+ Mode timeMode = Mode::NTP;
/** @brief The current time owner */
- Owner timeOwner;
+ Owner timeOwner = Owner::BMC;
/** @brief Set current time to system
*
@@ -89,57 +57,6 @@
* @return Microseconds since UTC
*/
std::chrono::microseconds getTime() const;
-
- /** @brief Convert a string to enum Mode
- *
- * Convert the time mode string to enum.
- * Valid strings are "NTP", "MANUAL"
- * If it's not a valid time mode string, return NTP.
- *
- * @param[in] mode - The string of time mode
- *
- * @return The Mode enum
- */
- static Mode convertToMode(const std::string& mode);
-
- /** @brief Convert a string to enum Owner
- *
- * Convert the time owner string to enum.
- * Valid strings are "BMC", "HOST", "SPLIT", "BOTH"
- * If it's not a valid time owner string, return BMC.
- *
- * @param[in] owner - The string of time owner
- *
- * @return The Owner enum
- */
- static Owner convertToOwner(const std::string& owner);
-
- private:
- /** @brief Initialize the time mode and owner */
- void initialize();
-
- /** @brief Set current time mode
- *
- * @param[in] mode - The string of time mode
- */
- void setCurrentTimeMode(const std::string& mode);
-
- /** @brief Set current time owner
- *
- * @param[in] owner - The string of time owner
- */
- void setCurrentTimeOwner(const std::string& owner);
-
- /** @brief Get setting value from settings manager
- *
- * @param[in] setting - The string of the setting to get
- *
- * @return The value of the setting
- */
- std::string getSettings(const char* setting) const;
-
- /** @brief The map maps the string key to enum Owner */
- static const std::map<std::string, Owner> ownerMap;
};
} // namespace time
diff --git a/main.cpp b/main.cpp
index b3f4b57..b8a5adb 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,13 +3,23 @@
#include "config.h"
#include "bmc_epoch.hpp"
#include "host_epoch.hpp"
+#include "manager.hpp"
int main()
{
auto bus = sdbusplus::bus::new_default();
+
+ // Add sdbusplus ObjectManager
+ sdbusplus::server::manager::manager bmcEpochObjManager(bus, OBJPATH_BMC);
+ sdbusplus::server::manager::manager hostEpochObjManager(bus, OBJPATH_HOST);
+
+ phosphor::time::Manager manager(bus);
phosphor::time::BmcEpoch bmc(bus, OBJPATH_BMC);
phosphor::time::HostEpoch host(bus,OBJPATH_HOST);
+ manager.addListener(&bmc);
+ manager.addListener(&host);
+
bus.request_name(BUSNAME);
while (true)
diff --git a/manager.cpp b/manager.cpp
new file mode 100644
index 0000000..c4732f4
--- /dev/null
+++ b/manager.cpp
@@ -0,0 +1,179 @@
+#include "manager.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+namespace rules = sdbusplus::bus::match::rules;
+
+namespace // anonymous
+{
+constexpr auto SETTINGS_SERVICE = "org.openbmc.settings.Host";
+constexpr auto SETTINGS_PATH = "/org/openbmc/settings/host0";
+constexpr auto SETTINGS_INTERFACE = "org.openbmc.settings.Host";
+constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
+constexpr auto METHOD_GET = "Get";
+
+constexpr auto PROPERTY_TIME_MODE = "time_mode";
+constexpr auto PROPERTY_TIME_OWNER = "time_owner";
+
+// TODO: Use new settings in xyz.openbmc_project
+const auto MATCH_PROPERTY_CHANGE =
+ rules::type::signal() +
+ rules::member("PropertiesChanged") +
+ rules::path("/org/openbmc/settings/host0") +
+ rules::interface("org.freedesktop.DBus.Properties");
+
+}
+
+namespace phosphor
+{
+namespace time
+{
+
+using namespace phosphor::logging;
+
+const std::set<std::string>
+Manager::managedProperties = {PROPERTY_TIME_MODE, PROPERTY_TIME_OWNER};
+
+const std::map<std::string, Owner> Manager::ownerMap =
+{
+ { "BMC", Owner::BMC },
+ { "HOST", Owner::HOST },
+ { "SPLIT", Owner::SPLIT },
+ { "BOTH", Owner::BOTH },
+};
+
+Manager::Manager(sdbusplus::bus::bus& bus)
+ : bus(bus),
+ propertyChangeMatch(bus, MATCH_PROPERTY_CHANGE, onPropertyChanged, this)
+{
+ setCurrentTimeMode(getSettings(PROPERTY_TIME_MODE));
+ setCurrentTimeOwner(getSettings(PROPERTY_TIME_OWNER));
+}
+
+void Manager::addListener(PropertyChangeListner* listener)
+{
+ // Notify listener about the initial value
+ listener->onModeChanged(timeMode);
+ listener->onOwnerChanged(timeOwner);
+
+ listeners.insert(listener);
+}
+
+void Manager::onPropertyChanged(const std::string& key,
+ const std::string& value)
+{
+ // TODO: Check pgood
+ // If it's off, notify listners;
+ // If it's on, hold the values and store in persistent storage.
+ // And when pgood turns back to off, notify the listners.
+
+ // TODO: Check dhcp_ntp
+
+ if (key == PROPERTY_TIME_MODE)
+ {
+ setCurrentTimeMode(value);
+ for (const auto& listener : listeners)
+ {
+ listener->onModeChanged(timeMode);
+ }
+ }
+ else if (key == PROPERTY_TIME_OWNER)
+ {
+ setCurrentTimeOwner(value);
+ for (const auto& listener : listeners)
+ {
+ listener->onOwnerChanged(timeOwner);
+ }
+ }
+}
+
+int Manager::onPropertyChanged(sd_bus_message* msg,
+ void* userData,
+ sd_bus_error* retError)
+{
+ using properties = std::map < std::string,
+ sdbusplus::message::variant<int, std::string >>;
+ auto m = sdbusplus::message::message(msg);
+ // message type: sa{sv}as
+ std::string ignore;
+ properties props;
+ m.read(ignore, props);
+ for (const auto& item : props)
+ {
+ if (managedProperties.find(item.first) != managedProperties.end())
+ {
+ static_cast<Manager*>(userData)
+ ->onPropertyChanged(item.first, item.second.get<std::string>());
+ }
+ }
+ return 0;
+}
+
+
+void Manager::setCurrentTimeMode(const std::string& mode)
+{
+ log<level::INFO>("Time mode is changed",
+ entry("MODE=%s", mode.c_str()));
+ timeMode = convertToMode(mode);
+}
+
+void Manager::setCurrentTimeOwner(const std::string& owner)
+{
+ log<level::INFO>("Time owner is changed",
+ entry("OWNER=%s", owner.c_str()));
+ timeOwner = convertToOwner(owner);
+}
+
+std::string Manager::getSettings(const char* value) const
+{
+ sdbusplus::message::variant<std::string> mode;
+ auto method = bus.new_method_call(SETTINGS_SERVICE,
+ SETTINGS_PATH,
+ PROPERTY_INTERFACE,
+ METHOD_GET);
+ method.append(SETTINGS_INTERFACE, value);
+ auto reply = bus.call(method);
+ if (reply)
+ {
+ reply.read(mode);
+ }
+ else
+ {
+ log<level::ERR>("Failed to get settings");
+ }
+
+ return mode.get<std::string>();
+}
+
+Mode Manager::convertToMode(const std::string& mode)
+{
+ if (mode == "NTP")
+ {
+ return Mode::NTP;
+ }
+ else if (mode == "MANUAL")
+ {
+ return Mode::MANUAL;
+ }
+ else
+ {
+ log<level::ERR>("Unrecognized mode",
+ entry("%s", mode.c_str()));
+ return Mode::NTP;
+ }
+}
+
+Owner Manager::convertToOwner(const std::string& owner)
+{
+ auto it = ownerMap.find(owner);
+ if (it == ownerMap.end())
+ {
+ log<level::ERR>("Unrecognized owner",
+ entry("%s", owner.c_str()));
+ return Owner::BMC;
+ }
+ return it->second;
+}
+
+}
+}
diff --git a/manager.hpp b/manager.hpp
new file mode 100644
index 0000000..65240ac
--- /dev/null
+++ b/manager.hpp
@@ -0,0 +1,135 @@
+#pragma once
+
+#include "types.hpp"
+#include "property_change_listener.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+
+#include <set>
+#include <string>
+
+namespace phosphor
+{
+namespace time
+{
+
+/** @class Manager
+ * @brief The manager to handle OpenBMC time.
+ * @details It registers various time related settings and properties signals
+ * on DBus and handle the changes.
+ * For certain properties it also notifies the changed events to listeners.
+ */
+class Manager
+{
+ public:
+ friend class TestManager;
+ explicit Manager(sdbusplus::bus::bus& bus);
+
+ /** @brief Add a listener that will be called
+ * when property is changed
+ **/
+ void addListener(PropertyChangeListner* listener);
+
+ private:
+ /** @brief Persistent sdbusplus DBus connection */
+ sdbusplus::bus::bus& bus;
+
+ /** @brief The match of settings property change */
+ sdbusplus::bus::match::match propertyChangeMatch;
+
+ /** @brief The container to hold all the listeners */
+ std::set<PropertyChangeListner*> listeners;
+
+ /** @brief The current time mode */
+ Mode timeMode;
+
+ /** @brief The current time owner */
+ Owner timeOwner;
+
+ /** @brief Get setting from settingsd service
+ *
+ * @param[in] setting - The string of the setting
+ *
+ * @return The setting value in string
+ */
+ std::string getSettings(const char* setting) const;
+
+ /** @brief Set current time mode
+ *
+ * @param[in] mode - The string of time mode
+ */
+ void setCurrentTimeMode(const std::string& mode);
+
+ /** @brief Set current time owner
+ *
+ * @param[in] owner - The string of time owner
+ */
+ void setCurrentTimeOwner(const std::string& owner);
+
+ /** @brief Notified on settings property changed
+ *
+ * @param[in] key - The name of property that is changed
+ * @param[in] value - The value of the property
+ */
+ void onPropertyChanged(const std::string& key,
+ const std::string& value);
+
+ /** @brief The static function called on settings property changed
+ *
+ * @param[in] msg - Data associated with subscribed signal
+ * @param[in] userData - Pointer to this object instance
+ * @param[out] retError - Not used but required with signal API
+ */
+ static int onPropertyChanged(sd_bus_message* msg,
+ void* userData,
+ sd_bus_error* retError);
+
+ /** @brief Convert a string to enum Mode
+ *
+ * Convert the time mode string to enum.
+ * Valid strings are "NTP", "MANUAL"
+ * If it's not a valid time mode string, return NTP.
+ *
+ * @param[in] mode - The string of time mode
+ *
+ * @return The Mode enum
+ */
+ static Mode convertToMode(const std::string& mode);
+
+ /** @brief Convert a string to enum Owner
+ *
+ * Convert the time owner string to enum.
+ * Valid strings are "BMC", "HOST", "SPLIT", "BOTH"
+ * If it's not a valid time owner string, return BMC.
+ *
+ * @param[in] owner - The string of time owner
+ *
+ * @return The Owner enum
+ */
+ static Owner convertToOwner(const std::string& owner);
+
+ using Updater = std::function<void(const std::string&)>;
+
+ /** @brief Map the property string to functions that shall
+ * be called when the property is changed
+ */
+ const std::map<std::string, Updater> propertyUpdaters =
+ {
+ {"time_mode", std::bind(&Manager::setCurrentTimeMode,
+ this, std::placeholders::_1)},
+ {"time_owner", std::bind(&Manager::setCurrentTimeOwner,
+ this, std::placeholders::_1)}
+ };
+
+ /** @brief The properties that manager shall notify the
+ * listeners when changed
+ */
+ static const std::set<std::string> managedProperties;
+
+ /** @brief The map that maps the string to Owners */
+ static const std::map<std::string, Owner> ownerMap;
+};
+
+}
+}
diff --git a/property_change_listener.hpp b/property_change_listener.hpp
new file mode 100644
index 0000000..de23f47
--- /dev/null
+++ b/property_change_listener.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "types.hpp"
+
+namespace phosphor
+{
+namespace time
+{
+
+class PropertyChangeListner
+{
+ public:
+ virtual ~PropertyChangeListner() {}
+
+ /** @brief Notified on time mode is changed */
+ virtual void onModeChanged(Mode mode) = 0;
+
+ /** @brief Notified on time owner is changed */
+ virtual void onOwnerChanged(Owner owner) = 0;
+};
+
+}
+}
diff --git a/test/Makefile.am b/test/Makefile.am
index bdd258e..b8ea41c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -8,7 +8,8 @@
test_SOURCES = \
TestEpochBase.cpp \
TestBmcEpoch.cpp \
- TestHostEpoch.cpp
+ TestHostEpoch.cpp \
+ TestManager.cpp
test_LDADD = $(top_builddir)/libtimemanager.la
diff --git a/test/TestBmcEpoch.cpp b/test/TestBmcEpoch.cpp
index da65b3e..2fd55a5 100644
--- a/test/TestBmcEpoch.cpp
+++ b/test/TestBmcEpoch.cpp
@@ -3,6 +3,7 @@
#include "bmc_epoch.hpp"
#include "config.h"
+#include "types.hpp"
namespace phosphor
{
@@ -13,9 +14,6 @@
class TestBmcEpoch : public testing::Test
{
public:
- using Mode = EpochBase::Mode;
- using Owner = EpochBase::Owner;
-
sdbusplus::bus::bus bus;
BmcEpoch bmcEpoch;
diff --git a/test/TestEpochBase.cpp b/test/TestEpochBase.cpp
index c3ca7e1..e4a2b68 100644
--- a/test/TestEpochBase.cpp
+++ b/test/TestEpochBase.cpp
@@ -1,6 +1,7 @@
#include <sdbusplus/bus.hpp>
#include <gtest/gtest.h>
+#include "types.hpp"
#include "epoch_base.hpp"
namespace phosphor
@@ -11,9 +12,6 @@
class TestEpochBase : public testing::Test
{
public:
- using Mode = EpochBase::Mode;
- using Owner = EpochBase::Owner;
-
sdbusplus::bus::bus bus;
EpochBase epochBase;
@@ -24,40 +22,38 @@
// Empty
}
- // Proxies for EpochBase's private members and functions
- Mode convertToMode(const std::string& mode)
+ Mode getMode()
{
- return EpochBase::convertToMode(mode);
+ return epochBase.timeMode;
}
- Owner convertToOwner(const std::string& owner)
+ Owner getOwner()
{
- return EpochBase::convertToOwner(owner);
+ return epochBase.timeOwner;
}
};
-TEST_F(TestEpochBase, convertToMode)
+TEST_F(TestEpochBase, onModeChange)
{
- EXPECT_EQ(Mode::NTP, convertToMode("NTP"));
- EXPECT_EQ(Mode::MANUAL, convertToMode("MANUAL"));
+ epochBase.onModeChanged(Mode::NTP);
+ EXPECT_EQ(Mode::NTP, getMode());
- // All unrecognized strings are mapped to Ntp
- EXPECT_EQ(Mode::NTP, convertToMode(""));
- EXPECT_EQ(Mode::NTP, convertToMode("Manual"));
- EXPECT_EQ(Mode::NTP, convertToMode("whatever"));
+ epochBase.onModeChanged(Mode::MANUAL);
+ EXPECT_EQ(Mode::MANUAL, getMode());
}
-
-TEST_F(TestEpochBase, convertToOwner)
+TEST_F(TestEpochBase, onOwnerChange)
{
- EXPECT_EQ(Owner::BMC, convertToOwner("BMC"));
- EXPECT_EQ(Owner::HOST, convertToOwner("HOST"));
- EXPECT_EQ(Owner::SPLIT, convertToOwner("SPLIT"));
- EXPECT_EQ(Owner::BOTH, convertToOwner("BOTH"));
+ epochBase.onOwnerChanged(Owner::BMC);
+ EXPECT_EQ(Owner::BMC, getOwner());
- // All unrecognized strings are mapped to Bmc
- EXPECT_EQ(Owner::BMC, convertToOwner(""));
- EXPECT_EQ(Owner::BMC, convertToOwner("Split"));
- EXPECT_EQ(Owner::BMC, convertToOwner("xyz"));
+ epochBase.onOwnerChanged(Owner::HOST);
+ EXPECT_EQ(Owner::HOST, getOwner());
+
+ epochBase.onOwnerChanged(Owner::SPLIT);
+ EXPECT_EQ(Owner::SPLIT, getOwner());
+
+ epochBase.onOwnerChanged(Owner::BOTH);
+ EXPECT_EQ(Owner::BOTH, getOwner());
}
}
diff --git a/test/TestHostEpoch.cpp b/test/TestHostEpoch.cpp
index dca8d72..ec8ecf1 100644
--- a/test/TestHostEpoch.cpp
+++ b/test/TestHostEpoch.cpp
@@ -3,6 +3,7 @@
#include "host_epoch.hpp"
#include "config.h"
+#include "types.hpp"
namespace phosphor
{
@@ -15,9 +16,6 @@
class TestHostEpoch : public testing::Test
{
public:
- using Mode = EpochBase::Mode;
- using Owner = EpochBase::Owner;
-
sdbusplus::bus::bus bus;
HostEpoch hostEpoch;
diff --git a/test/TestManager.cpp b/test/TestManager.cpp
new file mode 100644
index 0000000..4d9ae73
--- /dev/null
+++ b/test/TestManager.cpp
@@ -0,0 +1,76 @@
+#include <sdbusplus/bus.hpp>
+#include <gtest/gtest.h>
+
+#include "types.hpp"
+#include "manager.hpp"
+
+namespace phosphor
+{
+namespace time
+{
+
+class TestManager : public testing::Test
+{
+ public:
+ sdbusplus::bus::bus bus;
+ Manager manager;
+
+ TestManager()
+ : bus(sdbusplus::bus::new_default()),
+ manager(bus)
+ {
+ // Empty
+ }
+
+ // Proxies for Manager's private members and functions
+ Mode getTimeMode()
+ {
+ return manager.timeMode;
+ }
+ Owner getTimeOwner()
+ {
+ return manager.timeOwner;
+ }
+ Mode convertToMode(const std::string& mode)
+ {
+ return Manager::convertToMode(mode);
+ }
+ Owner convertToOwner(const std::string& owner)
+ {
+ return Manager::convertToOwner(owner);
+ }
+};
+
+TEST_F(TestManager, empty)
+{
+ EXPECT_EQ(Mode::NTP, getTimeMode());
+ EXPECT_EQ(Owner::BMC, getTimeOwner());
+}
+
+TEST_F(TestManager, convertToMode)
+{
+ EXPECT_EQ(Mode::NTP, convertToMode("NTP"));
+ EXPECT_EQ(Mode::MANUAL, convertToMode("MANUAL"));
+
+ // All unrecognized strings are mapped to Ntp
+ EXPECT_EQ(Mode::NTP, convertToMode(""));
+ EXPECT_EQ(Mode::NTP, convertToMode("Manual"));
+ EXPECT_EQ(Mode::NTP, convertToMode("whatever"));
+}
+
+
+TEST_F(TestManager, convertToOwner)
+{
+ EXPECT_EQ(Owner::BMC, convertToOwner("BMC"));
+ EXPECT_EQ(Owner::HOST, convertToOwner("HOST"));
+ EXPECT_EQ(Owner::SPLIT, convertToOwner("SPLIT"));
+ EXPECT_EQ(Owner::BOTH, convertToOwner("BOTH"));
+
+ // All unrecognized strings are mapped to Bmc
+ EXPECT_EQ(Owner::BMC, convertToOwner(""));
+ EXPECT_EQ(Owner::BMC, convertToOwner("Split"));
+ EXPECT_EQ(Owner::BMC, convertToOwner("xyz"));
+}
+
+}
+}
diff --git a/types.hpp b/types.hpp
new file mode 100644
index 0000000..9b88965
--- /dev/null
+++ b/types.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+namespace phosphor
+{
+namespace time
+{
+ /** @brief Supported time modes
+ * NTP Time sourced by Network Time Server
+ * MANUAL User of the system need to set the time
+ */
+ enum class Mode
+ {
+ NTP,
+ MANUAL,
+ };
+
+ /** @brief Supported time owners
+ * BMC Time source may be NTP or MANUAL but it has to be set natively
+ * on the BMC. Meaning, host can not set the time. What it also
+ * means is that when BMC gets IPMI_SET_SEL_TIME, then its ignored.
+ * similarly, when BMC gets IPMI_GET_SEL_TIME, then the BMC's time
+ * is returned.
+ *
+ * HOST Its only IPMI_SEL_SEL_TIME that will set the time on BMC.
+ * Meaning, IPMI_GET_SEL_TIME and request to get BMC time will
+ * result in same value.
+ *
+ * SPLIT Both BMC and HOST will maintain their individual clocks but then
+ * the time information is stored in BMC. BMC can have either NTP
+ * or MANUAL as it's source of time and will set the time directly
+ * on the BMC. When IPMI_SET_SEL_TIME is received, then the delta
+ * between that and BMC's time is calculated and is stored.
+ * When BMC reads the time, the current time is returned.
+ * When IPMI_GET_SEL_TIME is received, BMC's time is retrieved and
+ * then the delta offset is factored in prior to returning.
+ *
+ * BOTH: BMC's time is set with whoever that sets the time. Similarly,
+ * BMC's time is returned to whoever that asks the time.
+ */
+ enum class Owner
+ {
+ BMC,
+ HOST,
+ SPLIT,
+ BOTH,
+ };
+}
+}
+