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