1693eaed0SAndrew Geissler #include <systemd_target_parser.hpp>
2693eaed0SAndrew Geissler
3693eaed0SAndrew Geissler #include <cstdio>
4693eaed0SAndrew Geissler #include <cstdlib>
5693eaed0SAndrew Geissler #include <filesystem>
6e426b589SAndrew Geissler #include <iostream>
7e426b589SAndrew Geissler
8e426b589SAndrew Geissler #include <gtest/gtest.h>
9693eaed0SAndrew Geissler
10693eaed0SAndrew Geissler namespace fs = std::filesystem;
11693eaed0SAndrew Geissler
12693eaed0SAndrew Geissler // Enable debug by default for debug when needed
13693eaed0SAndrew Geissler bool gVerbose = true;
14693eaed0SAndrew Geissler
TEST(TargetJsonParser,BasicGoodPath)15693eaed0SAndrew Geissler TEST(TargetJsonParser, BasicGoodPath)
16693eaed0SAndrew Geissler {
17693eaed0SAndrew Geissler auto defaultData1 = R"(
18693eaed0SAndrew Geissler {
19693eaed0SAndrew Geissler "targets" : {
20693eaed0SAndrew Geissler "multi-user.target" : {
21693eaed0SAndrew Geissler "errorsToMonitor": ["default"],
22693eaed0SAndrew Geissler "errorToLog": "xyz.openbmc_project.State.BMC.Error.MultiUserTargetFailure"},
23693eaed0SAndrew Geissler "obmc-chassis-poweron@0.target" : {
24693eaed0SAndrew Geissler "errorsToMonitor": ["timeout", "failed"],
25693eaed0SAndrew Geissler "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"}
26693eaed0SAndrew Geissler }
27693eaed0SAndrew Geissler }
28693eaed0SAndrew Geissler )"_json;
29693eaed0SAndrew Geissler
30693eaed0SAndrew Geissler auto defaultData2 = R"(
31693eaed0SAndrew Geissler {
32693eaed0SAndrew Geissler "targets" : {
33693eaed0SAndrew Geissler "obmc-host-start@0.target" : {
34693eaed0SAndrew Geissler "errorsToMonitor": ["default"],
35693eaed0SAndrew Geissler "errorToLog": "xyz.openbmc_project.State.Host.Error.HostStartFailure"},
36693eaed0SAndrew Geissler "obmc-host-stop@0.target" : {
37693eaed0SAndrew Geissler "errorsToMonitor": ["dependency"],
38693eaed0SAndrew Geissler "errorToLog": "xyz.openbmc_project.State.Host.Error.HostStopFailure"}
39693eaed0SAndrew Geissler }
40693eaed0SAndrew Geissler }
41693eaed0SAndrew Geissler )"_json;
42693eaed0SAndrew Geissler
43693eaed0SAndrew Geissler std::FILE* tmpf = fopen("/tmp/good_file1.json", "w");
44693eaed0SAndrew Geissler std::fputs(defaultData1.dump().c_str(), tmpf);
45693eaed0SAndrew Geissler std::fclose(tmpf);
46693eaed0SAndrew Geissler
47693eaed0SAndrew Geissler tmpf = fopen("/tmp/good_file2.json", "w");
48693eaed0SAndrew Geissler std::fputs(defaultData2.dump().c_str(), tmpf);
49693eaed0SAndrew Geissler std::fclose(tmpf);
50693eaed0SAndrew Geissler
51693eaed0SAndrew Geissler std::vector<std::string> filePaths;
52*437f0b27SPavithra Barithaya filePaths.emplace_back("/tmp/good_file1.json");
53*437f0b27SPavithra Barithaya filePaths.emplace_back("/tmp/good_file2.json");
54693eaed0SAndrew Geissler
55693eaed0SAndrew Geissler TargetErrorData targetData = parseFiles(filePaths);
56693eaed0SAndrew Geissler
57693eaed0SAndrew Geissler EXPECT_EQ(targetData.size(), 4);
58693eaed0SAndrew Geissler EXPECT_NE(targetData.find("multi-user.target"), targetData.end());
59693eaed0SAndrew Geissler EXPECT_NE(targetData.find("obmc-chassis-poweron@0.target"),
60693eaed0SAndrew Geissler targetData.end());
61693eaed0SAndrew Geissler EXPECT_NE(targetData.find("obmc-host-start@0.target"), targetData.end());
62693eaed0SAndrew Geissler EXPECT_NE(targetData.find("obmc-host-stop@0.target"), targetData.end());
63693eaed0SAndrew Geissler targetEntry tgt = targetData["obmc-chassis-poweron@0.target"];
64693eaed0SAndrew Geissler EXPECT_EQ(tgt.errorToLog,
65693eaed0SAndrew Geissler "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure");
66693eaed0SAndrew Geissler EXPECT_EQ(tgt.errorsToMonitor.size(), 2);
6775a2614fSAndrew Geissler // Check a target with "default" for errorsToMonitor, should have 3 defaults
6875a2614fSAndrew Geissler tgt = targetData["obmc-host-start@0.target"];
6975a2614fSAndrew Geissler EXPECT_EQ(tgt.errorsToMonitor.size(), 3);
70693eaed0SAndrew Geissler
71693eaed0SAndrew Geissler std::remove("/tmp/good_file1.json");
72693eaed0SAndrew Geissler std::remove("/tmp/good_file2.json");
73693eaed0SAndrew Geissler }
74693eaed0SAndrew Geissler
TEST(TargetJsonParser,InvalidErrorToMonitor)75693eaed0SAndrew Geissler TEST(TargetJsonParser, InvalidErrorToMonitor)
76693eaed0SAndrew Geissler {
77693eaed0SAndrew Geissler auto invalidDataError = R"(
78693eaed0SAndrew Geissler {
79693eaed0SAndrew Geissler "targets" : {
80693eaed0SAndrew Geissler "obmc-chassis-poweron@0.target" : {
81693eaed0SAndrew Geissler "errorsToMonitor": ["timeout", "invalid"],
82693eaed0SAndrew Geissler "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"}
83693eaed0SAndrew Geissler }
84693eaed0SAndrew Geissler }
85693eaed0SAndrew Geissler )"_json;
86693eaed0SAndrew Geissler
87693eaed0SAndrew Geissler std::FILE* tmpf = fopen("/tmp/invalid_error_file.json", "w");
88693eaed0SAndrew Geissler std::fputs(invalidDataError.dump().c_str(), tmpf);
89693eaed0SAndrew Geissler std::fclose(tmpf);
90693eaed0SAndrew Geissler
91693eaed0SAndrew Geissler std::vector<std::string> filePaths;
92*437f0b27SPavithra Barithaya filePaths.emplace_back("/tmp/invalid_error_file.json");
93693eaed0SAndrew Geissler
94693eaed0SAndrew Geissler // Verify exception thrown on invalid errorsToMonitor
95693eaed0SAndrew Geissler EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths),
96693eaed0SAndrew Geissler std::out_of_range);
97693eaed0SAndrew Geissler std::remove("/tmp/invalid_error_file.json");
98693eaed0SAndrew Geissler }
99693eaed0SAndrew Geissler
TEST(TargetJsonParser,InvalidFileFormat)100693eaed0SAndrew Geissler TEST(TargetJsonParser, InvalidFileFormat)
101693eaed0SAndrew Geissler {
102693eaed0SAndrew Geissler std::FILE* tmpf = fopen("/tmp/invalid_json_file.json", "w");
10366a93fc8SPavithra Barithaya std::fputs(R"({"targets":{"missing closing quote}})", tmpf);
104693eaed0SAndrew Geissler fclose(tmpf);
105693eaed0SAndrew Geissler
106693eaed0SAndrew Geissler std::vector<std::string> filePaths;
107*437f0b27SPavithra Barithaya filePaths.emplace_back("/tmp/invalid_json_file.json");
108693eaed0SAndrew Geissler
109693eaed0SAndrew Geissler // Verify exception thrown on invalid json file format
110693eaed0SAndrew Geissler EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths),
111693eaed0SAndrew Geissler nlohmann::detail::parse_error);
112693eaed0SAndrew Geissler std::remove("/tmp/invalid_json_file.json");
113693eaed0SAndrew Geissler }
11475a2614fSAndrew Geissler
TEST(TargetJsonParser,NotJustDefault)11575a2614fSAndrew Geissler TEST(TargetJsonParser, NotJustDefault)
11675a2614fSAndrew Geissler {
11775a2614fSAndrew Geissler auto notJustDefault = R"(
11875a2614fSAndrew Geissler {
11975a2614fSAndrew Geissler "targets" : {
12075a2614fSAndrew Geissler "obmc-chassis-poweron@0.target" : {
12175a2614fSAndrew Geissler "errorsToMonitor": ["timeout", "default"],
12275a2614fSAndrew Geissler "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"}
12375a2614fSAndrew Geissler }
12475a2614fSAndrew Geissler }
12575a2614fSAndrew Geissler )"_json;
12675a2614fSAndrew Geissler
12775a2614fSAndrew Geissler std::FILE* tmpf = fopen("/tmp/not_just_default_file.json", "w");
12875a2614fSAndrew Geissler std::fputs(notJustDefault.dump().c_str(), tmpf);
12975a2614fSAndrew Geissler std::fclose(tmpf);
13075a2614fSAndrew Geissler
13175a2614fSAndrew Geissler std::vector<std::string> filePaths;
132*437f0b27SPavithra Barithaya filePaths.emplace_back("/tmp/not_just_default_file.json");
13375a2614fSAndrew Geissler
13475a2614fSAndrew Geissler // Verify exception thrown on invalid errorsToMonitor
13575a2614fSAndrew Geissler EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths),
13675a2614fSAndrew Geissler std::invalid_argument);
13775a2614fSAndrew Geissler std::remove("/tmp/not_just_default_file.json");
13875a2614fSAndrew Geissler }
139