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