1 /** 2 * Copyright © 2019 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "extensions/openpower-pels/manager.hpp" 17 #include "log_manager.hpp" 18 #include "mocks.hpp" 19 #include "pel_utils.hpp" 20 21 #include <fstream> 22 #include <regex> 23 #include <sdbusplus/test/sdbus_mock.hpp> 24 #include <xyz/openbmc_project/Common/error.hpp> 25 26 #include <gtest/gtest.h> 27 28 using namespace openpower::pels; 29 namespace fs = std::filesystem; 30 31 using ::testing::NiceMock; 32 33 class TestLogger 34 { 35 public: 36 void log(const std::string& name, phosphor::logging::Entry::Level level, 37 const EventLogger::ADMap& additionalData) 38 { 39 errName = name; 40 errLevel = level; 41 ad = additionalData; 42 } 43 44 std::string errName; 45 phosphor::logging::Entry::Level errLevel; 46 EventLogger::ADMap ad; 47 }; 48 49 class ManagerTest : public CleanPELFiles 50 { 51 public: 52 ManagerTest() : 53 bus(sdbusplus::get_mocked_new(&sdbusInterface)), 54 logManager(bus, "logging_path") 55 { 56 sd_event_default(&sdEvent); 57 } 58 59 ~ManagerTest() 60 { 61 sd_event_unref(sdEvent); 62 } 63 64 NiceMock<sdbusplus::SdBusMock> sdbusInterface; 65 sdbusplus::bus::bus bus; 66 phosphor::logging::internal::Manager logManager; 67 sd_event* sdEvent; 68 TestLogger logger; 69 }; 70 71 fs::path makeTempDir() 72 { 73 char path[] = "/tmp/tempnameXXXXXX"; 74 std::filesystem::path dir = mkdtemp(path); 75 return dir; 76 } 77 78 std::optional<fs::path> findAnyPELInRepo() 79 { 80 // PELs are named <timestamp>_<ID> 81 std::regex expr{"\\d+_\\d+"}; 82 83 for (auto& f : fs::directory_iterator(getPELRepoPath() / "logs")) 84 { 85 if (std::regex_search(f.path().string(), expr)) 86 { 87 return f.path(); 88 } 89 } 90 return std::nullopt; 91 } 92 93 // Test that using the RAWPEL=<file> with the Manager::create() call gets 94 // a PEL saved in the repository. 95 TEST_F(ManagerTest, TestCreateWithPEL) 96 { 97 std::unique_ptr<DataInterfaceBase> dataIface = 98 std::make_unique<MockDataInterface>(); 99 100 openpower::pels::Manager manager{ 101 logManager, std::move(dataIface), 102 std::bind(std::mem_fn(&TestLogger::log), &logger, std::placeholders::_1, 103 std::placeholders::_2, std::placeholders::_3)}; 104 105 // Create a PEL, write it to a file, and pass that filename into 106 // the create function. 107 auto data = pelDataFactory(TestPELType::pelSimple); 108 109 fs::path pelFilename = makeTempDir() / "rawpel"; 110 std::ofstream pelFile{pelFilename}; 111 pelFile.write(reinterpret_cast<const char*>(data.data()), data.size()); 112 pelFile.close(); 113 114 std::string adItem = "RAWPEL=" + pelFilename.string(); 115 std::vector<std::string> additionalData{adItem}; 116 std::vector<std::string> associations; 117 118 manager.create("error message", 42, 0, 119 phosphor::logging::Entry::Level::Error, additionalData, 120 associations); 121 122 // Find the file in the PEL repository directory 123 auto pelPathInRepo = findAnyPELInRepo(); 124 125 EXPECT_TRUE(pelPathInRepo); 126 127 // Now remove it based on its OpenBMC event log ID 128 manager.erase(42); 129 130 pelPathInRepo = findAnyPELInRepo(); 131 132 EXPECT_FALSE(pelPathInRepo); 133 134 fs::remove_all(pelFilename.parent_path()); 135 } 136 137 TEST_F(ManagerTest, TestCreateWithInvalidPEL) 138 { 139 std::unique_ptr<DataInterfaceBase> dataIface = 140 std::make_unique<MockDataInterface>(); 141 142 openpower::pels::Manager manager{ 143 logManager, std::move(dataIface), 144 std::bind(std::mem_fn(&TestLogger::log), &logger, std::placeholders::_1, 145 std::placeholders::_2, std::placeholders::_3)}; 146 147 // Create a PEL, write it to a file, and pass that filename into 148 // the create function. 149 auto data = pelDataFactory(TestPELType::pelSimple); 150 151 // Truncate it to make it invalid. 152 data.resize(200); 153 154 fs::path pelFilename = makeTempDir() / "rawpel"; 155 std::ofstream pelFile{pelFilename}; 156 pelFile.write(reinterpret_cast<const char*>(data.data()), data.size()); 157 pelFile.close(); 158 159 std::string adItem = "RAWPEL=" + pelFilename.string(); 160 std::vector<std::string> additionalData{adItem}; 161 std::vector<std::string> associations; 162 163 manager.create("error message", 42, 0, 164 phosphor::logging::Entry::Level::Error, additionalData, 165 associations); 166 167 // Run the event loop to log the bad PEL event 168 sdeventplus::Event e{sdEvent}; 169 e.run(std::chrono::milliseconds(1)); 170 171 PEL invalidPEL{data}; 172 EXPECT_EQ(logger.errName, "org.open_power.Logging.Error.BadHostPEL"); 173 EXPECT_EQ(logger.errLevel, phosphor::logging::Entry::Level::Error); 174 EXPECT_EQ(std::stoi(logger.ad["PLID"], nullptr, 16), invalidPEL.plid()); 175 EXPECT_EQ(logger.ad["OBMC_LOG_ID"], "42"); 176 EXPECT_EQ(logger.ad["SRC"], (*invalidPEL.primarySRC())->asciiString()); 177 EXPECT_EQ(logger.ad["PEL_SIZE"], std::to_string(data.size())); 178 179 // Check that the bad PEL data was saved to a file. 180 auto badPELData = readPELFile(getPELRepoPath() / "badPEL"); 181 EXPECT_EQ(*badPELData, data); 182 183 fs::remove_all(pelFilename.parent_path()); 184 } 185 186 // Test that the message registry can be used to build a PEL. 187 TEST_F(ManagerTest, TestCreateWithMessageRegistry) 188 { 189 const auto registry = R"( 190 { 191 "PELs": 192 [ 193 { 194 "Name": "xyz.openbmc_project.Error.Test", 195 "Subsystem": "power_supply", 196 "ActionFlags": ["service_action", "report"], 197 "SRC": 198 { 199 "ReasonCode": "0x2030" 200 }, 201 "Documentation": 202 { 203 "Description": "A PGOOD Fault", 204 "Message": "PS had a PGOOD Fault" 205 } 206 } 207 ] 208 } 209 )"; 210 211 auto path = getMessageRegistryPath(); 212 fs::create_directories(path); 213 path /= "message_registry.json"; 214 215 std::ofstream registryFile{path}; 216 registryFile << registry; 217 registryFile.close(); 218 219 std::unique_ptr<DataInterfaceBase> dataIface = 220 std::make_unique<MockDataInterface>(); 221 222 openpower::pels::Manager manager{ 223 logManager, std::move(dataIface), 224 std::bind(std::mem_fn(&TestLogger::log), &logger, std::placeholders::_1, 225 std::placeholders::_2, std::placeholders::_3)}; 226 227 std::vector<std::string> additionalData; 228 std::vector<std::string> associations; 229 230 // Create the event log to create the PEL from. 231 manager.create("xyz.openbmc_project.Error.Test", 33, 0, 232 phosphor::logging::Entry::Level::Error, additionalData, 233 associations); 234 235 // Ensure a PEL was created in the repository 236 auto pelFile = findAnyPELInRepo(); 237 ASSERT_TRUE(pelFile); 238 239 auto data = readPELFile(*pelFile); 240 PEL pel(*data); 241 242 // Spot check it. Other testcases cover the details. 243 EXPECT_TRUE(pel.valid()); 244 EXPECT_EQ(pel.obmcLogID(), 33); 245 EXPECT_EQ(pel.primarySRC().value()->asciiString(), 246 "BD612030 "); 247 248 // Remove it 249 manager.erase(33); 250 pelFile = findAnyPELInRepo(); 251 EXPECT_FALSE(pelFile); 252 253 // Create an event log that can't be found in the registry. 254 manager.create("xyz.openbmc_project.Error.Foo", 33, 0, 255 phosphor::logging::Entry::Level::Error, additionalData, 256 associations); 257 258 // Currently, no PEL should be created. Eventually, a 'missing registry 259 // entry' PEL will be there. 260 pelFile = findAnyPELInRepo(); 261 EXPECT_FALSE(pelFile); 262 } 263 264 TEST_F(ManagerTest, TestDBusMethods) 265 { 266 std::unique_ptr<DataInterfaceBase> dataIface = 267 std::make_unique<MockDataInterface>(); 268 269 Manager manager{logManager, std::move(dataIface), 270 std::bind(std::mem_fn(&TestLogger::log), &logger, 271 std::placeholders::_1, std::placeholders::_2, 272 std::placeholders::_3)}; 273 274 // Create a PEL, write it to a file, and pass that filename into 275 // the create function so there's one in the repo. 276 auto data = pelDataFactory(TestPELType::pelSimple); 277 278 fs::path pelFilename = makeTempDir() / "rawpel"; 279 std::ofstream pelFile{pelFilename}; 280 pelFile.write(reinterpret_cast<const char*>(data.data()), data.size()); 281 pelFile.close(); 282 283 std::string adItem = "RAWPEL=" + pelFilename.string(); 284 std::vector<std::string> additionalData{adItem}; 285 std::vector<std::string> associations; 286 287 manager.create("error message", 42, 0, 288 phosphor::logging::Entry::Level::Error, additionalData, 289 associations); 290 291 // getPELFromOBMCID 292 auto newData = manager.getPELFromOBMCID(42); 293 EXPECT_EQ(newData.size(), data.size()); 294 295 // Read the PEL to get the ID for later 296 PEL pel{newData}; 297 auto id = pel.id(); 298 299 EXPECT_THROW( 300 manager.getPELFromOBMCID(id + 1), 301 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument); 302 303 // getPEL 304 auto unixfd = manager.getPEL(id); 305 306 // Get the size 307 struct stat s; 308 int r = fstat(unixfd, &s); 309 ASSERT_EQ(r, 0); 310 auto size = s.st_size; 311 312 // Open the FD and check the contents 313 FILE* fp = fdopen(unixfd, "r"); 314 ASSERT_NE(fp, nullptr); 315 316 std::vector<uint8_t> fdData; 317 fdData.resize(size); 318 r = fread(fdData.data(), 1, size, fp); 319 EXPECT_EQ(r, size); 320 321 EXPECT_EQ(newData, fdData); 322 323 fclose(fp); 324 325 // Run the event loop to close the FD 326 sdeventplus::Event e{sdEvent}; 327 e.run(std::chrono::milliseconds(1)); 328 329 EXPECT_THROW( 330 manager.getPEL(id + 1), 331 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument); 332 333 // hostAck 334 manager.hostAck(id); 335 336 EXPECT_THROW( 337 manager.hostAck(id + 1), 338 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument); 339 340 // hostReject 341 manager.hostReject(id, Manager::RejectionReason::BadPEL); 342 343 // Run the event loop to log the bad PEL event 344 e.run(std::chrono::milliseconds(1)); 345 346 EXPECT_EQ(logger.errName, "org.open_power.Logging.Error.SentBadPELToHost"); 347 EXPECT_EQ(id, std::stoi(logger.ad["BAD_ID"], nullptr, 16)); 348 349 manager.hostReject(id, Manager::RejectionReason::HostFull); 350 351 EXPECT_THROW( 352 manager.hostReject(id + 1, Manager::RejectionReason::BadPEL), 353 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument); 354 355 fs::remove_all(pelFilename.parent_path()); 356 } 357 358 // An ESEL from the wild 359 const std::string esel{ 360 "00 00 df 00 00 00 00 20 00 04 12 01 6f aa 00 00 " 361 "50 48 00 30 01 00 33 00 00 00 00 07 5c 69 cc 0d 00 00 00 07 5c d5 50 db " 362 "42 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 90 00 00 4e 90 00 00 4e " 363 "55 48 00 18 01 00 09 00 8a 03 40 00 00 00 00 00 ff ff 00 00 00 00 00 00 " 364 "50 53 00 50 01 01 00 00 02 00 00 09 33 2d 00 48 00 00 00 e0 00 00 10 00 " 365 "00 00 00 00 00 20 00 00 00 0c 00 02 00 00 00 fa 00 00 0c e4 00 00 00 12 " 366 "42 43 38 41 33 33 32 44 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 " 367 "20 20 20 20 20 20 20 20 55 44 00 1c 01 06 01 00 02 54 41 4b 00 00 00 06 " 368 "00 00 00 55 00 01 f9 20 00 00 00 00 55 44 00 24 01 06 01 00 01 54 41 4b " 369 "00 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 23 01 00 02 00 05 00 00 " 370 "55 44 00 0c 01 0b 01 00 0f 01 00 00 55 44 00 10 01 04 01 00 0f 9f de 6a " 371 "00 01 00 00 55 44 00 7c 00 0c 01 00 00 13 0c 02 00 fa 0c e4 16 00 01 2c " 372 "0c 1c 16 00 00 fa 0a f0 14 00 00 fa 0b b8 14 00 00 be 09 60 12 00 01 2c " 373 "0d 7a 12 00 00 fa 0c 4e 10 00 00 fa 0c e4 10 00 00 be 0a 8c 16 00 01 2c " 374 "0c 1c 16 00 01 09 09 f6 16 00 00 fa 09 f6 14 00 00 fa 0b b8 14 00 00 fa " 375 "0a f0 14 00 00 be 08 ca 12 00 01 2c 0c e4 12 00 00 fa 0b 54 10 00 00 fa " 376 "0c 2d 10 00 00 be 08 ca 55 44 00 58 01 03 01 00 00 00 00 00 00 05 31 64 " 377 "00 00 00 00 00 05 0d d4 00 00 00 00 40 5f 06 e0 00 00 00 00 40 5d d2 00 " 378 "00 00 00 00 40 57 d3 d0 00 00 00 00 40 58 f6 a0 00 00 00 00 40 54 c9 34 " 379 "00 00 00 00 40 55 9a 10 00 00 00 00 40 4c 0a 80 00 00 00 00 00 00 27 14 " 380 "55 44 01 84 01 01 01 00 48 6f 73 74 62 6f 6f 74 20 42 75 69 6c 64 20 49 " 381 "44 3a 20 68 6f 73 74 62 6f 6f 74 2d 66 65 63 37 34 64 66 2d 70 30 61 38 " 382 "37 64 63 34 2f 68 62 69 63 6f 72 65 2e 62 69 6e 00 49 42 4d 2d 77 69 74 " 383 "68 65 72 73 70 6f 6f 6e 2d 4f 50 39 2d 76 32 2e 34 2d 39 2e 32 33 34 0a " 384 "09 6f 70 2d 62 75 69 6c 64 2d 38 32 66 34 63 66 30 0a 09 62 75 69 6c 64 " 385 "72 6f 6f 74 2d 32 30 31 39 2e 30 35 2e 32 2d 31 30 2d 67 38 39 35 39 31 " 386 "31 34 0a 09 73 6b 69 62 6f 6f 74 2d 76 36 2e 35 2d 31 38 2d 67 34 37 30 " 387 "66 66 62 35 66 32 39 64 37 0a 09 68 6f 73 74 62 6f 6f 74 2d 66 65 63 37 " 388 "34 64 66 2d 70 30 61 38 37 64 63 34 0a 09 6f 63 63 2d 65 34 35 39 37 61 " 389 "62 0a 09 6c 69 6e 75 78 2d 35 2e 32 2e 31 37 2d 6f 70 65 6e 70 6f 77 65 " 390 "72 31 2d 70 64 64 63 63 30 33 33 0a 09 70 65 74 69 74 62 6f 6f 74 2d 76 " 391 "31 2e 31 30 2e 34 0a 09 6d 61 63 68 69 6e 65 2d 78 6d 6c 2d 63 36 32 32 " 392 "63 62 35 2d 70 37 65 63 61 62 33 64 0a 09 68 6f 73 74 62 6f 6f 74 2d 62 " 393 "69 6e 61 72 69 65 73 2d 36 36 65 39 61 36 30 0a 09 63 61 70 70 2d 75 63 " 394 "6f 64 65 2d 70 39 2d 64 64 32 2d 76 34 0a 09 73 62 65 2d 36 30 33 33 30 " 395 "65 30 0a 09 68 63 6f 64 65 2d 68 77 30 39 32 31 31 39 61 2e 6f 70 6d 73 " 396 "74 0a 00 00 55 44 00 70 01 04 01 00 0f 9f de 6a 00 05 00 00 07 5f 1d f4 " 397 "30 32 43 59 34 37 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 398 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " 399 "0b ac 54 02 59 41 31 39 33 34 36 39 37 30 35 38 00 00 00 00 00 00 05 22 " 400 "a1 58 01 8a 00 58 40 20 17 18 4d 2c 00 00 00 fc 01 a1 00 00 55 44 00 14 " 401 "01 08 01 00 00 00 00 01 00 00 00 5a 00 00 00 05 55 44 03 fc 01 15 31 00 " 402 "01 28 00 42 46 41 50 49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 f4 " 403 "00 00 00 00 00 00 03 f4 00 00 00 0b 00 00 00 00 00 00 00 3d 2c 9b c2 84 " 404 "00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 09 " 405 "00 00 00 00 00 11 bd 20 00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 " 406 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 00 00 00 00 00 01 2c " 407 "00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0c 1c 00 00 00 64 00 00 00 3d " 408 "2c 9b d1 11 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 " 409 "00 00 00 0a 00 00 00 00 00 13 b5 a0 00 00 00 00 00 01 f8 80 00 00 00 00 " 410 "00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00 " 411 "00 00 00 be 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0a 8c 00 00 00 64 " 412 "00 00 00 3d 2c 9b df 98 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 " 413 "00 00 00 00 00 00 00 0b 00 00 00 00 00 15 ae 20 00 00 00 00 00 01 f8 80 " 414 "00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 " 415 "00 00 00 00 00 00 00 fa 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0c e4 " 416 "00 00 00 64 00 00 00 3d 2c 9b ea b7 00 00 01 e4 00 48 43 4f fb ed 70 b1 " 417 "00 00 02 01 00 00 00 00 00 00 00 0c 00 00 00 00 00 17 a6 a0 00 00 00 00 " 418 "00 01 f8 80 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 " 419 "00 00 00 12 00 00 00 00 00 00 00 fa 00 00 00 00 00 00 07 d0 00 00 00 00 " 420 "00 00 0c 4e 00 00 00 64 00 00 00 3d 2c 9b f6 27 00 00 01 e4 00 48 43 4f " 421 "fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 0d 00 00 00 00 00 19 9f 20 " 422 "00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 " 423 "00 00 00 00 00 00 00 12 00 00 00 00 00 00 01 2c 00 00 00 00 00 00 07 d0 " 424 "00 00 00 00 00 00 0d 7a 00 00 00 64 00 00 00 3d 2c 9c 05 75 00 00 01 e4 " 425 "00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 0e 00 00 00 00 " 426 "00 1b 97 a0 00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 00 00 00 00 " 427 "00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 be 00 00 00 00 " 428 "00 00 07 d0 00 00 00 00 00 00 09 60 00 00 00 64 00 00 00 3d 2c 9c 11 29 " 429 "00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 00 00 00 0f " 430 "00 00 00 00 00 1d 90 20 00 00 00 00 00 01 f8 80 00 00 00 00 00 00 00 01 " 431 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 00 fa " 432 "00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0b b8 00 00 00 64 00 00 00 3d " 433 "2c 9c 1c 45 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 00 00 00 00 " 434 "00 00 00 10 00 00 00 00 00 1f 88 a0 00 00 00 00 00 01 f8 80 00 00 00 00 " 435 "00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 00 00 00 00 " 436 "00 00 00 fa 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0a f0 00 00 00 64 " 437 "00 00 00 3d 2c 9c 2b 14 00 00 01 e4 00 48 43 4f fb ed 70 b1 00 00 02 01 " 438 "00 00 00 00 00 00 00 11 00 00 00 00 00 21 81 20 00 00 00 00 00 01 f8 80 " 439 "00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 " 440 "00 00 00 00 00 00 01 2c 00 00 00 00 00 00 07 d0 00 00 00 00 00 00 0c 1c " 441 "00 00 00 64 00 00 00 3d 2d 6d 8f 9e 00 00 01 e4 00 00 43 4f 52 d7 9c 36 " 442 "00 00 04 73 00 00 00 1c 00 00 00 3d 2d 6d 99 ac 00 00 01 e4 00 10 43 4f " 443 "3f f2 02 3d 00 00 05 58 00 00 00 00 02 00 00 01 00 00 00 00 00 00 00 40 " 444 "00 00 00 2c 55 44 00 30 01 15 31 00 01 28 00 42 46 41 50 49 5f 44 42 47 " 445 "00 00 00 00 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00 28 00 00 00 00 " 446 "00 00 00 00 55 44 01 74 01 15 31 00 01 28 00 42 46 41 50 49 5f 49 00 00 " 447 "00 00 00 00 00 00 00 00 00 00 01 6c 00 00 00 00 00 00 01 6c 00 00 00 0b " 448 "00 00 00 00 00 00 00 3c 0d 52 18 5e 00 00 01 e4 00 08 43 4f 46 79 94 13 " 449 "00 00 0a 5b 00 00 00 00 00 00 2c 00 00 00 00 24 00 00 00 3c 0d 6b 26 6c " 450 "00 00 01 e4 00 00 43 4f 4e 9b 18 74 00 00 01 03 00 00 00 1c 00 00 00 3c " 451 "12 b9 2d 13 00 00 01 e4 00 00 43 4f ea 31 ed d4 00 00 05 c4 00 00 00 1c " 452 "00 00 00 3c 13 02 73 53 00 00 01 e4 00 00 43 4f ea 31 ed d4 00 00 05 c4 " 453 "00 00 00 1c 00 00 00 3c 13 04 7c 94 00 00 01 e4 00 00 43 4f ea 31 ed d4 " 454 "00 00 05 c4 00 00 00 1c 00 00 00 3c 13 06 ad e1 00 00 01 e4 00 00 43 4f " 455 "ea 31 ed d4 00 00 05 c4 00 00 00 1c 00 00 00 3c 13 07 3f 77 00 00 01 e4 " 456 "00 00 43 4f 5e 4a 55 32 00 00 10 f2 00 00 00 1c 00 00 00 3c 13 07 4e e4 " 457 "00 00 01 e4 00 00 43 4f 5e 4a 55 32 00 00 0d 68 00 00 00 1c 00 00 00 3c " 458 "13 36 79 18 00 00 01 e4 00 00 43 4f ea 31 ed d4 00 00 05 c4 00 00 00 1c " 459 "00 00 00 3d 2c 9c 36 70 00 00 01 e4 00 00 43 4f 23 45 90 97 00 00 02 47 " 460 "00 00 00 1c 00 00 00 3d 2d 6d a3 ed 00 00 01 e4 00 08 43 4f 74 3a 5b 1a " 461 "00 00 04 cc 00 00 00 00 02 00 00 01 00 00 00 24 55 44 00 30 01 15 31 00 " 462 "01 28 00 42 53 43 41 4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 " 463 "00 00 00 00 00 00 00 28 00 00 00 00 00 00 00 00"}; 464 465 TEST_F(ManagerTest, TestESELToRawData) 466 { 467 auto data = Manager::eselToRawData(esel); 468 469 EXPECT_EQ(data.size(), 2464); 470 471 PEL pel{data}; 472 EXPECT_TRUE(pel.valid()); 473 } 474 475 TEST_F(ManagerTest, TestCreateWithESEL) 476 { 477 std::unique_ptr<DataInterfaceBase> dataIface = 478 std::make_unique<MockDataInterface>(); 479 480 openpower::pels::Manager manager{ 481 logManager, std::move(dataIface), 482 std::bind(std::mem_fn(&TestLogger::log), &logger, std::placeholders::_1, 483 std::placeholders::_2, std::placeholders::_3)}; 484 485 { 486 std::string adItem = "ESEL=" + esel; 487 std::vector<std::string> additionalData{adItem}; 488 std::vector<std::string> associations; 489 490 manager.create("error message", 37, 0, 491 phosphor::logging::Entry::Level::Error, additionalData, 492 associations); 493 494 auto data = manager.getPELFromOBMCID(37); 495 PEL pel{data}; 496 EXPECT_TRUE(pel.valid()); 497 } 498 499 // Now an invalid one 500 { 501 std::string adItem = "ESEL=" + esel; 502 503 // Crop it 504 adItem.resize(adItem.size() - 300); 505 506 std::vector<std::string> additionalData{adItem}; 507 std::vector<std::string> associations; 508 509 manager.create("error message", 38, 0, 510 phosphor::logging::Entry::Level::Error, additionalData, 511 associations); 512 513 EXPECT_THROW( 514 manager.getPELFromOBMCID(38), 515 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument); 516 517 // Run the event loop to log the bad PEL event 518 sdeventplus::Event e{sdEvent}; 519 e.run(std::chrono::milliseconds(1)); 520 521 EXPECT_EQ(logger.errName, "org.open_power.Logging.Error.BadHostPEL"); 522 EXPECT_EQ(logger.errLevel, phosphor::logging::Entry::Level::Error); 523 } 524 } 525