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