1 #include "rde/external_storer_file.hpp" 2 3 #include <sdbusplus/bus.hpp> 4 #include <sdbusplus/test/sdbus_mock.hpp> 5 6 #include <string_view> 7 8 #include <gmock/gmock-matchers.h> 9 #include <gmock/gmock.h> 10 #include <gtest/gtest.h> 11 12 namespace bios_bmc_smm_error_logger 13 { 14 namespace rde 15 { 16 17 using ::testing::_; 18 using ::testing::DoAll; 19 using ::testing::Return; 20 using ::testing::SaveArg; 21 using ::testing::StrEq; 22 23 class MockFileWriter : public FileHandlerInterface 24 { 25 public: 26 MOCK_METHOD(bool, createFolder, (const std::string& path), 27 (const, override)); 28 MOCK_METHOD(bool, createFile, 29 (const std::string& path, const nlohmann::json& jsonPdr), 30 (const, override)); 31 }; 32 33 class ExternalStorerFileTest : public ::testing::Test 34 { 35 public: 36 ExternalStorerFileTest() : 37 bus(sdbusplus::get_mocked_new(&sdbusMock)), 38 mockFileWriter(std::make_unique<MockFileWriter>()) 39 { 40 mockFileWriterPtr = dynamic_cast<MockFileWriter*>(mockFileWriter.get()); 41 42 EXPECT_CALL( 43 sdbusMock, 44 sd_bus_add_object_manager( 45 nullptr, _, 46 StrEq( 47 "/xyz/openbmc_project/external_storer/bios_bmc_smm_error_logger/CPER"))) 48 .WillOnce(Return(0)); 49 50 exStorer = std::make_unique<ExternalStorerFileInterface>( 51 bus, rootPath, std::move(mockFileWriter)); 52 } 53 54 protected: 55 sdbusplus::SdBusMock sdbusMock; 56 sdbusplus::bus_t bus; 57 std::unique_ptr<FileHandlerInterface> mockFileWriter; 58 std::unique_ptr<ExternalStorerFileInterface> exStorer; 59 MockFileWriter* mockFileWriterPtr; 60 const std::string rootPath = "/some/path"; 61 }; 62 63 TEST_F(ExternalStorerFileTest, InvalidJsonTest) 64 { 65 // Try an invalid JSON. 66 std::string jsonStr = "Invalid JSON"; 67 EXPECT_THAT(exStorer->publishJson(jsonStr), false); 68 } 69 70 TEST_F(ExternalStorerFileTest, NoOdataTypeFailureTest) 71 { 72 // Try a JSON without @odata.type. 73 std::string jsonStr = R"( 74 { 75 "@odata.id": "/redfish/v1/Systems/system/Memory/dimm0/MemoryMetrics", 76 "Id":"Metrics" 77 } 78 )"; 79 EXPECT_THAT(exStorer->publishJson(jsonStr), false); 80 } 81 82 TEST_F(ExternalStorerFileTest, LogServiceNoOdataIdTest) 83 { 84 // Try a LogService without @odata.id. 85 std::string jsonStr = R"( 86 { 87 "@odata.type": "#LogService.v1_1_0.LogService","Id":"6F7-C1A7C" 88 } 89 )"; 90 EXPECT_THAT(exStorer->publishJson(jsonStr), false); 91 } 92 93 TEST_F(ExternalStorerFileTest, LogServiceNoIdTest) 94 { 95 // Try a LogService without Id. 96 std::string jsonStr = R"( 97 { 98 "@odata.id": "/redfish/v1/Systems/system/LogServices/6F7-C1A7C", 99 "@odata.type": "#LogService.v1_1_0.LogService" 100 } 101 )"; 102 EXPECT_THAT(exStorer->publishJson(jsonStr), false); 103 } 104 105 TEST_F(ExternalStorerFileTest, LogServiceTest) 106 { 107 // A valid LogService test. 108 std::string jsonStr = R"( 109 { 110 "@odata.id": "/redfish/v1/Systems/system/LogServices/6F7-C1A7C", 111 "@odata.type": "#LogService.v1_1_0.LogService","Id":"6F7-C1A7C" 112 } 113 )"; 114 std::string exServiceFolder = 115 "/some/path/redfish/v1/Systems/system/LogServices/6F7-C1A7C"; 116 std::string exEntriesFolder = 117 "/some/path/redfish/v1/Systems/system/LogServices/6F7-C1A7C/Entries"; 118 nlohmann::json exEntriesJson = "{}"_json; 119 nlohmann::json exServiceJson = nlohmann::json::parse(jsonStr); 120 EXPECT_CALL(*mockFileWriterPtr, createFile(exServiceFolder, exServiceJson)) 121 .WillOnce(Return(true)); 122 EXPECT_CALL(*mockFileWriterPtr, createFile(exEntriesFolder, exEntriesJson)) 123 .WillOnce(Return(true)); 124 EXPECT_THAT(exStorer->publishJson(jsonStr), true); 125 } 126 127 TEST_F(ExternalStorerFileTest, LogEntryWithoutLogServiceTest) 128 { 129 // Try a LogEntry without sending a LogService first. 130 std::string jsonLogEntry = R"( 131 { 132 "@odata.type": "#LogEntry.v1_13_0.LogEntry" 133 } 134 )"; 135 EXPECT_THAT(exStorer->publishJson(jsonLogEntry), false); 136 } 137 138 TEST_F(ExternalStorerFileTest, LogEntryTest) 139 { 140 // Before sending a LogEntry, first we need to push a LogService. 141 std::string jsonLogSerivce = R"( 142 { 143 "@odata.id": "/redfish/v1/Systems/system/LogServices/6F7-C1A7C", 144 "@odata.type": "#LogService.v1_1_0.LogService","Id":"6F7-C1A7C" 145 } 146 )"; 147 std::string exServiceFolder = 148 "/some/path/redfish/v1/Systems/system/LogServices/6F7-C1A7C"; 149 std::string exEntriesFolder = 150 "/some/path/redfish/v1/Systems/system/LogServices/6F7-C1A7C/Entries"; 151 nlohmann::json exEntriesJson = "{}"_json; 152 nlohmann::json exServiceJson = nlohmann::json::parse(jsonLogSerivce); 153 EXPECT_CALL(*mockFileWriterPtr, createFile(exServiceFolder, exServiceJson)) 154 .WillOnce(Return(true)); 155 EXPECT_CALL(*mockFileWriterPtr, createFile(exEntriesFolder, exEntriesJson)) 156 .WillOnce(Return(true)); 157 EXPECT_THAT(exStorer->publishJson(jsonLogSerivce), true); 158 159 // Now send a LogEntry 160 std::string jsonLogEntry = R"( 161 { 162 "@odata.id": "/some/odata/id", 163 "@odata.type": "#LogEntry.v1_13_0.LogEntry" 164 } 165 )"; 166 167 nlohmann::json logEntryOut; 168 EXPECT_CALL(*mockFileWriterPtr, createFile(_, _)) 169 .WillOnce(DoAll(SaveArg<1>(&logEntryOut), Return(true))); 170 171 constexpr const char* dbusPath = 172 "/xyz/openbmc_project/external_storer/bios_bmc_smm_error_logger/CPER/entry0"; 173 constexpr const char* dbusInterface = "xyz.openbmc_project.Common.FilePath"; 174 175 EXPECT_CALL(sdbusMock, sd_bus_add_object_vtable(nullptr, _, StrEq(dbusPath), 176 StrEq(dbusInterface), _, _)) 177 .WillOnce(Return(0)); 178 EXPECT_CALL(sdbusMock, 179 sd_bus_emit_interfaces_added_strv(nullptr, StrEq(dbusPath), _)) 180 .WillOnce(Return(0)); 181 182 EXPECT_THAT(exStorer->publishJson(jsonLogEntry), true); 183 EXPECT_NE(logEntryOut["Id"], nullptr); 184 EXPECT_EQ(logEntryOut["@odata.id"], nullptr); 185 186 EXPECT_CALL(sdbusMock, sd_bus_emit_interfaces_removed_strv( 187 nullptr, StrEq(dbusPath), _)) 188 .WillOnce(Return(0)); 189 } 190 191 TEST_F(ExternalStorerFileTest, OtherSchemaNoOdataIdTest) 192 { 193 // Try a another PDRs without @odata.id. 194 std::string jsonStr = R"( 195 { 196 "@odata.type": "#MemoryMetrics.v1_4_1.MemoryMetrics", 197 "Id":"Metrics" 198 } 199 )"; 200 EXPECT_THAT(exStorer->publishJson(jsonStr), false); 201 } 202 203 TEST_F(ExternalStorerFileTest, OtherSchemaTypeTest) 204 { 205 // A valid MemoryMetrics PDR. 206 std::string jsonStr = R"( 207 { 208 "@odata.id": "/redfish/v1/Systems/system/Memory/dimm0/MemoryMetrics", 209 "@odata.type": "#MemoryMetrics.v1_4_1.MemoryMetrics", 210 "Id": "Metrics" 211 } 212 )"; 213 std::string exFolder = 214 "/some/path/redfish/v1/Systems/system/Memory/dimm0/MemoryMetrics"; 215 nlohmann::json exJson = nlohmann::json::parse(jsonStr); 216 EXPECT_CALL(*mockFileWriterPtr, createFile(exFolder, exJson)) 217 .WillOnce(Return(true)); 218 EXPECT_THAT(exStorer->publishJson(jsonStr), true); 219 } 220 221 } // namespace rde 222 } // namespace bios_bmc_smm_error_logger 223