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/registry.hpp" 17 18 #include <nlohmann/json.hpp> 19 20 #include <filesystem> 21 #include <fstream> 22 23 #include <gtest/gtest.h> 24 25 using namespace openpower::pels::message; 26 using namespace openpower::pels; 27 namespace fs = std::filesystem; 28 29 const auto registryData = R"( 30 { 31 "PELs": 32 [ 33 { 34 "Name": "xyz.openbmc_project.Power.Fault", 35 "Subsystem": "power_supply", 36 37 "SRC": 38 { 39 "ReasonCode": "0x2030" 40 }, 41 42 "Documentation": 43 { 44 "Description": "A PGOOD Fault", 45 "Message": "PS had a PGOOD Fault" 46 } 47 }, 48 49 { 50 "Name": "xyz.openbmc_project.Power.OverVoltage", 51 "Subsystem": "power_control_hw", 52 "Severity": 53 [ 54 { 55 "System": "systemA", 56 "SevValue": "unrecoverable" 57 }, 58 { 59 "System": "systemB", 60 "SevValue": "recovered" 61 }, 62 { 63 "SevValue": "predictive" 64 } 65 ], 66 "MfgSeverity": "non_error", 67 "ActionFlags": ["service_action", "report", "call_home"], 68 "MfgActionFlags": ["hidden"], 69 70 "SRC": 71 { 72 "ReasonCode": "0x2333", 73 "Type": "BD", 74 "SymptomIDFields": ["SRCWord5", "SRCWord6", "SRCWord7"], 75 "Words6To9": 76 { 77 "6": 78 { 79 "Description": "Failing unit number", 80 "AdditionalDataPropSource": "PS_NUM" 81 }, 82 83 "7": 84 { 85 "Description": "bad voltage", 86 "AdditionalDataPropSource": "VOLTAGE" 87 } 88 }, 89 "DeconfigFlag": true, 90 "CheckstopFlag": true 91 }, 92 93 "Documentation": 94 { 95 "Description": "A PGOOD Fault", 96 "Message": "PS %1 had a PGOOD Fault", 97 "MessageArgSources": 98 [ 99 "SRCWord6" 100 ], 101 "Notes": [ 102 "In the UserData section there is a JSON", 103 "dump that provides debug information." 104 ] 105 }, 106 107 "JournalCapture": 108 { 109 "NumLines": 7 110 } 111 }, 112 113 { 114 "Name": "xyz.openbmc_project.Common.Error.Timeout", 115 "PossibleSubsystems": ["processor", "memory"], 116 117 "SRC": 118 { 119 "ReasonCode": "0x2030" 120 }, 121 "Documentation": 122 { 123 "Description": "A PGOOD Fault", 124 "Message": "PS had a PGOOD Fault" 125 } 126 }, 127 128 { 129 "Name": "xyz.openbmc_project.Journal.Capture", 130 "Subsystem": "power_supply", 131 132 "SRC": 133 { 134 "ReasonCode": "0x2030" 135 }, 136 137 "Documentation": 138 { 139 "Description": "journal capture test", 140 "Message": "journal capture test" 141 }, 142 143 "JournalCapture": 144 { 145 "Sections": [ 146 { 147 "NumLines": 5, 148 "SyslogID": "test1" 149 }, 150 { 151 "NumLines": 6, 152 "SyslogID": "test2" 153 } 154 ] 155 } 156 } 157 ] 158 } 159 )"; 160 161 class RegistryTest : public ::testing::Test 162 { 163 protected: 164 static void SetUpTestCase() 165 { 166 char path[] = "/tmp/regtestXXXXXX"; 167 regDir = mkdtemp(path); 168 } 169 170 static void TearDownTestCase() 171 { 172 fs::remove_all(regDir); 173 } 174 175 static std::string writeData(const char* data) 176 { 177 fs::path path = regDir / "registry.json"; 178 std::ofstream stream{path}; 179 stream << data; 180 return path; 181 } 182 183 static fs::path regDir; 184 }; 185 186 fs::path RegistryTest::regDir{}; 187 188 TEST_F(RegistryTest, TestNoEntry) 189 { 190 auto path = RegistryTest::writeData(registryData); 191 Registry registry{path}; 192 193 auto entry = registry.lookup("foo", LookupType::name); 194 EXPECT_FALSE(entry); 195 } 196 197 TEST_F(RegistryTest, TestFindEntry) 198 { 199 auto path = RegistryTest::writeData(registryData); 200 Registry registry{path}; 201 202 auto entry = registry.lookup("xyz.openbmc_project.Power.OverVoltage", 203 LookupType::name); 204 ASSERT_TRUE(entry); 205 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage"); 206 EXPECT_EQ(entry->subsystem, 0x62); 207 208 ASSERT_EQ(entry->severity->size(), 3); 209 EXPECT_EQ((*entry->severity)[0].severity, 0x40); 210 EXPECT_EQ((*entry->severity)[0].system, "systemA"); 211 EXPECT_EQ((*entry->severity)[1].severity, 0x10); 212 EXPECT_EQ((*entry->severity)[1].system, "systemB"); 213 EXPECT_EQ((*entry->severity)[2].severity, 0x20); 214 EXPECT_EQ((*entry->severity)[2].system, ""); 215 216 EXPECT_EQ(entry->mfgSeverity->size(), 1); 217 EXPECT_EQ((*entry->mfgSeverity)[0].severity, 0x00); 218 219 EXPECT_EQ(*(entry->actionFlags), 0xA800); 220 EXPECT_EQ(*(entry->mfgActionFlags), 0x4000); 221 EXPECT_EQ(entry->componentID, 0x2300); 222 EXPECT_FALSE(entry->eventType); 223 EXPECT_FALSE(entry->eventScope); 224 225 EXPECT_EQ(entry->src.type, 0xBD); 226 EXPECT_EQ(entry->src.reasonCode, 0x2333); 227 EXPECT_TRUE(entry->src.deconfigFlag); 228 EXPECT_TRUE(entry->src.checkstopFlag); 229 230 auto& hexwords = entry->src.hexwordADFields; 231 EXPECT_TRUE(hexwords); 232 EXPECT_EQ((*hexwords).size(), 2); 233 234 auto word = (*hexwords).find(6); 235 EXPECT_NE(word, (*hexwords).end()); 236 EXPECT_EQ(std::get<0>(word->second), "PS_NUM"); 237 238 word = (*hexwords).find(7); 239 EXPECT_NE(word, (*hexwords).end()); 240 EXPECT_EQ(std::get<0>(word->second), "VOLTAGE"); 241 242 auto& sid = entry->src.symptomID; 243 EXPECT_TRUE(sid); 244 EXPECT_EQ((*sid).size(), 3); 245 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 5), (*sid).end()); 246 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 6), (*sid).end()); 247 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 7), (*sid).end()); 248 249 EXPECT_EQ(entry->doc.description, "A PGOOD Fault"); 250 EXPECT_EQ(entry->doc.message, "PS %1 had a PGOOD Fault"); 251 auto& hexwordSource = entry->doc.messageArgSources; 252 EXPECT_TRUE(hexwordSource); 253 EXPECT_EQ((*hexwordSource).size(), 1); 254 EXPECT_EQ((*hexwordSource).front(), "SRCWord6"); 255 256 const auto& jc = entry->journalCapture; 257 ASSERT_TRUE(jc); 258 ASSERT_TRUE(std::holds_alternative<size_t>(*jc)); 259 EXPECT_EQ(std::get<size_t>(*jc), 7); 260 261 entry = registry.lookup("0x2333", LookupType::reasonCode); 262 ASSERT_TRUE(entry); 263 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage"); 264 } 265 266 // Check the entry that mostly uses defaults 267 TEST_F(RegistryTest, TestFindEntryMinimal) 268 { 269 auto path = RegistryTest::writeData(registryData); 270 Registry registry{path}; 271 272 auto entry = registry.lookup("xyz.openbmc_project.Power.Fault", 273 LookupType::name); 274 ASSERT_TRUE(entry); 275 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.Fault"); 276 EXPECT_EQ(entry->subsystem, 0x61); 277 EXPECT_FALSE(entry->severity); 278 EXPECT_FALSE(entry->mfgSeverity); 279 EXPECT_FALSE(entry->mfgActionFlags); 280 EXPECT_FALSE(entry->actionFlags); 281 EXPECT_EQ(entry->componentID, 0x2000); 282 EXPECT_FALSE(entry->eventType); 283 EXPECT_FALSE(entry->eventScope); 284 285 EXPECT_EQ(entry->src.reasonCode, 0x2030); 286 EXPECT_EQ(entry->src.type, 0xBD); 287 EXPECT_FALSE(entry->src.hexwordADFields); 288 EXPECT_FALSE(entry->src.symptomID); 289 EXPECT_FALSE(entry->src.deconfigFlag); 290 EXPECT_FALSE(entry->src.checkstopFlag); 291 } 292 293 TEST_F(RegistryTest, TestBadJSON) 294 { 295 auto path = RegistryTest::writeData("bad {} json"); 296 297 Registry registry{path}; 298 299 EXPECT_FALSE(registry.lookup("foo", LookupType::name)); 300 } 301 302 // Test the helper functions the use the pel_values data. 303 TEST_F(RegistryTest, TestHelperFunctions) 304 { 305 using namespace openpower::pels::message::helper; 306 EXPECT_EQ(getSubsystem("input_power_source"), 0xA1); 307 EXPECT_THROW(getSubsystem("foo"), std::runtime_error); 308 309 EXPECT_EQ(getSeverity("symptom_recovered"), 0x71); 310 EXPECT_THROW(getSeverity("foo"), std::runtime_error); 311 312 EXPECT_EQ(getEventType("dump_notification"), 0x08); 313 EXPECT_THROW(getEventType("foo"), std::runtime_error); 314 315 EXPECT_EQ(getEventScope("possibly_multiple_platforms"), 0x04); 316 EXPECT_THROW(getEventScope("foo"), std::runtime_error); 317 318 std::vector<std::string> flags{"service_action", "dont_report", 319 "termination"}; 320 EXPECT_EQ(getActionFlags(flags), 0x9100); 321 322 flags.clear(); 323 flags.push_back("foo"); 324 EXPECT_THROW(getActionFlags(flags), std::runtime_error); 325 } 326 327 TEST_F(RegistryTest, TestGetSRCReasonCode) 328 { 329 using namespace openpower::pels::message::helper; 330 EXPECT_EQ(getSRCReasonCode(R"({"ReasonCode": "0x5555"})"_json, "foo"), 331 0x5555); 332 333 EXPECT_THROW(getSRCReasonCode(R"({"ReasonCode": "ZZZZ"})"_json, "foo"), 334 std::runtime_error); 335 } 336 337 TEST_F(RegistryTest, TestGetSRCType) 338 { 339 using namespace openpower::pels::message::helper; 340 EXPECT_EQ(getSRCType(R"({"Type": "11"})"_json, "foo"), 0x11); 341 EXPECT_EQ(getSRCType(R"({"Type": "BF"})"_json, "foo"), 0xBF); 342 343 EXPECT_THROW(getSRCType(R"({"Type": "1"})"_json, "foo"), 344 std::runtime_error); 345 346 EXPECT_THROW(getSRCType(R"({"Type": "111"})"_json, "foo"), 347 std::runtime_error); 348 } 349 350 TEST_F(RegistryTest, TestGetSRCHexwordFields) 351 { 352 using namespace openpower::pels::message::helper; 353 const auto hexwords = R"( 354 {"Words6To9": 355 { 356 "8": 357 { 358 "Description": "TEST", 359 "AdditionalDataPropSource": "TEST" 360 } 361 } 362 })"_json; 363 364 auto fields = getSRCHexwordFields(hexwords, "foo"); 365 EXPECT_TRUE(fields); 366 auto word = fields->find(8); 367 EXPECT_NE(word, fields->end()); 368 369 const auto theInvalidRWord = R"( 370 {"Words6To9": 371 { 372 "R": 373 { 374 "Description": "TEST", 375 "AdditionalDataPropSource": "TEST" 376 } 377 } 378 })"_json; 379 380 EXPECT_THROW(getSRCHexwordFields(theInvalidRWord, "foo"), 381 std::runtime_error); 382 } 383 384 TEST_F(RegistryTest, TestGetSRCSymptomIDFields) 385 { 386 using namespace openpower::pels::message::helper; 387 const auto sID = R"( 388 { 389 "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord5"] 390 })"_json; 391 392 auto fields = getSRCSymptomIDFields(sID, "foo"); 393 EXPECT_NE(std::find(fields->begin(), fields->end(), 3), fields->end()); 394 EXPECT_NE(std::find(fields->begin(), fields->end(), 4), fields->end()); 395 EXPECT_NE(std::find(fields->begin(), fields->end(), 5), fields->end()); 396 397 const auto badField = R"( 398 { 399 "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord"] 400 })"_json; 401 402 EXPECT_THROW(getSRCSymptomIDFields(badField, "foo"), std::runtime_error); 403 } 404 405 TEST_F(RegistryTest, TestGetComponentID) 406 { 407 using namespace openpower::pels::message::helper; 408 409 // Get it from the JSON 410 auto id = getComponentID(0xBD, 0x4200, R"({"ComponentID":"0x4200"})"_json, 411 "foo"); 412 EXPECT_EQ(id, 0x4200); 413 414 // Get it from the reason code on a 0xBD SRC 415 id = getComponentID(0xBD, 0x6700, R"({})"_json, "foo"); 416 EXPECT_EQ(id, 0x6700); 417 418 // Not present on a 0x11 SRC 419 EXPECT_THROW(getComponentID(0x11, 0x8800, R"({})"_json, "foo"), 420 std::runtime_error); 421 } 422 423 // Test when callouts are in the JSON. 424 TEST_F(RegistryTest, TestGetCallouts) 425 { 426 std::vector<std::string> names; 427 428 { 429 // Callouts without AD, that depend on system type, 430 // where there is a default entry without a system type. 431 auto json = R"( 432 [ 433 { 434 "System": "system1", 435 "CalloutList": 436 [ 437 { 438 "Priority": "high", 439 "LocCode": "P1-C1" 440 }, 441 { 442 "Priority": "low", 443 "LocCode": "P1" 444 }, 445 { 446 "Priority": "low", 447 "SymbolicFRU": "service_docs" 448 }, 449 { 450 "Priority": "low", 451 "SymbolicFRUTrusted": "air_mover", 452 "UseInventoryLocCode": true 453 } 454 ] 455 }, 456 { 457 "CalloutList": 458 [ 459 { 460 "Priority": "medium", 461 "Procedure": "bmc_code" 462 }, 463 { 464 "Priority": "low", 465 "LocCode": "P3-C8", 466 "SymbolicFRUTrusted": "service_docs" 467 } 468 ] 469 470 } 471 ])"_json; 472 473 AdditionalData ad; 474 names.push_back("system1"); 475 476 auto callouts = Registry::getCallouts(json, names, ad); 477 EXPECT_EQ(callouts.size(), 4); 478 EXPECT_EQ(callouts[0].priority, "high"); 479 EXPECT_EQ(callouts[0].locCode, "P1-C1"); 480 EXPECT_EQ(callouts[0].procedure, ""); 481 EXPECT_EQ(callouts[0].symbolicFRU, ""); 482 EXPECT_EQ(callouts[0].symbolicFRUTrusted, ""); 483 EXPECT_EQ(callouts[1].priority, "low"); 484 EXPECT_EQ(callouts[1].locCode, "P1"); 485 EXPECT_EQ(callouts[1].procedure, ""); 486 EXPECT_EQ(callouts[1].symbolicFRU, ""); 487 EXPECT_EQ(callouts[1].symbolicFRUTrusted, ""); 488 EXPECT_EQ(callouts[2].priority, "low"); 489 EXPECT_EQ(callouts[2].locCode, ""); 490 EXPECT_EQ(callouts[2].procedure, ""); 491 EXPECT_EQ(callouts[2].symbolicFRU, "service_docs"); 492 EXPECT_EQ(callouts[2].symbolicFRUTrusted, ""); 493 EXPECT_EQ(callouts[3].priority, "low"); 494 EXPECT_EQ(callouts[3].locCode, ""); 495 EXPECT_EQ(callouts[3].procedure, ""); 496 EXPECT_EQ(callouts[3].symbolicFRU, ""); 497 EXPECT_EQ(callouts[3].symbolicFRUTrusted, "air_mover"); 498 EXPECT_EQ(callouts[3].useInventoryLocCode, true); 499 500 // system2 isn't in the JSON, so it will pick the default one 501 names[0] = "system2"; 502 callouts = Registry::getCallouts(json, names, ad); 503 EXPECT_EQ(callouts.size(), 2); 504 EXPECT_EQ(callouts[0].priority, "medium"); 505 EXPECT_EQ(callouts[0].locCode, ""); 506 EXPECT_EQ(callouts[0].procedure, "bmc_code"); 507 EXPECT_EQ(callouts[0].symbolicFRU, ""); 508 EXPECT_EQ(callouts[1].priority, "low"); 509 EXPECT_EQ(callouts[1].locCode, "P3-C8"); 510 EXPECT_EQ(callouts[1].procedure, ""); 511 EXPECT_EQ(callouts[1].symbolicFRU, ""); 512 EXPECT_EQ(callouts[1].symbolicFRUTrusted, "service_docs"); 513 EXPECT_EQ(callouts[1].useInventoryLocCode, false); 514 } 515 516 // Empty JSON array (treated as an error) 517 { 518 auto json = R"([])"_json; 519 AdditionalData ad; 520 names[0] = "system1"; 521 EXPECT_THROW(Registry::getCallouts(json, names, ad), 522 std::runtime_error); 523 } 524 525 { 526 // Callouts without AD, that depend on system type, 527 // where there isn't a default entry without a system type. 528 auto json = R"( 529 [ 530 { 531 "System": "system1", 532 "CalloutList": 533 [ 534 { 535 "Priority": "high", 536 "LocCode": "P1-C1" 537 }, 538 { 539 "Priority": "low", 540 "LocCode": "P1", 541 "SymbolicFRU": "1234567" 542 } 543 ] 544 }, 545 { 546 "System": "system2", 547 "CalloutList": 548 [ 549 { 550 "Priority": "medium", 551 "LocCode": "P7", 552 "CalloutType": "tool_fru" 553 } 554 ] 555 556 } 557 ])"_json; 558 559 AdditionalData ad; 560 names[0] = "system1"; 561 562 auto callouts = Registry::getCallouts(json, names, ad); 563 EXPECT_EQ(callouts.size(), 2); 564 EXPECT_EQ(callouts[0].priority, "high"); 565 EXPECT_EQ(callouts[0].locCode, "P1-C1"); 566 EXPECT_EQ(callouts[0].procedure, ""); 567 EXPECT_EQ(callouts[0].symbolicFRU, ""); 568 EXPECT_EQ(callouts[0].symbolicFRUTrusted, ""); 569 EXPECT_EQ(callouts[1].priority, "low"); 570 EXPECT_EQ(callouts[1].locCode, "P1"); 571 EXPECT_EQ(callouts[1].procedure, ""); 572 EXPECT_EQ(callouts[1].symbolicFRU, "1234567"); 573 EXPECT_EQ(callouts[1].symbolicFRUTrusted, ""); 574 575 names[0] = "system2"; 576 callouts = Registry::getCallouts(json, names, ad); 577 EXPECT_EQ(callouts.size(), 1); 578 EXPECT_EQ(callouts[0].priority, "medium"); 579 EXPECT_EQ(callouts[0].locCode, "P7"); 580 EXPECT_EQ(callouts[0].procedure, ""); 581 EXPECT_EQ(callouts[0].symbolicFRU, ""); 582 EXPECT_EQ(callouts[0].symbolicFRUTrusted, ""); 583 584 // There is no entry for system3 or a default system, 585 // so this should fail. 586 names[0] = "system3"; 587 EXPECT_THROW(Registry::getCallouts(json, names, ad), 588 std::runtime_error); 589 } 590 591 { 592 // Callouts that use the AdditionalData key PROC_NUM 593 // as an index into them, along with a system type. 594 // It supports PROC_NUMs 0 and 1. 595 auto json = R"( 596 { 597 "ADName": "PROC_NUM", 598 "CalloutsWithTheirADValues": 599 [ 600 { 601 "ADValue": "0", 602 "Callouts": 603 [ 604 { 605 "System": "system3", 606 "CalloutList": 607 [ 608 { 609 "Priority": "high", 610 "LocCode": "P1-C5" 611 }, 612 { 613 "Priority": "medium", 614 "LocCode": "P1-C6", 615 "SymbolicFRU": "1234567" 616 }, 617 { 618 "Priority": "low", 619 "Procedure": "bmc_code", 620 "CalloutType": "config_procedure" 621 } 622 ] 623 }, 624 { 625 "CalloutList": 626 [ 627 { 628 "Priority": "low", 629 "LocCode": "P55" 630 } 631 ] 632 } 633 ] 634 }, 635 { 636 "ADValue": "1", 637 "Callouts": 638 [ 639 { 640 "CalloutList": 641 [ 642 { 643 "Priority": "high", 644 "LocCode": "P1-C6", 645 "CalloutType": "external_fru" 646 } 647 ] 648 } 649 ] 650 } 651 ] 652 })"_json; 653 654 { 655 // Find callouts for PROC_NUM 0 on system3 656 std::vector<std::string> adData{"PROC_NUM=0"}; 657 AdditionalData ad{adData}; 658 names[0] = "system3"; 659 660 auto callouts = Registry::getCallouts(json, names, ad); 661 EXPECT_EQ(callouts.size(), 3); 662 EXPECT_EQ(callouts[0].priority, "high"); 663 EXPECT_EQ(callouts[0].locCode, "P1-C5"); 664 EXPECT_EQ(callouts[0].procedure, ""); 665 EXPECT_EQ(callouts[0].symbolicFRU, ""); 666 EXPECT_EQ(callouts[0].symbolicFRUTrusted, ""); 667 EXPECT_EQ(callouts[1].priority, "medium"); 668 EXPECT_EQ(callouts[1].locCode, "P1-C6"); 669 EXPECT_EQ(callouts[1].procedure, ""); 670 EXPECT_EQ(callouts[1].symbolicFRU, "1234567"); 671 EXPECT_EQ(callouts[1].symbolicFRUTrusted, ""); 672 EXPECT_EQ(callouts[2].priority, "low"); 673 EXPECT_EQ(callouts[2].locCode, ""); 674 EXPECT_EQ(callouts[2].procedure, "bmc_code"); 675 EXPECT_EQ(callouts[2].symbolicFRU, ""); 676 EXPECT_EQ(callouts[2].symbolicFRUTrusted, ""); 677 678 // Find callouts for PROC_NUM 0 that uses the default system entry. 679 names[0] = "system99"; 680 681 callouts = Registry::getCallouts(json, names, ad); 682 EXPECT_EQ(callouts.size(), 1); 683 EXPECT_EQ(callouts[0].priority, "low"); 684 EXPECT_EQ(callouts[0].locCode, "P55"); 685 EXPECT_EQ(callouts[0].procedure, ""); 686 EXPECT_EQ(callouts[0].symbolicFRU, ""); 687 EXPECT_EQ(callouts[0].symbolicFRUTrusted, ""); 688 } 689 { 690 // Find callouts for PROC_NUM 1 that uses a default system entry. 691 std::vector<std::string> adData{"PROC_NUM=1"}; 692 AdditionalData ad{adData}; 693 names[0] = "system1"; 694 695 auto callouts = Registry::getCallouts(json, names, ad); 696 EXPECT_EQ(callouts.size(), 1); 697 EXPECT_EQ(callouts[0].priority, "high"); 698 EXPECT_EQ(callouts[0].locCode, "P1-C6"); 699 EXPECT_EQ(callouts[0].procedure, ""); 700 EXPECT_EQ(callouts[0].symbolicFRU, ""); 701 EXPECT_EQ(callouts[0].symbolicFRUTrusted, ""); 702 } 703 { 704 // There is no entry for PROC_NUM 2, so no callouts 705 std::vector<std::string> adData{"PROC_NUM=2"}; 706 AdditionalData ad{adData}; 707 708 auto callouts = Registry::getCallouts(json, names, ad); 709 EXPECT_TRUE(callouts.empty()); 710 } 711 } 712 713 { 714 // Callouts with a 'CalloutsWhenNoADMatch' section that will 715 // be used when the AdditionalData value doesn't match. 716 auto json = R"( 717 { 718 "ADName": "PROC_NUM", 719 "CalloutsWithTheirADValues": 720 [ 721 { 722 "ADValue": "0", 723 "Callouts": 724 [ 725 { 726 "CalloutList": 727 [ 728 { 729 "Priority": "high", 730 "LocCode": "P0-C0" 731 } 732 ] 733 } 734 ] 735 } 736 ], 737 "CalloutsWhenNoADMatch": [ 738 { 739 "CalloutList": [ 740 { 741 "Priority": "medium", 742 "LocCode": "P1-C1" 743 } 744 ] 745 } 746 ] 747 })"_json; 748 749 // There isn't an entry in the JSON for a PROC_NUM of 8 750 // so it should choose the P1-C1 callout. 751 std::vector<std::string> adData{"PROC_NUM=8"}; 752 AdditionalData ad{adData}; 753 names.clear(); 754 755 auto callouts = Registry::getCallouts(json, names, ad); 756 EXPECT_EQ(callouts.size(), 1); 757 EXPECT_EQ(callouts[0].priority, "medium"); 758 EXPECT_EQ(callouts[0].locCode, "P1-C1"); 759 } 760 } 761 762 TEST_F(RegistryTest, TestNoSubsystem) 763 { 764 auto path = RegistryTest::writeData(registryData); 765 Registry registry{path}; 766 767 auto entry = registry.lookup("xyz.openbmc_project.Common.Error.Timeout", 768 LookupType::name); 769 ASSERT_TRUE(entry); 770 EXPECT_FALSE(entry->subsystem); 771 } 772 773 TEST_F(RegistryTest, TestJournalSectionCapture) 774 { 775 auto path = RegistryTest::writeData(registryData); 776 Registry registry{path}; 777 778 auto entry = registry.lookup("xyz.openbmc_project.Journal.Capture", 779 LookupType::name); 780 ASSERT_TRUE(entry); 781 782 const auto& jc = entry->journalCapture; 783 ASSERT_TRUE(jc); 784 ASSERT_TRUE(std::holds_alternative<AppCaptureList>(*jc)); 785 const auto& acl = std::get<AppCaptureList>(*jc); 786 787 ASSERT_EQ(acl.size(), 2); 788 789 EXPECT_EQ(acl[0].syslogID, "test1"); 790 EXPECT_EQ(acl[0].numLines, 5); 791 792 EXPECT_EQ(acl[1].syslogID, "test2"); 793 EXPECT_EQ(acl[1].numLines, 6); 794 } 795