regulators: Add phase_fault_detection to parser
Enhance the JSON configuration file parser to support the new
phase_fault_detection object.
Add gtest test cases to exercise new code.
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I5b987054ef35c8b27d7d984e5e9ec9b4488bf944
diff --git a/phosphor-regulators/src/config_file_parser.cpp b/phosphor-regulators/src/config_file_parser.cpp
index 6527b5f..430d490 100644
--- a/phosphor-regulators/src/config_file_parser.cpp
+++ b/phosphor-regulators/src/config_file_parser.cpp
@@ -759,6 +759,38 @@
return std::make_unique<OrAction>(std::move(actions));
}
+std::unique_ptr<PhaseFaultDetection>
+ parsePhaseFaultDetection(const json& element)
+{
+ verifyIsObject(element);
+ unsigned int propertyCount{0};
+
+ // Optional comments property; value not stored
+ if (element.contains("comments"))
+ {
+ ++propertyCount;
+ }
+
+ // Optional device_id property
+ std::string deviceID{};
+ auto deviceIDIt = element.find("device_id");
+ if (deviceIDIt != element.end())
+ {
+ deviceID = parseString(*deviceIDIt);
+ ++propertyCount;
+ }
+
+ // Required rule_id or actions property
+ std::vector<std::unique_ptr<Action>> actions{};
+ actions = parseRuleIDOrActionsProperty(element);
+ ++propertyCount;
+
+ // Verify no invalid properties exist
+ verifyPropertyCount(element, propertyCount);
+
+ return std::make_unique<PhaseFaultDetection>(std::move(actions), deviceID);
+}
+
PhaseFaultType parsePhaseFaultType(const json& element)
{
std::string value = parseString(element);
diff --git a/phosphor-regulators/src/config_file_parser.hpp b/phosphor-regulators/src/config_file_parser.hpp
index 63c8bf8..05c5b60 100644
--- a/phosphor-regulators/src/config_file_parser.hpp
+++ b/phosphor-regulators/src/config_file_parser.hpp
@@ -35,6 +35,7 @@
#include "not_action.hpp"
#include "or_action.hpp"
#include "phase_fault.hpp"
+#include "phase_fault_detection.hpp"
#include "pmbus_read_sensor_action.hpp"
#include "pmbus_write_vout_command_action.hpp"
#include "presence_detection.hpp"
@@ -256,7 +257,7 @@
parseCompareVPD(const nlohmann::json& element);
/**
- * Parses a JSON element containing a configuration.
+ * Parses a JSON element containing a configuration object.
*
* Returns the corresponding C++ Configuration object.
*
@@ -554,6 +555,19 @@
std::unique_ptr<OrAction> parseOr(const nlohmann::json& element);
/**
+ * Parses a JSON element containing a phase_fault_detection object.
+ *
+ * Returns the corresponding C++ PhaseFaultDetection object.
+ *
+ * Throws an exception if parsing fails.
+ *
+ * @param element JSON element
+ * @return PhaseFaultDetection object
+ */
+std::unique_ptr<PhaseFaultDetection>
+ parsePhaseFaultDetection(const nlohmann::json& element);
+
+/**
* Parses a JSON element containing a PhaseFaultType expressed as a string.
*
* Returns the corresponding PhaseFaultType enum value.
@@ -592,7 +606,7 @@
parsePMBusWriteVoutCommand(const nlohmann::json& element);
/**
- * Parses a JSON element containing a presence detection operation.
+ * Parses a JSON element containing a presence_detection object.
*
* Returns the corresponding C++ PresenceDetection object.
*
@@ -713,7 +727,7 @@
parseSensorDataFormat(const nlohmann::json& element);
/**
- * Parses a JSON element containing a sensor monitoring operation.
+ * Parses a JSON element containing a sensor_monitoring object.
*
* Returns the corresponding C++ SensorMonitoring object.
*
diff --git a/phosphor-regulators/test/config_file_parser_tests.cpp b/phosphor-regulators/test/config_file_parser_tests.cpp
index b48f8b8..79e2cf4 100644
--- a/phosphor-regulators/test/config_file_parser_tests.cpp
+++ b/phosphor-regulators/test/config_file_parser_tests.cpp
@@ -34,6 +34,7 @@
#include "not_action.hpp"
#include "or_action.hpp"
#include "phase_fault.hpp"
+#include "phase_fault_detection.hpp"
#include "pmbus_read_sensor_action.hpp"
#include "pmbus_utils.hpp"
#include "pmbus_write_vout_command_action.hpp"
@@ -3489,6 +3490,156 @@
}
}
+TEST(ConfigFileParserTests, ParsePhaseFaultDetection)
+{
+ // Test where works: actions specified: optional properties not specified
+ {
+ const json element = R"(
+ {
+ "actions": [
+ { "run_rule": "detect_phase_fault_rule" }
+ ]
+ }
+ )"_json;
+ std::unique_ptr<PhaseFaultDetection> phaseFaultDetection =
+ parsePhaseFaultDetection(element);
+ EXPECT_EQ(phaseFaultDetection->getActions().size(), 1);
+ EXPECT_EQ(phaseFaultDetection->getDeviceID(), "");
+ }
+
+ // Test where works: rule_id specified: optional properties specified
+ {
+ const json element = R"(
+ {
+ "comments": [ "Detect phase fault using I/O expander" ],
+ "device_id": "io_expander",
+ "rule_id": "detect_phase_fault_rule"
+ }
+ )"_json;
+ std::unique_ptr<PhaseFaultDetection> phaseFaultDetection =
+ parsePhaseFaultDetection(element);
+ EXPECT_EQ(phaseFaultDetection->getActions().size(), 1);
+ EXPECT_EQ(phaseFaultDetection->getDeviceID(), "io_expander");
+ }
+
+ // Test where fails: Element is not an object
+ try
+ {
+ const json element = R"( [ "foo", "bar" ] )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Element is not an object");
+ }
+
+ // Test where fails: device_id value is invalid
+ try
+ {
+ const json element = R"(
+ {
+ "device_id": 1,
+ "rule_id": "detect_phase_fault_rule"
+ }
+ )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Element is not a string");
+ }
+
+ // Test where fails: rule_id value is invalid
+ try
+ {
+ const json element = R"(
+ {
+ "rule_id": 1
+ }
+ )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Element is not a string");
+ }
+
+ // Test where fails: actions object is invalid
+ try
+ {
+ const json element = R"(
+ {
+ "actions": 1
+ }
+ )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Element is not an array");
+ }
+
+ // Test where fails: Required actions or rule_id property not specified
+ try
+ {
+ const json element = R"(
+ {
+ "device_id": "io_expander"
+ }
+ )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
+ "either rule_id or actions");
+ }
+
+ // Test where fails: Required actions or rule_id property both specified
+ try
+ {
+ const json element = R"(
+ {
+ "rule_id": "detect_phase_fault_rule",
+ "actions": [
+ { "run_rule": "detect_phase_fault_rule" }
+ ]
+ }
+ )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Invalid property combination: Must contain "
+ "either rule_id or actions");
+ }
+
+ // Test where fails: Invalid property specified
+ try
+ {
+ const json element = R"(
+ {
+ "foo": "bar",
+ "actions": [
+ { "run_rule": "detect_phase_fault_rule" }
+ ]
+ }
+ )"_json;
+ parsePhaseFaultDetection(element);
+ ADD_FAILURE() << "Should not have reached this line.";
+ }
+ catch (const std::invalid_argument& e)
+ {
+ EXPECT_STREQ(e.what(), "Element contains an invalid property");
+ }
+}
+
TEST(ConfigFileParserTests, ParsePhaseFaultType)
{
// Test where works: n