blob: 24a52132cf3b54545711ea05798c46776de7dd9d [file] [log] [blame]
Zane Shelley0b8368c2021-03-18 17:33:41 -05001#include <stdio.h>
2
3#include <analyzer/resolution.hpp>
Zane Shelley5d63cef2021-09-17 18:10:17 -05004#include <util/trace.hpp>
5
6#include <regex>
Zane Shelley0b8368c2021-03-18 17:33:41 -05007
8#include "gtest/gtest.h"
9
10// Chip string
11constexpr auto chip_str = "/proc0";
12
13// Unit paths
Zane Shelley5d63cef2021-09-17 18:10:17 -050014constexpr auto proc_str = "";
15constexpr auto iolink_str = "pib/perv24/pauc0/iohs0/smpgroup0";
16constexpr auto omi_str = "pib/perv12/mc0/mi0/mcc0/omi0";
17constexpr auto ocmb_str = "pib/perv12/mc0/mi0/mcc0/omi0/ocmb0";
18constexpr auto core_str = "pib/perv39/eq7/fc1/core1";
Zane Shelley0b8368c2021-03-18 17:33:41 -050019
20// Local implementation of this function.
21namespace analyzer
22{
23
Zane Shelley84721d92021-09-08 13:30:27 -050024//------------------------------------------------------------------------------
25
Zane Shelley96d54862021-09-17 11:16:12 -050026// Helper function to get the root cause chip target path from the service data.
27std::string __getRootCauseChipPath(const ServiceData& i_sd)
28{
29 return std::string{(const char*)i_sd.getRootCause().getChip().getChip()};
30}
31
32//------------------------------------------------------------------------------
33
34// Helper function to get a unit target path from the given unit path, which is
35// a devtree path relative the the containing chip. An empty string indicates
36// the chip target path should be returned.
37std::string __getUnitPath(const std::string& i_chipPath,
38 const std::string& i_unitPath)
39{
40 auto path = i_chipPath; // default, if i_unitPath is empty
41
42 if (!i_unitPath.empty())
43 {
44 path += "/" + i_unitPath;
45 }
46
47 return path;
48}
49
50//------------------------------------------------------------------------------
51
Zane Shelley5d63cef2021-09-17 18:10:17 -050052// Helper function to get the connected target Path on the other side of the
53// given bus.
54std::tuple<std::string, std::string>
55 __getConnectedPath(const std::string& i_rxPath,
56 const callout::BusType& i_busType)
57{
58 std::string txUnitPath{};
59 std::string txChipPath{};
60
61 // Need to get the target type from the RX path.
62 const std::regex re{"(/proc0)(.*)/([a-z]+)([0-9]+)"};
63 std::smatch match;
64 std::regex_match(i_rxPath, match, re);
65 assert(5 == match.size());
66 std::string rxType = match[3].str();
67
68 if (callout::BusType::SMP_BUS == i_busType && "smpgroup" == rxType)
69 {
70 // Use the RX unit path on a different processor.
71 txUnitPath = "/proc1" + match[2].str() + "/" + rxType + match[4].str();
72 txChipPath = "/proc1";
73 }
74 else if (callout::BusType::OMI_BUS == i_busType && "omi" == rxType)
75 {
76 // Append the OCMB to the RX path.
77 txUnitPath = i_rxPath + "/ocmb0";
78 txChipPath = txUnitPath;
79 }
80 else if (callout::BusType::OMI_BUS == i_busType && "ocmb" == rxType)
81 {
82 // Strip the OCMB off of the RX path.
83 txUnitPath = match[1].str() + match[2].str();
84 txChipPath = "/proc0";
85 }
86 else
87 {
88 // This would be a code bug.
89 throw std::logic_error("Unsupported config: i_rxTarget=" + i_rxPath +
90 " i_busType=" + i_busType.getString());
91 }
92
93 assert(!txUnitPath.empty()); // just in case we missed something above
94
95 return std::make_tuple(txUnitPath, txChipPath);
96}
97
98//------------------------------------------------------------------------------
99
Zane Shelley0b8368c2021-03-18 17:33:41 -0500100void HardwareCalloutResolution::resolve(ServiceData& io_sd) const
101{
Zane Shelley96d54862021-09-17 11:16:12 -0500102 // Get the location code and entity path for this target.
103 auto locCode = __getRootCauseChipPath(io_sd);
104 auto entityPath = __getUnitPath(locCode, iv_unitPath);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500105
Zane Shelleyc85716c2021-08-17 10:54:06 -0500106 // Add the actual callout to the service data.
107 nlohmann::json callout;
Zane Shelley96d54862021-09-17 11:16:12 -0500108 callout["LocationCode"] = locCode;
Zane Shelleyc85716c2021-08-17 10:54:06 -0500109 callout["Priority"] = iv_priority.getUserDataString();
110 io_sd.addCallout(callout);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500111
Zane Shelley95135822021-08-23 09:00:05 -0500112 // Add the guard info to the service data.
Zane Shelley96d54862021-09-17 11:16:12 -0500113 Guard guard = io_sd.addGuard(entityPath, iv_guard);
114
115 // Add the callout FFDC to the service data.
116 nlohmann::json ffdc;
117 ffdc["Callout Type"] = "Hardware Callout";
118 ffdc["Target"] = entityPath;
119 ffdc["Priority"] = iv_priority.getRegistryString();
120 ffdc["Guard Type"] = guard.getString();
121 io_sd.addCalloutFFDC(ffdc);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500122}
123
Zane Shelleyc85716c2021-08-17 10:54:06 -0500124//------------------------------------------------------------------------------
125
Zane Shelley5d63cef2021-09-17 18:10:17 -0500126void ConnectedCalloutResolution::resolve(ServiceData& io_sd) const
127{
128 // Get the chip target path from the root cause signature.
129 auto chipPath = __getRootCauseChipPath(io_sd);
130
131 // Get the endpoint target path for the receiving side of the bus.
132 auto rxPath = __getUnitPath(chipPath, iv_unitPath);
133
134 // Get the endpoint target path for the transfer side of the bus.
135 auto txPath = __getConnectedPath(rxPath, iv_busType);
136
137 // Callout the TX endpoint.
138 nlohmann::json txCallout;
139 txCallout["LocationCode"] = std::get<1>(txPath);
140 txCallout["Priority"] = iv_priority.getUserDataString();
141 io_sd.addCallout(txCallout);
142
143 // Guard the TX endpoint.
144 Guard txGuard = io_sd.addGuard(std::get<0>(txPath), iv_guard);
145
146 // Add the callout FFDC to the service data.
147 nlohmann::json ffdc;
148 ffdc["Callout Type"] = "Connected Callout";
149 ffdc["Bus Type"] = iv_busType.getString();
150 ffdc["Target"] = std::get<0>(txPath);
151 ffdc["Priority"] = iv_priority.getRegistryString();
152 ffdc["Guard Type"] = txGuard.getString();
153 io_sd.addCalloutFFDC(ffdc);
154}
155
156//------------------------------------------------------------------------------
157
Zane Shelley4757a7b2021-09-20 22:23:38 -0500158void BusCalloutResolution::resolve(ServiceData& io_sd) const
159{
160 // Get the chip target path from the root cause signature.
161 auto chipPath = __getRootCauseChipPath(io_sd);
162
163 // Get the endpoint target path for the receiving side of the bus.
164 auto rxPath = __getUnitPath(chipPath, iv_unitPath);
165
166 // Get the endpoint target path for the transfer side of the bus.
167 auto txPath = __getConnectedPath(rxPath, iv_busType);
168
169 // Callout the RX endpoint.
170 nlohmann::json rxCallout;
171 rxCallout["LocationCode"] = chipPath;
172 rxCallout["Priority"] = iv_priority.getUserDataString();
173 io_sd.addCallout(rxCallout);
174
175 // Callout the TX endpoint.
176 nlohmann::json txCallout;
177 txCallout["LocationCode"] = std::get<1>(txPath);
178 txCallout["Priority"] = iv_priority.getUserDataString();
179 io_sd.addCallout(txCallout);
180
181 // Callout everything else in between.
182 // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane.
183 // There isn't a devtree object for this, yet. So will need to
184 // hardcode the location code for now. In the future, we will need a
185 // mechanism to make this data driven.
186 nlohmann::json bpCallout;
187 bpCallout["LocationCode"] = "P0";
188 bpCallout["Priority"] = iv_priority.getUserDataString();
189 io_sd.addCallout(bpCallout);
190
191 // Guard the RX endpoint.
192 Guard guard = io_sd.addGuard(rxPath, iv_guard);
193
194 // Guard the TX endpoint.
195 // No need to check return because it is the same as RX target.
196 io_sd.addGuard(std::get<0>(txPath), iv_guard);
197
198 // TODO: Currently no guard for "everything else in between".
199
200 // Add the callout FFDC to the service data.
201 nlohmann::json ffdc;
202 ffdc["Callout Type"] = "Bus Callout";
203 ffdc["Bus Type"] = iv_busType.getString();
204 ffdc["RX Target"] = rxPath;
205 ffdc["TX Target"] = std::get<0>(txPath);
206 ffdc["Priority"] = iv_priority.getRegistryString();
207 ffdc["Guard Type"] = guard.getString();
208 io_sd.addCalloutFFDC(ffdc);
209}
210
211//------------------------------------------------------------------------------
212
Zane Shelleyc85716c2021-08-17 10:54:06 -0500213void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
214{
215 // Add the actual callout to the service data.
216 nlohmann::json callout;
217 callout["Procedure"] = iv_procedure.getString();
218 callout["Priority"] = iv_priority.getUserDataString();
219 io_sd.addCallout(callout);
Zane Shelley96d54862021-09-17 11:16:12 -0500220
221 // Add the callout FFDC to the service data.
222 nlohmann::json ffdc;
223 ffdc["Callout Type"] = "Procedure Callout";
224 ffdc["Procedure"] = iv_procedure.getString();
225 ffdc["Priority"] = iv_priority.getRegistryString();
226 io_sd.addCalloutFFDC(ffdc);
Zane Shelleyc85716c2021-08-17 10:54:06 -0500227}
228
Zane Shelley84721d92021-09-08 13:30:27 -0500229//------------------------------------------------------------------------------
230
231void ClockCalloutResolution::resolve(ServiceData& io_sd) const
232{
Zane Shelley96d54862021-09-17 11:16:12 -0500233 // Add the callout to the service data.
234 // TODO: For P10, the callout is simply the backplane. There isn't a devtree
235 // object for this, yet. So will need to hardcode the location code
236 // for now. In the future, we will need a mechanism to make this data
237 // driven.
Zane Shelley84721d92021-09-08 13:30:27 -0500238 nlohmann::json callout;
Zane Shelley96d54862021-09-17 11:16:12 -0500239 callout["LocationCode"] = "P0";
Zane Shelley84721d92021-09-08 13:30:27 -0500240 callout["Priority"] = iv_priority.getUserDataString();
241 io_sd.addCallout(callout);
242
243 // Add the guard info to the service data.
Zane Shelley96d54862021-09-17 11:16:12 -0500244 // TODO: Still waiting for clock targets to be defined in the device tree.
245 // For get the processor path for the FFDC.
246 // static const std::map<callout::ClockType, std::string> m = {
247 // {callout::ClockType::OSC_REF_CLOCK_0, ""},
248 // {callout::ClockType::OSC_REF_CLOCK_1, ""},
249 // };
250 // auto target = std::string{util::pdbg::getPath(m.at(iv_clockType))};
251 // auto guardPath = util::pdbg::getPhysDevPath(target);
252 // Guard guard = io_sd.addGuard(guardPath, iv_guard);
253 auto guardPath = __getRootCauseChipPath(io_sd);
254
255 // Add the callout FFDC to the service data.
256 nlohmann::json ffdc;
257 ffdc["Callout Type"] = "Clock Callout";
258 ffdc["Clock Type"] = iv_clockType.getString();
259 ffdc["Target"] = guardPath;
260 ffdc["Priority"] = iv_priority.getRegistryString();
261 ffdc["Guard Type"] = ""; // TODO: guard.getString();
262 io_sd.addCalloutFFDC(ffdc);
Zane Shelley84721d92021-09-08 13:30:27 -0500263}
264
265//------------------------------------------------------------------------------
266
Zane Shelley0b8368c2021-03-18 17:33:41 -0500267} // namespace analyzer
268
269using namespace analyzer;
270
271TEST(Resolution, TestSet1)
272{
273 // Create a few resolutions
274 auto c1 = std::make_shared<HardwareCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500275 proc_str, callout::Priority::HIGH, false);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500276
277 auto c2 = std::make_shared<HardwareCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500278 omi_str, callout::Priority::MED_A, true);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500279
280 auto c3 = std::make_shared<HardwareCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500281 core_str, callout::Priority::MED, true);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500282
283 auto c4 = std::make_shared<ProcedureCalloutResolution>(
Zane Shelleyc85716c2021-08-17 10:54:06 -0500284 callout::Procedure::NEXTLVL, callout::Priority::LOW);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500285
Zane Shelley84721d92021-09-08 13:30:27 -0500286 auto c5 = std::make_shared<ClockCalloutResolution>(
287 callout::ClockType::OSC_REF_CLOCK_1, callout::Priority::LOW, false);
288
289 // l1 = (c1, c2, c5)
Zane Shelley723fa232021-08-09 12:02:06 -0500290 auto l1 = std::make_shared<ResolutionList>();
291 l1->push(c1);
292 l1->push(c2);
Zane Shelley84721d92021-09-08 13:30:27 -0500293 l1->push(c5);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500294
Zane Shelley84721d92021-09-08 13:30:27 -0500295 // l2 = (c4, c3, c1, c2, c5)
Zane Shelley723fa232021-08-09 12:02:06 -0500296 auto l2 = std::make_shared<ResolutionList>();
297 l2->push(c4);
298 l2->push(c3);
299 l2->push(l1);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500300
301 // Get some ServiceData objects
302 libhei::Chip chip{chip_str, 0xdeadbeef};
303 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
Zane Shelleyca496192021-08-09 12:05:52 -0500304 ServiceData sd1{sig, true};
305 ServiceData sd2{sig, false};
Zane Shelley0b8368c2021-03-18 17:33:41 -0500306
307 // Resolve
Zane Shelley723fa232021-08-09 12:02:06 -0500308 l1->resolve(sd1);
309 l2->resolve(sd2);
Zane Shelley0b8368c2021-03-18 17:33:41 -0500310
311 // Start verifying
312 nlohmann::json j{};
313 std::string s{};
314
Zane Shelleyc85716c2021-08-17 10:54:06 -0500315 j = sd1.getCalloutList();
Zane Shelley0b8368c2021-03-18 17:33:41 -0500316 s = R"([
317 {
318 "LocationCode": "/proc0",
319 "Priority": "H"
320 },
321 {
Zane Shelley84721d92021-09-08 13:30:27 -0500322 "LocationCode": "P0",
323 "Priority": "L"
Zane Shelley0b8368c2021-03-18 17:33:41 -0500324 }
325])";
Zane Shelley96d54862021-09-17 11:16:12 -0500326 EXPECT_EQ(s, j.dump(4));
Zane Shelley0b8368c2021-03-18 17:33:41 -0500327
Zane Shelleyc85716c2021-08-17 10:54:06 -0500328 j = sd2.getCalloutList();
Zane Shelley0b8368c2021-03-18 17:33:41 -0500329 s = R"([
330 {
331 "Priority": "L",
332 "Procedure": "NEXTLVL"
333 },
334 {
335 "LocationCode": "/proc0",
Zane Shelley0b8368c2021-03-18 17:33:41 -0500336 "Priority": "H"
337 },
338 {
Zane Shelley84721d92021-09-08 13:30:27 -0500339 "LocationCode": "P0",
340 "Priority": "L"
Zane Shelley0b8368c2021-03-18 17:33:41 -0500341 }
342])";
Zane Shelley96d54862021-09-17 11:16:12 -0500343 EXPECT_EQ(s, j.dump(4));
344}
345
346TEST(Resolution, HardwareCallout)
347{
348 auto c1 = std::make_shared<HardwareCalloutResolution>(
349 omi_str, callout::Priority::MED_A, true);
350
351 libhei::Chip chip{chip_str, 0xdeadbeef};
352 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
353 ServiceData sd{sig, true};
354
355 c1->resolve(sd);
356
357 nlohmann::json j{};
358 std::string s{};
359
360 // Callout list
361 j = sd.getCalloutList();
362 s = R"([
363 {
364 "LocationCode": "/proc0",
365 "Priority": "A"
366 }
367])";
368 EXPECT_EQ(s, j.dump(4));
369
370 // Callout FFDC
371 j = sd.getCalloutFFDC();
372 s = R"([
373 {
374 "Callout Type": "Hardware Callout",
375 "Guard Type": "FATAL",
376 "Priority": "medium_group_A",
377 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
378 }
379])";
380 EXPECT_EQ(s, j.dump(4));
381}
382
Zane Shelley5d63cef2021-09-17 18:10:17 -0500383TEST(Resolution, ConnectedCallout)
384{
385 auto c1 = std::make_shared<ConnectedCalloutResolution>(
386 callout::BusType::SMP_BUS, iolink_str, callout::Priority::MED_A, true);
387
388 auto c2 = std::make_shared<ConnectedCalloutResolution>(
389 callout::BusType::OMI_BUS, ocmb_str, callout::Priority::MED_B, true);
390
391 auto c3 = std::make_shared<ConnectedCalloutResolution>(
392 callout::BusType::OMI_BUS, omi_str, callout::Priority::MED_C, true);
393
394 libhei::Chip chip{chip_str, 0xdeadbeef};
395 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
396 ServiceData sd{sig, true};
397
398 nlohmann::json j{};
399 std::string s{};
400
401 c1->resolve(sd);
402 c2->resolve(sd);
403 c3->resolve(sd);
404
405 // Callout list
406 j = sd.getCalloutList();
407 s = R"([
408 {
409 "LocationCode": "/proc1",
410 "Priority": "A"
411 },
412 {
413 "LocationCode": "/proc0",
414 "Priority": "B"
415 },
416 {
417 "LocationCode": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0",
418 "Priority": "C"
419 }
420])";
421 EXPECT_EQ(s, j.dump(4));
422
423 // Callout FFDC
424 j = sd.getCalloutFFDC();
425 s = R"([
426 {
427 "Bus Type": "SMP_BUS",
428 "Callout Type": "Connected Callout",
429 "Guard Type": "FATAL",
430 "Priority": "medium_group_A",
431 "Target": "/proc1/pib/perv24/pauc0/iohs0/smpgroup0"
432 },
433 {
434 "Bus Type": "OMI_BUS",
435 "Callout Type": "Connected Callout",
436 "Guard Type": "FATAL",
437 "Priority": "medium_group_B",
438 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
439 },
440 {
441 "Bus Type": "OMI_BUS",
442 "Callout Type": "Connected Callout",
443 "Guard Type": "FATAL",
444 "Priority": "medium_group_C",
445 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
446 }
447])";
448 EXPECT_EQ(s, j.dump(4));
449}
450
Zane Shelley4757a7b2021-09-20 22:23:38 -0500451TEST(Resolution, BusCallout)
452{
453 auto c1 = std::make_shared<HardwareCalloutResolution>(
454 omi_str, callout::Priority::MED_A, true);
455
456 auto c2 = std::make_shared<ConnectedCalloutResolution>(
457 callout::BusType::OMI_BUS, omi_str, callout::Priority::MED_A, true);
458
459 auto c3 = std::make_shared<BusCalloutResolution>(
460 callout::BusType::OMI_BUS, omi_str, callout::Priority::LOW, false);
461
462 libhei::Chip chip{chip_str, 0xdeadbeef};
463 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
464 ServiceData sd{sig, true};
465
466 nlohmann::json j{};
467 std::string s{};
468
469 c1->resolve(sd);
470 c2->resolve(sd);
471 c3->resolve(sd);
472
473 // Callout list
474 j = sd.getCalloutList();
475 s = R"([
476 {
477 "LocationCode": "/proc0",
478 "Priority": "A"
479 },
480 {
481 "LocationCode": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0",
482 "Priority": "A"
483 },
484 {
485 "LocationCode": "P0",
486 "Priority": "L"
487 }
488])";
489 EXPECT_EQ(s, j.dump(4));
490
491 // Callout FFDC
492 j = sd.getCalloutFFDC();
493 s = R"([
494 {
495 "Callout Type": "Hardware Callout",
496 "Guard Type": "FATAL",
497 "Priority": "medium_group_A",
498 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0"
499 },
500 {
501 "Bus Type": "OMI_BUS",
502 "Callout Type": "Connected Callout",
503 "Guard Type": "FATAL",
504 "Priority": "medium_group_A",
505 "Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
506 },
507 {
508 "Bus Type": "OMI_BUS",
509 "Callout Type": "Bus Callout",
510 "Guard Type": "NONE",
511 "Priority": "low",
512 "RX Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0",
513 "TX Target": "/proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0"
514 }
515])";
516 EXPECT_EQ(s, j.dump(4));
517}
518
Zane Shelley96d54862021-09-17 11:16:12 -0500519TEST(Resolution, ClockCallout)
520{
521 auto c1 = std::make_shared<ClockCalloutResolution>(
522 callout::ClockType::OSC_REF_CLOCK_1, callout::Priority::HIGH, false);
523
524 libhei::Chip chip{chip_str, 0xdeadbeef};
525 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
526 ServiceData sd{sig, true};
527
528 c1->resolve(sd);
529
530 nlohmann::json j{};
531 std::string s{};
532
533 // Callout list
534 j = sd.getCalloutList();
535 s = R"([
536 {
537 "LocationCode": "P0",
538 "Priority": "H"
539 }
540])";
541 EXPECT_EQ(s, j.dump(4));
542
543 // Callout FFDC
544 j = sd.getCalloutFFDC();
545 s = R"([
546 {
547 "Callout Type": "Clock Callout",
548 "Clock Type": "OSC_REF_CLOCK_1",
549 "Guard Type": "",
550 "Priority": "high",
551 "Target": "/proc0"
552 }
553])";
554 EXPECT_EQ(s, j.dump(4));
555}
556
557TEST(Resolution, ProcedureCallout)
558{
559 auto c1 = std::make_shared<ProcedureCalloutResolution>(
560 callout::Procedure::NEXTLVL, callout::Priority::LOW);
561
562 libhei::Chip chip{chip_str, 0xdeadbeef};
563 libhei::Signature sig{chip, 0xabcd, 0, 0, libhei::ATTN_TYPE_CHECKSTOP};
564 ServiceData sd{sig, true};
565
566 c1->resolve(sd);
567
568 nlohmann::json j{};
569 std::string s{};
570
571 // Callout list
572 j = sd.getCalloutList();
573 s = R"([
574 {
575 "Priority": "L",
576 "Procedure": "NEXTLVL"
577 }
578])";
579 EXPECT_EQ(s, j.dump(4));
580
581 // Callout FFDC
582 j = sd.getCalloutFFDC();
583 s = R"([
584 {
585 "Callout Type": "Procedure Callout",
586 "Priority": "low",
587 "Procedure": "NEXTLVL"
588 }
589])";
590 EXPECT_EQ(s, j.dump(4));
Zane Shelley0b8368c2021-03-18 17:33:41 -0500591}