blob: 82d556b805b8c65fe6ebe66d3be20d5a765bcf3a [file] [log] [blame]
Alexander Hansen40fb5492025-10-28 17:56:12 +01001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2020 IBM Corporation
Matt Spinler18c42b02020-06-02 15:59:50 -05003
4#include "extensions/openpower-pels/device_callouts.hpp"
5#include "extensions/openpower-pels/paths.hpp"
6
7#include <fstream>
8
9#include <gtest/gtest.h>
10
11using namespace openpower::pels;
12using namespace openpower::pels::device_callouts;
13namespace fs = std::filesystem;
14
15// The callout JSON looks like:
16// "I2C":
17// "<bus>":
18// "<address>":
19// "Callouts": ...
20//
21// "FSI":
22// "<fsi link>":
23// "Callouts": ...
24//
25// "FSI-I2C":
26// "<fsi link>":
27// "<bus>":
28// "<address>":
29// "Callouts": ...
30//
31// "FSI-SPI":
32// "<fsi link>":
33// "<bus>":
34// "Callouts": ...
35
36const auto calloutJSON = R"(
37{
38 "I2C":
39 {
40 "0":
41 {
42 "32":
43 {
44 "Callouts":[
45 {
46 "Name": "/chassis/motherboard/cpu0",
47 "LocationCode": "P1-C19",
48 "Priority": "H"
49 }
50 ],
51 "Dest": "proc-0 target"
52 },
53 "81":
54 {
55 "Callouts":[
56 {
57 "Name": "/chassis/motherboard/cpu0",
58 "LocationCode": "P1-C19",
59 "Priority": "H"
60 }
61 ],
62 "Dest": "proc-0 target"
Matt Spinler6bc74ae2020-06-03 15:13:59 -050063 },
64 "90":
65 {
66 "Callouts":[
67 {
68 "Name": "This is missing the location code",
69 "Priority": "H"
70 }
71 ],
72 "Dest": "proc-0 target"
Matt Spinler18c42b02020-06-02 15:59:50 -050073 }
74 },
75 "14":
76 {
77 "112":
78 {
79 "Callouts":[
80 {
81 "Name": "/chassis/motherboard/cpu0",
82 "LocationCode": "P1-C19",
83 "Priority": "H"
84 }
85 ],
86 "Dest": "proc-0 target"
87 },
88 "114":
89 {
90 "Callouts":[
91 {
92 "Name": "/chassis/motherboard/cpu0",
93 "LocationCode": "P1-C19",
Matt Spinler6bc74ae2020-06-03 15:13:59 -050094 "Priority": "H",
95 "MRU": "core0"
Matt Spinler18c42b02020-06-02 15:59:50 -050096 },
97 {
98 "Name": "/chassis/motherboard",
99 "LocationCode": "P1",
100 "Priority": "M"
101 }
102 ],
103 "Dest": "proc-0 target"
104 }
105 }
106 },
107 "FSI":
108 {
109 "0":
110 {
111 "Callouts":[
112 {
113 "Name": "/chassis/motherboard/cpu0",
114 "LocationCode": "P1-C19",
115 "Priority": "H"
116 }
117 ],
118 "Dest": "proc-0 target"
119 },
120 "0-1":
121 {
122 "Callouts":[
123 {
124 "Name": "/chassis/motherboard/cpu0",
125 "LocationCode": "P1-C19",
126 "Priority": "H",
127 "MRU": "core"
128 }
129 ],
130 "Dest": "proc-0 target"
131 }
132 },
133 "FSI-I2C":
134 {
135 "0-3":
136 {
137 "7":
138 {
139 "24":
140 {
141 "Callouts":[
142 {
143 "Name": "/chassis/motherboard/cpu0",
144 "LocationCode": "P1-C19",
145 "Priority": "H"
146 }
147 ],
148 "Dest": "proc-0 target"
149 },
150 "25":
151 {
152 "Callouts":[
153 {
154 "Name": "/chassis/motherboard/cpu5",
155 "LocationCode": "P1-C25",
156 "Priority": "H"
157 },
158 {
159 "Name": "/chassis/motherboard",
160 "LocationCode": "P1",
161 "Priority": "M"
162 },
163 {
164 "Name": "/chassis/motherboard/bmc",
165 "LocationCode": "P2",
166 "Priority": "L"
167 }
168 ],
169 "Dest": "proc-5 target"
170 }
171 }
172 }
173 },
174 "FSI-SPI":
175 {
176 "8":
177 {
178 "3":
179 {
180 "Callouts":[
181 {
182 "Name": "/chassis/motherboard/cpu0",
183 "LocationCode": "P1-C19",
184 "Priority": "H"
185 }
186 ],
187 "Dest": "proc-0 target"
188 },
189 "4":
190 {
191 "Callouts":[
192 {
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500193 "Name": "/chassis/motherboard/cpu2",
194 "LocationCode": "P1-C12",
195 "Priority": "M"
Matt Spinler18c42b02020-06-02 15:59:50 -0500196 }
197 ],
198 "Dest": "proc-0 target"
199 }
200 }
201 }
202})"_json;
203
204class DeviceCalloutsTest : public ::testing::Test
205{
206 public:
207 static void SetUpTestCase()
208 {
209 dataPath = getPELReadOnlyDataPath();
210 std::ofstream file{dataPath / filename};
211 file << calloutJSON.dump();
212 }
213
214 static void TearDownTestCase()
215 {
216 fs::remove_all(dataPath);
217 }
218
219 static std::string filename;
220 static fs::path dataPath;
221};
222
223std::string DeviceCalloutsTest::filename = "systemA_dev_callouts.json";
224fs::path DeviceCalloutsTest::dataPath;
225
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500226namespace openpower::pels::device_callouts
227{
228
229// Helpers to compair vectors of Callout objects
230bool operator!=(const Callout& left, const Callout& right)
231{
232 return (left.priority != right.priority) ||
233 (left.locationCode != right.locationCode) ||
234 (left.name != right.name) || (left.mru != right.mru) ||
235 (left.debug != right.debug);
236}
237
238bool operator==(const std::vector<Callout>& left,
239 const std::vector<Callout>& right)
240{
241 if (left.size() != right.size())
242 {
243 return false;
244 }
245
246 for (size_t i = 0; i < left.size(); i++)
247 {
248 if (left[i] != right[i])
249 {
250 return false;
251 }
252 }
253
254 return true;
255}
256
257} // namespace openpower::pels::device_callouts
258
Matt Spinler18c42b02020-06-02 15:59:50 -0500259// Test looking up the JSON file based on the system compatible names
260TEST_F(DeviceCalloutsTest, getJSONFilenameTest)
261{
262 {
263 std::vector<std::string> compatibles{"system1", "systemA", "system3"};
264 EXPECT_EQ(util::getJSONFilename(compatibles),
265 fs::path{dataPath / filename});
266 }
267
268 // Actual filename not in compatibles
269 {
270 std::vector<std::string> compatibles{"system5", "system6"};
271 EXPECT_THROW(util::getJSONFilename(compatibles), std::invalid_argument);
272 }
Matt Spinler0f8a7382020-07-22 12:58:45 -0500273
274 // Test using the fallback name
275 {
276 // If _dev_callouts.json is there, it will be used if no other
277 // match is found.
278 fs::path fallbackFile{dataPath / "_dev_callouts.json"};
279 std::ofstream file{fallbackFile};
280 file << calloutJSON.dump();
281 file.close();
282
283 // Fallback shouldn't be used because the actual systemA file is there
284 {
285 std::vector<std::string> compatibles{"system1", "systemA",
286 "system3"};
287 EXPECT_EQ(util::getJSONFilename(compatibles),
288 fs::path{dataPath / filename});
289 }
290
291 // Fallback should be used because no other match
292 {
293 std::vector<std::string> compatibles{"systemX", "systemY"};
294 EXPECT_EQ(util::getJSONFilename(compatibles), fallbackFile);
295 }
296 }
Matt Spinler18c42b02020-06-02 15:59:50 -0500297}
Matt Spinlera3070892020-06-03 10:52:32 -0500298
299// Test determining the callout type from the device path
300TEST_F(DeviceCalloutsTest, getCalloutTypeTest)
301{
Matt Spinlera3070892020-06-03 10:52:32 -0500302 // Invalid
303 {
304 EXPECT_EQ(util::getCalloutType("/some/bad/device/path"),
305 util::CalloutType::unknown);
306 }
307
308 // I2C
309 {
310 EXPECT_EQ(util::getCalloutType(
311 "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/"
Matt Spinler70e8a112024-09-24 14:27:42 -0500312 "1e78a340.i2c/i2c-14/14-0072"),
Matt Spinlera3070892020-06-03 10:52:32 -0500313 util::CalloutType::i2c);
314 }
315
316 // FSI
317 {
318 EXPECT_EQ(util::getCalloutType(
319 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
320 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
321 "slave@01:00/01:01:00:06/sbefifo2-dev0/occ-hwmon.2"),
322 util::CalloutType::fsi);
323 }
324
325 // FSI-I2C
326 {
327 EXPECT_EQ(util::getCalloutType(
328 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
329 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
330 "slave@01:00/01:01:00:03/i2c-211/211-0055"),
331 util::CalloutType::fsii2c);
332 }
333
334 // FSI-SPI
335 {
Matt Spinlera3070892020-06-03 10:52:32 -0500336 EXPECT_EQ(
337 util::getCalloutType(
338 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/"
339 "fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/slave@08:00/"
340 "01:03:00:04/spi_master/spi9/spi9.0/spi9.00/nvmem"),
341 util::CalloutType::fsispi);
342 }
343}
Matt Spinler44c0a642020-06-03 11:28:25 -0500344
345// Test getting I2C search keys
346TEST_F(DeviceCalloutsTest, getI2CSearchKeysTest)
347{
Matt Spinler44c0a642020-06-03 11:28:25 -0500348 {
349 EXPECT_EQ(util::getI2CSearchKeys(
350 "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/"
Matt Spinler70e8a112024-09-24 14:27:42 -0500351 "1e78a340.i2c/i2c-10/10-0022"),
Matt Spinler44c0a642020-06-03 11:28:25 -0500352 (std::tuple{10, 0x22}));
353
354 EXPECT_EQ(util::getI2CSearchKeys(
355 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
356 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
357 "slave@01:00/01:01:00:03/i2c-211/211-0055"),
358 (std::tuple{11, 0x55}));
359 }
360
361 {
362 EXPECT_THROW(util::getI2CSearchKeys("/sys/some/bad/path"),
363 std::invalid_argument);
364 }
365}
366//
367// Test getting SPI search keys
368TEST_F(DeviceCalloutsTest, getSPISearchKeysTest)
369{
370 {
371 EXPECT_EQ(
372 util::getSPISearchKeys(
373 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/"
374 "fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/slave@08:00/"
375 "01:03:00:04/spi_master/spi9/spi9.0/spi9.00/nvmem"),
376 9);
377 }
378
379 {
380 EXPECT_THROW(util::getSPISearchKeys("/sys/some/bad/path"),
381 std::invalid_argument);
382 }
383}
384
385// Test getting FSI search keys
386TEST_F(DeviceCalloutsTest, getFSISearchKeysTest)
387{
388 {
389 EXPECT_EQ(util::getFSISearchKeys(
390 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
391 "fsi-master/fsi0/slave@00:00/00:00:00:04/spi_master/spi2/"
392 "spi2.0/spi2.00/nvmem"),
393 "0");
394 }
395
396 {
397 EXPECT_EQ(util::getFSISearchKeys(
398 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
399 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
400 "slave@01:00/01:01:00:06/sbefifo2-dev0/occ-hwmon.2"),
401 "0-1");
402 }
403
404 {
405 EXPECT_EQ(
406 util::getFSISearchKeys(
407 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
408 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
409 "slave@01:00/01:01:00:0a:/fsi-master/slave@04:00/01:01:00:0a"),
410 "0-1-4");
411 }
412
413 {
414 EXPECT_THROW(util::getFSISearchKeys("/sys/some/bad/path"),
415 std::invalid_argument);
416 }
417}
418
419// Test getting FSI-I2C search keys
420TEST_F(DeviceCalloutsTest, getFSII2CSearchKeysTest)
421{
422 {
423 // Link 0-1 bus 11 address 0x55
424 EXPECT_EQ(util::getFSII2CSearchKeys(
425 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
426 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
427 "slave@01:00/01:01:00:03/i2c-211/211-0055"),
428 (std::tuple{"0-1", std::tuple{11, 0x55}}));
429 }
430
431 {
432 EXPECT_THROW(util::getFSII2CSearchKeys("/sys/some/bad/path"),
433 std::invalid_argument);
434 }
435}
436
437// Test getting FSI-SPI search keys
438TEST_F(DeviceCalloutsTest, getFSISPISearchKeysTest)
439{
440 {
441 // Link 0-8 SPI 9
442 EXPECT_EQ(
443 util::getFSISPISearchKeys(
444 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/"
445 "fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/slave@08:00/"
446 "01:03:00:04/spi_master/spi9/spi9.0/spi9.00/nvmem"),
447 (std::tuple{"0-8", 9}));
448 }
449
450 {
451 EXPECT_THROW(util::getFSISPISearchKeys("/sys/some/bad/path"),
452 std::invalid_argument);
453 }
454}
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500455
456TEST_F(DeviceCalloutsTest, getCalloutsTest)
457{
458 std::vector<std::string> systemTypes{"systemA", "systemB"};
459
460 // A really bogus path
461 {
462 EXPECT_THROW(getCallouts("/bad/path", systemTypes),
463 std::invalid_argument);
464 }
465
466 // I2C
467 {
468 auto callouts = getCallouts(
469 "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/"
Matt Spinler70e8a112024-09-24 14:27:42 -0500470 "1e78a340.i2c/i2c-14/14-0072",
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500471 systemTypes);
472
473 std::vector<Callout> expected{
474 {"H", "P1-C19", "/chassis/motherboard/cpu0", "core0",
475 "I2C: bus: 14 address: 114 dest: proc-0 target"},
476 {"M", "P1", "/chassis/motherboard", "", ""}};
477
478 EXPECT_EQ(callouts, expected);
479
480 // Use the bus/address API instead of the device path one
481 callouts = getI2CCallouts(14, 0x72, systemTypes);
482 EXPECT_EQ(callouts, expected);
483
484 // I2C address not in JSON
485 EXPECT_THROW(
486 getCallouts(
487 "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/"
Matt Spinler70e8a112024-09-24 14:27:42 -0500488 "1e78a340.i2c/i2c-14/14-0099",
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500489 systemTypes),
490 std::invalid_argument);
491
492 // A bad JSON entry, missing the location code
493 EXPECT_THROW(
494 getCallouts(
495 "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/"
Matt Spinler70e8a112024-09-24 14:27:42 -0500496 "1e78a340.i2c/i2c-0/0-005a",
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500497 systemTypes),
498 std::runtime_error);
499 }
500
501 // FSI
502 {
503 auto callouts = getCallouts(
504 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
505 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
506 "slave@01:00/01:01:00:06/sbefifo2-dev0/occ-hwmon.2",
507 systemTypes);
508
Patrick Williams075c7922024-08-16 15:19:49 -0400509 std::vector<Callout> expected{
510 {"H", "P1-C19", "/chassis/motherboard/cpu0", "core",
511 "FSI: links: 0-1 dest: proc-0 target"}};
Matt Spinler6bc74ae2020-06-03 15:13:59 -0500512
513 EXPECT_EQ(callouts, expected);
514
515 // link 9-1 not in JSON
516 EXPECT_THROW(
517 getCallouts(
518 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
519 "fsi-master/fsi0/slave@09:00/00:00:00:0a/fsi-master/fsi1/"
520 "slave@01:00/01:01:00:06/sbefifo2-dev0/occ-hwmon.2",
521 systemTypes),
522 std::invalid_argument);
523 }
524
525 // FSI-I2C
526 {
527 auto callouts = getCallouts(
528 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
529 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
530 "slave@03:00/01:01:00:03/i2c-207/207-0019",
531 systemTypes);
532
533 std::vector<Callout> expected{
534 {"H", "P1-C25", "/chassis/motherboard/cpu5", "",
535 "FSI-I2C: links: 0-3 bus: 7 addr: 25 dest: proc-5 target"},
536 {"M", "P1", "/chassis/motherboard", "", ""},
537 {"L", "P2", "/chassis/motherboard/bmc", "", ""}};
538
539 EXPECT_EQ(callouts, expected);
540
541 // Bus 2 not in JSON
542 EXPECT_THROW(
543 getCallouts(
544 "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
545 "fsi-master/fsi0/slave@00:00/00:00:00:0a/fsi-master/fsi1/"
546 "slave@03:00/01:01:00:03/i2c-202/202-0019",
547 systemTypes),
548 std::invalid_argument);
549 }
550
551 // FSI-SPI
552 {
553 auto callouts =
554 getCallouts("/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
555 "fsi-master/fsi0/slave@08:00/00:00:00:04/spi_master/"
556 "spi3/spi3.0/spi3.00/nvmem",
557 systemTypes);
558
559 std::vector<Callout> expected{
560 {"H", "P1-C19", "/chassis/motherboard/cpu0", "",
561 "FSI-SPI: links: 8 bus: 3 dest: proc-0 target"}};
562
563 EXPECT_EQ(callouts, expected);
564
565 // Bus 7 not in the JSON
566 EXPECT_THROW(
567 getCallouts("/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/"
568 "fsi-master/fsi0/slave@08:00/00:00:00:04/spi_master/"
569 "spi7/spi7.0/spi7.00/nvmem",
570 systemTypes),
571 std::invalid_argument);
572 }
573}