sysd_monitor: Parse json file(s)
Parse the json file(s) into a c++ data object that can be used in later
commits to easily check for monitored targets and log appropriate
errors.
Accept a command line parameter to input file and call parsing function
Tested:
- Verified 100% code coverage of new parser cpp
Change-Id: I0bacd80b7f5330eb9cb03d8e3717742ab107bf94
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/test/systemd_parser.cpp b/test/systemd_parser.cpp
new file mode 100644
index 0000000..7ca94b9
--- /dev/null
+++ b/test/systemd_parser.cpp
@@ -0,0 +1,109 @@
+#include <systemd_target_parser.hpp>
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <cstdio>
+#include <cstdlib>
+#include <filesystem>
+
+namespace fs = std::filesystem;
+
+// Enable debug by default for debug when needed
+bool gVerbose = true;
+
+TEST(TargetJsonParser, BasicGoodPath)
+{
+ auto defaultData1 = R"(
+ {
+ "targets" : {
+ "multi-user.target" : {
+ "errorsToMonitor": ["default"],
+ "errorToLog": "xyz.openbmc_project.State.BMC.Error.MultiUserTargetFailure"},
+ "obmc-chassis-poweron@0.target" : {
+ "errorsToMonitor": ["timeout", "failed"],
+ "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"}
+ }
+ }
+ )"_json;
+
+ auto defaultData2 = R"(
+ {
+ "targets" : {
+ "obmc-host-start@0.target" : {
+ "errorsToMonitor": ["default"],
+ "errorToLog": "xyz.openbmc_project.State.Host.Error.HostStartFailure"},
+ "obmc-host-stop@0.target" : {
+ "errorsToMonitor": ["dependency"],
+ "errorToLog": "xyz.openbmc_project.State.Host.Error.HostStopFailure"}
+ }
+ }
+ )"_json;
+
+ std::FILE* tmpf = fopen("/tmp/good_file1.json", "w");
+ std::fputs(defaultData1.dump().c_str(), tmpf);
+ std::fclose(tmpf);
+
+ tmpf = fopen("/tmp/good_file2.json", "w");
+ std::fputs(defaultData2.dump().c_str(), tmpf);
+ std::fclose(tmpf);
+
+ std::vector<std::string> filePaths;
+ filePaths.push_back("/tmp/good_file1.json");
+ filePaths.push_back("/tmp/good_file2.json");
+
+ TargetErrorData targetData = parseFiles(filePaths);
+
+ EXPECT_EQ(targetData.size(), 4);
+ EXPECT_NE(targetData.find("multi-user.target"), targetData.end());
+ EXPECT_NE(targetData.find("obmc-chassis-poweron@0.target"),
+ targetData.end());
+ EXPECT_NE(targetData.find("obmc-host-start@0.target"), targetData.end());
+ EXPECT_NE(targetData.find("obmc-host-stop@0.target"), targetData.end());
+ targetEntry tgt = targetData["obmc-chassis-poweron@0.target"];
+ EXPECT_EQ(tgt.errorToLog,
+ "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure");
+ EXPECT_EQ(tgt.errorsToMonitor.size(), 2);
+
+ std::remove("/tmp/good_file1.json");
+ std::remove("/tmp/good_file2.json");
+}
+
+TEST(TargetJsonParser, InvalidErrorToMonitor)
+{
+ auto invalidDataError = R"(
+ {
+ "targets" : {
+ "obmc-chassis-poweron@0.target" : {
+ "errorsToMonitor": ["timeout", "invalid"],
+ "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"}
+ }
+ }
+ )"_json;
+
+ std::FILE* tmpf = fopen("/tmp/invalid_error_file.json", "w");
+ std::fputs(invalidDataError.dump().c_str(), tmpf);
+ std::fclose(tmpf);
+
+ std::vector<std::string> filePaths;
+ filePaths.push_back("/tmp/invalid_error_file.json");
+
+ // Verify exception thrown on invalid errorsToMonitor
+ EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths),
+ std::out_of_range);
+ std::remove("/tmp/invalid_error_file.json");
+}
+
+TEST(TargetJsonParser, InvalidFileFormat)
+{
+ std::FILE* tmpf = fopen("/tmp/invalid_json_file.json", "w");
+ std::fputs("{\"targets\":{\"missing closing quote}}", tmpf);
+ fclose(tmpf);
+
+ std::vector<std::string> filePaths;
+ filePaths.push_back("/tmp/invalid_json_file.json");
+
+ // Verify exception thrown on invalid json file format
+ EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths),
+ nlohmann::detail::parse_error);
+ std::remove("/tmp/invalid_json_file.json");
+}