1 #include <systemd_target_parser.hpp> 2 #include <gtest/gtest.h> 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <filesystem> 8 9 namespace fs = std::filesystem; 10 11 // Enable debug by default for debug when needed 12 bool gVerbose = true; 13 14 TEST(TargetJsonParser, BasicGoodPath) 15 { 16 auto defaultData1 = R"( 17 { 18 "targets" : { 19 "multi-user.target" : { 20 "errorsToMonitor": ["default"], 21 "errorToLog": "xyz.openbmc_project.State.BMC.Error.MultiUserTargetFailure"}, 22 "obmc-chassis-poweron@0.target" : { 23 "errorsToMonitor": ["timeout", "failed"], 24 "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"} 25 } 26 } 27 )"_json; 28 29 auto defaultData2 = R"( 30 { 31 "targets" : { 32 "obmc-host-start@0.target" : { 33 "errorsToMonitor": ["default"], 34 "errorToLog": "xyz.openbmc_project.State.Host.Error.HostStartFailure"}, 35 "obmc-host-stop@0.target" : { 36 "errorsToMonitor": ["dependency"], 37 "errorToLog": "xyz.openbmc_project.State.Host.Error.HostStopFailure"} 38 } 39 } 40 )"_json; 41 42 std::FILE* tmpf = fopen("/tmp/good_file1.json", "w"); 43 std::fputs(defaultData1.dump().c_str(), tmpf); 44 std::fclose(tmpf); 45 46 tmpf = fopen("/tmp/good_file2.json", "w"); 47 std::fputs(defaultData2.dump().c_str(), tmpf); 48 std::fclose(tmpf); 49 50 std::vector<std::string> filePaths; 51 filePaths.push_back("/tmp/good_file1.json"); 52 filePaths.push_back("/tmp/good_file2.json"); 53 54 TargetErrorData targetData = parseFiles(filePaths); 55 56 EXPECT_EQ(targetData.size(), 4); 57 EXPECT_NE(targetData.find("multi-user.target"), targetData.end()); 58 EXPECT_NE(targetData.find("obmc-chassis-poweron@0.target"), 59 targetData.end()); 60 EXPECT_NE(targetData.find("obmc-host-start@0.target"), targetData.end()); 61 EXPECT_NE(targetData.find("obmc-host-stop@0.target"), targetData.end()); 62 targetEntry tgt = targetData["obmc-chassis-poweron@0.target"]; 63 EXPECT_EQ(tgt.errorToLog, 64 "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"); 65 EXPECT_EQ(tgt.errorsToMonitor.size(), 2); 66 // Check a target with "default" for errorsToMonitor, should have 3 defaults 67 tgt = targetData["obmc-host-start@0.target"]; 68 EXPECT_EQ(tgt.errorsToMonitor.size(), 3); 69 70 std::remove("/tmp/good_file1.json"); 71 std::remove("/tmp/good_file2.json"); 72 } 73 74 TEST(TargetJsonParser, InvalidErrorToMonitor) 75 { 76 auto invalidDataError = R"( 77 { 78 "targets" : { 79 "obmc-chassis-poweron@0.target" : { 80 "errorsToMonitor": ["timeout", "invalid"], 81 "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"} 82 } 83 } 84 )"_json; 85 86 std::FILE* tmpf = fopen("/tmp/invalid_error_file.json", "w"); 87 std::fputs(invalidDataError.dump().c_str(), tmpf); 88 std::fclose(tmpf); 89 90 std::vector<std::string> filePaths; 91 filePaths.push_back("/tmp/invalid_error_file.json"); 92 93 // Verify exception thrown on invalid errorsToMonitor 94 EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths), 95 std::out_of_range); 96 std::remove("/tmp/invalid_error_file.json"); 97 } 98 99 TEST(TargetJsonParser, InvalidFileFormat) 100 { 101 std::FILE* tmpf = fopen("/tmp/invalid_json_file.json", "w"); 102 std::fputs("{\"targets\":{\"missing closing quote}}", tmpf); 103 fclose(tmpf); 104 105 std::vector<std::string> filePaths; 106 filePaths.push_back("/tmp/invalid_json_file.json"); 107 108 // Verify exception thrown on invalid json file format 109 EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths), 110 nlohmann::detail::parse_error); 111 std::remove("/tmp/invalid_json_file.json"); 112 } 113 114 TEST(TargetJsonParser, NotJustDefault) 115 { 116 auto notJustDefault = R"( 117 { 118 "targets" : { 119 "obmc-chassis-poweron@0.target" : { 120 "errorsToMonitor": ["timeout", "default"], 121 "errorToLog": "xyz.openbmc_project.State.Chassis.Error.PowerOnTargetFailure"} 122 } 123 } 124 )"_json; 125 126 std::FILE* tmpf = fopen("/tmp/not_just_default_file.json", "w"); 127 std::fputs(notJustDefault.dump().c_str(), tmpf); 128 std::fclose(tmpf); 129 130 std::vector<std::string> filePaths; 131 filePaths.push_back("/tmp/not_just_default_file.json"); 132 133 // Verify exception thrown on invalid errorsToMonitor 134 EXPECT_THROW(TargetErrorData targetData = parseFiles(filePaths), 135 std::invalid_argument); 136 std::remove("/tmp/not_just_default_file.json"); 137 } 138