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