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