summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac7
-rw-r--r--extensions/openpower-pels/manager.cpp1
-rw-r--r--extensions/openpower-pels/manager.hpp18
-rw-r--r--extensions/openpower-pels/openpower-pels.mk1
-rw-r--r--extensions/openpower-pels/paths.cpp6
-rw-r--r--extensions/openpower-pels/paths.hpp4
-rw-r--r--extensions/openpower-pels/registry.cpp195
-rw-r--r--extensions/openpower-pels/registry.hpp179
-rw-r--r--test/openpower-pels/Makefile.include13
-rw-r--r--test/openpower-pels/paths.cpp13
-rw-r--r--test/openpower-pels/pel_manager_test.cpp3
-rw-r--r--test/openpower-pels/pel_utils.cpp1
-rw-r--r--test/openpower-pels/pel_utils.hpp3
-rw-r--r--test/openpower-pels/registry_test.cpp166
14 files changed, 602 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index ead0a07..e5f2d81 100644
--- a/configure.ac
+++ b/configure.ac
@@ -159,6 +159,13 @@ AC_DEFINE_UNQUOTED([EXTENSION_PERSIST_DIR], ["$EXTENSION_PERSIST_DIR"], \
AM_CONDITIONAL([ENABLE_PEL_EXTENSION], [test "x$enable_openpower_pel_extension" == "xyes"])
+AS_IF([test "x$enable_openpower_pel_extension" == "xyes"],
+ [AC_CHECK_HEADER(
+ nlohmann/json.hpp,
+ [],
+ [AC_MSG_ERROR([Could not find nlohmann/json.hpp])]])
+)
+
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile test/Makefile phosphor-rsyslog-config/Makefile])
AC_CONFIG_FILES([phosphor-logging.pc])
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index ef071bd..fd3670c 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -110,6 +110,7 @@ void Manager::createPEL(const std::string& message, uint32_t obmcLogID,
const std::vector<std::string>& additionalData,
const std::vector<std::string>& associations)
{
+ // TODO: look up the error in _registry and create a PEL
}
} // namespace pels
diff --git a/extensions/openpower-pels/manager.hpp b/extensions/openpower-pels/manager.hpp
index 49ac8bf..5f092f4 100644
--- a/extensions/openpower-pels/manager.hpp
+++ b/extensions/openpower-pels/manager.hpp
@@ -3,6 +3,7 @@
#include "data_interface.hpp"
#include "log_manager.hpp"
#include "paths.hpp"
+#include "registry.hpp"
#include "repository.hpp"
namespace openpower
@@ -10,8 +11,6 @@ namespace openpower
namespace pels
{
-using namespace phosphor::logging;
-
/**
* @brief PEL manager object
*/
@@ -33,7 +32,9 @@ class Manager
explicit Manager(phosphor::logging::internal::Manager& logManager,
std::unique_ptr<DataInterfaceBase>&& dataIface) :
_logManager(logManager),
- _repo(getPELRepoPath()), _dataIface(std::move(dataIface))
+ _repo(getPELRepoPath()),
+ _registry(getMessageRegistryPath() / message::registryFileName),
+ _dataIface(std::move(dataIface))
{
}
@@ -50,7 +51,7 @@ class Manager
* @param[in] associations - the Associations property
*/
void create(const std::string& message, uint32_t obmcLogID,
- uint64_t timestamp, Entry::Level severity,
+ uint64_t timestamp, phosphor::logging::Entry::Level severity,
const std::vector<std::string>& additionalData,
const std::vector<std::string>& associations);
@@ -93,14 +94,14 @@ class Manager
* @param[in] associations - The associations property
*/
void createPEL(const std::string& message, uint32_t obmcLogID,
- uint64_t timestamp, Entry::Level severity,
+ uint64_t timestamp, phosphor::logging::Entry::Level severity,
const std::vector<std::string>& additionalData,
const std::vector<std::string>& associations);
/**
* @brief Reference to phosphor-logging's Manager class
*/
- internal::Manager& _logManager;
+ phosphor::logging::internal::Manager& _logManager;
/**
* @brief The PEL repository object
@@ -108,6 +109,11 @@ class Manager
Repository _repo;
/**
+ * @brief The PEL message registry object
+ */
+ message::Registry _registry;
+
+ /**
* @brief The API the PEL sections use to gather data
*/
std::unique_ptr<DataInterfaceBase> _dataIface;
diff --git a/extensions/openpower-pels/openpower-pels.mk b/extensions/openpower-pels/openpower-pels.mk
index 14e1966..aa69a2e 100644
--- a/extensions/openpower-pels/openpower-pels.mk
+++ b/extensions/openpower-pels/openpower-pels.mk
@@ -10,5 +10,6 @@ phosphor_log_manager_SOURCES += \
extensions/openpower-pels/pel.cpp \
extensions/openpower-pels/pel_values.cpp \
extensions/openpower-pels/private_header.cpp \
+ extensions/openpower-pels/registry.cpp \
extensions/openpower-pels/repository.cpp \
extensions/openpower-pels/user_header.cpp
diff --git a/extensions/openpower-pels/paths.cpp b/extensions/openpower-pels/paths.cpp
index 27e7373..b8ccfe8 100644
--- a/extensions/openpower-pels/paths.cpp
+++ b/extensions/openpower-pels/paths.cpp
@@ -25,6 +25,10 @@ fs::path getPELRepoPath()
return repoPath;
}
-} // namespace pels
+fs::path getMessageRegistryPath()
+{
+ return std::filesystem::path{"/usr/share/phosphor-logging/pels"};
+}
+} // namespace pels
} // namespace openpower
diff --git a/extensions/openpower-pels/paths.hpp b/extensions/openpower-pels/paths.hpp
index 64566d2..91d8c5f 100644
--- a/extensions/openpower-pels/paths.hpp
+++ b/extensions/openpower-pels/paths.hpp
@@ -16,5 +16,9 @@ std::filesystem::path getPELIDFile();
*/
std::filesystem::path getPELRepoPath();
+/**
+ * @brief Returns the path to the message registry JSON file
+ */
+std::filesystem::path getMessageRegistryPath();
} // namespace pels
} // namespace openpower
diff --git a/extensions/openpower-pels/registry.cpp b/extensions/openpower-pels/registry.cpp
new file mode 100644
index 0000000..42ced0c
--- /dev/null
+++ b/extensions/openpower-pels/registry.cpp
@@ -0,0 +1,195 @@
+#include "registry.hpp"
+
+#include "pel_types.hpp"
+#include "pel_values.hpp"
+
+#include <fstream>
+#include <phosphor-logging/log.hpp>
+
+namespace openpower
+{
+namespace pels
+{
+namespace message
+{
+
+namespace pv = pel_values;
+namespace fs = std::filesystem;
+using namespace phosphor::logging;
+
+constexpr auto debugFilePath = "/etc/phosphor-logging/";
+
+namespace helper
+{
+
+uint8_t getSubsystem(const std::string& subsystemName)
+{
+ // Get the actual value to use in the PEL for the string name
+ auto ss = pv::findByName(subsystemName, pv::subsystemValues);
+ if (ss == pv::subsystemValues.end())
+ {
+ // Schema validation should be catching this.
+ log<level::ERR>("Invalid subsystem name used in message registry",
+ entry("SUBSYSTEM=%s", subsystemName.c_str()));
+
+ throw std::runtime_error("Invalid subsystem used in message registry");
+ }
+
+ return std::get<pv::fieldValuePos>(*ss);
+}
+
+uint8_t getSeverity(const std::string& severityName)
+{
+ auto s = pv::findByName(severityName, pv::severityValues);
+ if (s == pv::severityValues.end())
+ {
+ // Schema validation should be catching this.
+ log<level::ERR>("Invalid severity name used in message registry",
+ entry("SEVERITY=%s", severityName.c_str()));
+
+ throw std::runtime_error("Invalid severity used in message registry");
+ }
+
+ return std::get<pv::fieldValuePos>(*s);
+}
+
+uint16_t getActionFlags(const std::vector<std::string>& flags)
+{
+ uint16_t actionFlags = 0;
+
+ // Make the bitmask based on the array of flag names
+ for (const auto& flag : flags)
+ {
+ auto s = pv::findByName(flag, pv::actionFlagsValues);
+ if (s == pv::actionFlagsValues.end())
+ {
+ // Schema validation should be catching this.
+ log<level::ERR>("Invalid action flag name used in message registry",
+ entry("FLAG=%s", flag.c_str()));
+
+ throw std::runtime_error(
+ "Invalid action flag used in message registry");
+ }
+
+ actionFlags |= std::get<pv::fieldValuePos>(*s);
+ }
+
+ return actionFlags;
+}
+
+uint8_t getEventType(const std::string& eventTypeName)
+{
+ auto t = pv::findByName(eventTypeName, pv::eventTypeValues);
+ if (t == pv::eventTypeValues.end())
+ {
+ log<level::ERR>("Invalid event type used in message registry",
+ entry("EVENT_TYPE=%s", eventTypeName.c_str()));
+
+ throw std::runtime_error("Invalid event type used in message registry");
+ }
+ return std::get<pv::fieldValuePos>(*t);
+}
+
+uint8_t getEventScope(const std::string& eventScopeName)
+{
+ auto s = pv::findByName(eventScopeName, pv::eventScopeValues);
+ if (s == pv::eventScopeValues.end())
+ {
+ log<level::ERR>("Invalid event scope used in registry",
+ entry("EVENT_SCOPE=%s", eventScopeName.c_str()));
+
+ throw std::runtime_error(
+ "Invalid event scope used in message registry");
+ }
+ return std::get<pv::fieldValuePos>(*s);
+}
+
+} // namespace helper
+
+std::optional<Entry> Registry::lookup(const std::string& name)
+{
+ // Look in /etc first in case someone put a test file there
+ fs::path debugFile{fs::path{debugFilePath} / registryFileName};
+ nlohmann::json registry;
+ std::ifstream file;
+
+ if (fs::exists(debugFile))
+ {
+ log<level::INFO>("Using debug PEL message registry");
+ file.open(debugFile);
+ }
+ else
+ {
+ file.open(_registryFile);
+ }
+
+ try
+ {
+ registry = nlohmann::json::parse(file);
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>("Error parsing message registry JSON",
+ entry("JSON_ERROR=%s", e.what()));
+ return std::nullopt;
+ }
+
+ // Find an entry with this name in the PEL array.
+ auto e = std::find_if(registry["PELs"].begin(), registry["PELs"].end(),
+ [&name](const auto& j) { return name == j["Name"]; });
+
+ if (e != registry["PELs"].end())
+ {
+ // Fill in the Entry structure from the JSON. Most, but not all, fields
+ // are optional.
+
+ try
+ {
+ Entry entry;
+ entry.name = (*e)["Name"];
+ entry.subsystem = helper::getSubsystem((*e)["Subsystem"]);
+ entry.actionFlags = helper::getActionFlags((*e)["ActionFlags"]);
+
+ if (e->find("MfgActionFlags") != e->end())
+ {
+ entry.mfgActionFlags =
+ helper::getActionFlags((*e)["MfgActionFlags"]);
+ }
+
+ if (e->find("Severity") != e->end())
+ {
+ entry.severity = helper::getSeverity((*e)["Severity"]);
+ }
+
+ if (e->find("MfgSeverity") != e->end())
+ {
+ entry.mfgSeverity = helper::getSeverity((*e)["MfgSeverity"]);
+ }
+
+ if (e->find("EventType") != e->end())
+ {
+ entry.eventType = helper::getEventType((*e)["EventType"]);
+ }
+
+ if (e->find("EventScope") != e->end())
+ {
+ entry.eventScope = helper::getEventScope((*e)["EventScope"]);
+ }
+
+ // TODO: SRC fields
+
+ return entry;
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>("Found invalid message registry field",
+ entry("ERROR=%s", e.what()));
+ }
+ }
+
+ return std::nullopt;
+}
+
+} // namespace message
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/registry.hpp b/extensions/openpower-pels/registry.hpp
new file mode 100644
index 0000000..e56bd42
--- /dev/null
+++ b/extensions/openpower-pels/registry.hpp
@@ -0,0 +1,179 @@
+#pragma once
+#include <filesystem>
+#include <nlohmann/json.hpp>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace openpower
+{
+namespace pels
+{
+namespace message
+{
+
+constexpr auto registryFileName = "message_registry.json";
+
+/**
+ * @brief Represents a message registry entry, which is used for creating a
+ * PEL from an OpenBMC event log.
+ */
+struct Entry
+{
+ /**
+ * @brief The error name, like "xyz.openbmc_project.Error.Foo".
+ */
+ std::string name;
+
+ /**
+ * @brief The PEL subsystem field.
+ */
+ uint8_t subsystem;
+
+ /**
+ * @brief The optional PEL severity field. If not specified, the PEL
+ * will use the severity of the OpenBMC event log.
+ */
+ std::optional<uint8_t> severity;
+
+ /**
+ * @brief The optional severity field to use when in manufacturing tolerance
+ * mode.
+ */
+ std::optional<uint8_t> mfgSeverity;
+
+ /**
+ * @brief The PEL action flags field.
+ */
+ uint16_t actionFlags;
+
+ /**
+ * @brief The optional action flags to use instead when in manufacturing
+ * tolerance mode.
+ */
+ std::optional<uint16_t> mfgActionFlags;
+
+ /**
+ * @brief The PEL event type field. If not specified, higher level code
+ * will decide the value.
+ */
+ std::optional<uint8_t> eventType;
+
+ /**
+ * @brief The PEL event scope field. If not specified, higher level code
+ * will decide the value.
+ */
+ std::optional<uint8_t> eventScope;
+
+ // TODO: SRC related fields
+};
+
+/**
+ * @class Registry
+ *
+ * This class wraps the message registry JSON data and allows one to find
+ * the message registry entry pertaining to the error name.
+ *
+ * So that new registry files can easily be tested, the code will look for
+ * /etc/phosphor-logging/message_registry.json before looking for the real
+ * path.
+ */
+class Registry
+{
+ public:
+ Registry() = delete;
+ ~Registry() = default;
+ Registry(const Registry&) = default;
+ Registry& operator=(const Registry&) = default;
+ Registry(Registry&&) = default;
+ Registry& operator=(Registry&&) = default;
+
+ /**
+ * @brief Constructor
+ * @param[in] registryFile - The path to the file.
+ */
+ explicit Registry(const std::filesystem::path& registryFile) :
+ _registryFile(registryFile)
+ {
+ }
+
+ /**
+ * @brief Find a registry entry based on its error name.
+ *
+ * This function does do some basic sanity checking on the JSON contents,
+ * but there is also an external program that enforces a schema on the
+ * registry JSON that should catch all of these problems ahead of time.
+ *
+ * @param[in] name - The error name, like xyz.openbmc_project.Error.Foo
+ *
+ * @return optional<Entry> A filled in message registry structure if
+ * found, otherwise an empty optional object.
+ */
+ std::optional<Entry> lookup(const std::string& name);
+
+ private:
+ /**
+ * @brief The path to the registry JSON file.
+ */
+ std::filesystem::path _registryFile;
+};
+
+namespace helper
+{
+
+/**
+ * @brief A helper function to get the PEL subsystem value based on
+ * the registry subsystem name.
+ *
+ * @param[in] subsystemName - The registry name for the subsystem
+ *
+ * @return uint8_t The PEL subsystem value
+ */
+uint8_t getSubsystem(const std::string& subsystemName);
+
+/**
+ * @brief A helper function to get the PEL severity value based on
+ * the registry severity name.
+ *
+ * @param[in] severityName - The registry name for the severity
+ *
+ * @return uint8_t The PEL severity value
+ */
+uint8_t getSeverity(const std::string& severityName);
+
+/**
+ * @brief A helper function to get the action flags value based on
+ * the action flag names used in the registry.
+ *
+ * @param[in] flags - The list of flag names from the registry.
+ *
+ * @return uint16_t - The bitfield of flags used in the PEL.
+ */
+uint16_t getActionFlags(const std::vector<std::string>& flags);
+
+/**
+ * @brief A helper function to get the PEL event type value based on
+ * the registry event type name.
+ *
+ * @param[in] eventTypeName - The registry name for the event type
+ *
+ * @return uint8_t The PEL event type value
+ */
+uint8_t getEventType(const std::string& eventTypeName);
+
+/**
+ * @brief A helper function to get the PEL event scope value based on
+ * the registry event scope name.
+ *
+ * @param[in] eventScopeName - The registry name for the event scope
+ *
+ * @return uint8_t The PEL event scope value
+ */
+uint8_t getEventScope(const std::string& eventScopeName);
+
+} // namespace helper
+
+} // namespace message
+
+} // namespace pels
+} // namespace openpower
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index 5705f73..18df9ec 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -10,6 +10,7 @@ check_PROGRAMS += \
pel_values_test \
pel_manager_test \
private_header_test \
+ registry_test \
repository_test \
section_header_test \
stream_test \
@@ -19,7 +20,9 @@ pel_objects = \
$(top_builddir)/extensions/openpower-pels/bcd_time.o \
$(top_builddir)/extensions/openpower-pels/log_id.o \
$(top_builddir)/extensions/openpower-pels/pel.o \
+ $(top_builddir)/extensions/openpower-pels/pel_values.o \
$(top_builddir)/extensions/openpower-pels/private_header.o \
+ $(top_builddir)/extensions/openpower-pels/registry.o \
$(top_builddir)/extensions/openpower-pels/user_header.o
additional_data_test_SOURCES = %reldir%/additional_data_test.cpp
@@ -108,6 +111,16 @@ pel_manager_test_LDADD = \
$(top_builddir)/extensions/openpower-pels/repository.o
pel_manager_test_LDFLAGS = $(test_ldflags)
+registry_test_SOURCES = \
+ %reldir%/registry_test.cpp %reldir%/paths.cpp
+registry_test_CPPFLAGS = $(test_cppflags)
+registry_test_CXXFLAGS = $(test_cxxflags)
+registry_test_LDADD = \
+ $(test_ldadd) \
+ $(top_builddir)/extensions/openpower-pels/registry.o \
+ $(top_builddir)/extensions/openpower-pels/pel_values.o
+registry_test_LDFLAGS = $(test_ldflags)
+
mtms_test_SOURCES = %reldir%/mtms_test.cpp
mtms_test_CPPFLAGS = $(test_cppflags)
mtms_test_CXXFLAGS = $(test_cxxflags)
diff --git a/test/openpower-pels/paths.cpp b/test/openpower-pels/paths.cpp
index 27f4bce..502fcf0 100644
--- a/test/openpower-pels/paths.cpp
+++ b/test/openpower-pels/paths.cpp
@@ -35,5 +35,18 @@ std::filesystem::path getPELRepoPath()
return repoPath;
}
+std::filesystem::path getMessageRegistryPath()
+{
+ static std::string registryPath;
+
+ if (registryPath.empty())
+ {
+ char templ[] = "/tmp/msgregtestXXXXXX";
+ registryPath = mkdtemp(templ);
+ }
+
+ return registryPath;
+}
+
} // namespace pels
} // namespace openpower
diff --git a/test/openpower-pels/pel_manager_test.cpp b/test/openpower-pels/pel_manager_test.cpp
index 0a82141..61fbedd 100644
--- a/test/openpower-pels/pel_manager_test.cpp
+++ b/test/openpower-pels/pel_manager_test.cpp
@@ -45,7 +45,8 @@ TEST_F(ManagerTest, TestCreateWithPEL)
std::vector<std::string> additionalData{adItem};
std::vector<std::string> associations;
- manager.create("error message", 42, 0, Entry::Level::Error, additionalData,
+ manager.create("error message", 42, 0,
+ phosphor::logging::Entry::Level::Error, additionalData,
associations);
// We don't know the exact name, but a file should have been added to the
diff --git a/test/openpower-pels/pel_utils.cpp b/test/openpower-pels/pel_utils.cpp
index 46ec8ed..3e0ac01 100644
--- a/test/openpower-pels/pel_utils.cpp
+++ b/test/openpower-pels/pel_utils.cpp
@@ -13,6 +13,7 @@ using namespace openpower::pels;
std::filesystem::path CleanLogID::pelIDFile{};
std::filesystem::path CleanPELFiles::pelIDFile{};
std::filesystem::path CleanPELFiles::repoPath{};
+std::filesystem::path CleanPELFiles::registryPath{};
constexpr uint8_t simplePEL[] = {
// private header section header
diff --git a/test/openpower-pels/pel_utils.hpp b/test/openpower-pels/pel_utils.hpp
index 262a6e7..e61bea2 100644
--- a/test/openpower-pels/pel_utils.hpp
+++ b/test/openpower-pels/pel_utils.hpp
@@ -33,6 +33,7 @@ class CleanPELFiles : public ::testing::Test
{
pelIDFile = openpower::pels::getPELIDFile();
repoPath = openpower::pels::getPELRepoPath();
+ registryPath = openpower::pels::getMessageRegistryPath();
}
static void TearDownTestCase()
@@ -40,10 +41,12 @@ class CleanPELFiles : public ::testing::Test
std::filesystem::remove_all(
std::filesystem::path{pelIDFile}.parent_path());
std::filesystem::remove_all(repoPath);
+ std::filesystem::remove_all(registryPath);
}
static std::filesystem::path pelIDFile;
static std::filesystem::path repoPath;
+ static std::filesystem::path registryPath;
};
/**
diff --git a/test/openpower-pels/registry_test.cpp b/test/openpower-pels/registry_test.cpp
new file mode 100644
index 0000000..2107725
--- /dev/null
+++ b/test/openpower-pels/registry_test.cpp
@@ -0,0 +1,166 @@
+#include "extensions/openpower-pels/registry.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <nlohmann/json.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels::message;
+namespace fs = std::filesystem;
+
+const auto registryData = R"(
+{
+ "PELs":
+ [
+ {
+ "Name": "xyz.openbmc_project.Power.Fault",
+ "Subsystem": "power_supply",
+ "ActionFlags": ["service_action", "report"],
+
+ "SRC":
+ {
+ "ReasonCode": "0x2030"
+ }
+ },
+
+ {
+ "Name": "xyz.openbmc_project.Power.OverVoltage",
+ "Subsystem": "power_control_hw",
+ "Severity": "unrecoverable",
+ "MfgSeverity": "non_error",
+ "ActionFlags": ["service_action", "report", "call_home"],
+ "MfgActionFlags": ["hidden"],
+
+ "SRC":
+ {
+ "ReasonCode": "0x2333",
+ "Type": "BD",
+ "SymptomIDFields": ["SRCWord5", "SRCWord6", "SRCWord7"],
+ "PowerFault": true,
+ "Words6To9":
+ {
+ "6":
+ {
+ "description": "Failing unit number",
+ "AdditionalDataPropSource": "PS_NUM"
+ },
+
+ "7":
+ {
+ "description": "bad voltage",
+ "AdditionalDataPropSource": "VOLTAGE"
+ }
+ }
+ }
+ }
+ ]
+}
+)";
+
+class RegistryTest : public ::testing::Test
+{
+ protected:
+ static void SetUpTestCase()
+ {
+ char path[] = "/tmp/regtestXXXXXX";
+ regDir = mkdtemp(path);
+ }
+
+ static void TearDownTestCase()
+ {
+ fs::remove_all(regDir);
+ }
+
+ static std::string writeData(const char* data)
+ {
+ fs::path path = regDir / "registry.json";
+ std::ofstream stream{path};
+ stream << data;
+ return path;
+ }
+
+ static fs::path regDir;
+};
+
+fs::path RegistryTest::regDir{};
+
+TEST_F(RegistryTest, TestNoEntry)
+{
+ auto path = RegistryTest::writeData(registryData);
+ Registry registry{path};
+
+ auto entry = registry.lookup("foo");
+ EXPECT_FALSE(entry);
+}
+
+TEST_F(RegistryTest, TestFindEntry)
+{
+ auto path = RegistryTest::writeData(registryData);
+ Registry registry{path};
+
+ auto entry = registry.lookup("xyz.openbmc_project.Power.OverVoltage");
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage");
+ EXPECT_EQ(entry->subsystem, 0x62);
+ EXPECT_EQ(*(entry->severity), 0x40);
+ EXPECT_EQ(*(entry->mfgSeverity), 0x00);
+ EXPECT_EQ(entry->actionFlags, 0xA800);
+ EXPECT_EQ(*(entry->mfgActionFlags), 0x4000);
+ EXPECT_FALSE(entry->eventType);
+ EXPECT_FALSE(entry->eventScope);
+
+ // TODO: compare SRC fields
+}
+
+// Check the entry that mostly uses defaults
+TEST_F(RegistryTest, TestFindEntryMinimal)
+{
+ auto path = RegistryTest::writeData(registryData);
+ Registry registry{path};
+
+ auto entry = registry.lookup("xyz.openbmc_project.Power.Fault");
+ ASSERT_TRUE(entry);
+ EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.Fault");
+ EXPECT_EQ(entry->subsystem, 0x61);
+ EXPECT_FALSE(entry->severity);
+ EXPECT_FALSE(entry->mfgSeverity);
+ EXPECT_FALSE(entry->mfgActionFlags);
+ EXPECT_EQ(entry->actionFlags, 0xA000);
+ EXPECT_FALSE(entry->eventType);
+ EXPECT_FALSE(entry->eventScope);
+}
+
+TEST_F(RegistryTest, TestBadJSON)
+{
+ auto path = RegistryTest::writeData("bad {} json");
+
+ Registry registry{path};
+
+ EXPECT_FALSE(registry.lookup("foo"));
+}
+
+// Test the helper functions the use the pel_values data.
+TEST_F(RegistryTest, TestHelperFunctions)
+{
+ using namespace openpower::pels::message::helper;
+ EXPECT_EQ(getSubsystem("input_power_source"), 0xA1);
+ EXPECT_THROW(getSubsystem("foo"), std::runtime_error);
+
+ EXPECT_EQ(getSeverity("symptom_recovered"), 0x71);
+ EXPECT_THROW(getSeverity("foo"), std::runtime_error);
+
+ EXPECT_EQ(getEventType("dump_notification"), 0x08);
+ EXPECT_THROW(getEventType("foo"), std::runtime_error);
+
+ EXPECT_EQ(getEventScope("possibly_multiple_platforms"), 0x04);
+ EXPECT_THROW(getEventScope("foo"), std::runtime_error);
+
+ std::vector<std::string> flags{"service_action", "dont_report",
+ "termination"};
+ EXPECT_EQ(getActionFlags(flags), 0x9100);
+
+ flags.clear();
+ flags.push_back("foo");
+ EXPECT_THROW(getActionFlags(flags), std::runtime_error);
+}
OpenPOWER on IntegriCloud