PEL: Add APIs to look up device path callouts
This commit adds the interfaces device_callouts::getCallouts() and
device_callouts::getI2CCallouts() that will be used to look up the FRU
callouts to add to PELs for errors stemming from accessing devices,
either by a sysfs path, or in the case of the latter interface an I2C
bus and address.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I573d04632fd9fc6356a0ff53f85c2a2c13038962
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index 34db4e5..0ee298b 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -4,6 +4,7 @@
additional_data_test \
ascii_string_test \
bcd_time_test \
+ device_callouts_test \
event_logger_test \
extended_user_header_test \
failing_mtms_test \
@@ -37,6 +38,7 @@
$(top_builddir)/extensions/openpower-pels/bcd_time.o \
$(top_builddir)/extensions/openpower-pels/callout.o \
$(top_builddir)/extensions/openpower-pels/callouts.o \
+ $(top_builddir)/extensions/openpower-pels/device_callouts.o \
$(top_builddir)/extensions/openpower-pels/extended_user_header.o \
$(top_builddir)/extensions/openpower-pels/failing_mtms.o \
$(top_builddir)/extensions/openpower-pels/fru_identity.o \
@@ -309,6 +311,7 @@
$(top_builddir)/extensions/openpower-pels/ascii_string.o \
$(top_builddir)/extensions/openpower-pels/callout.o \
$(top_builddir)/extensions/openpower-pels/callouts.o \
+ $(top_builddir)/extensions/openpower-pels/device_callouts.o \
$(top_builddir)/extensions/openpower-pels/fru_identity.o \
$(top_builddir)/extensions/openpower-pels/json_utils.o \
$(top_builddir)/extensions/openpower-pels/mru.o \
@@ -330,6 +333,7 @@
$(top_builddir)/extensions/openpower-pels/bcd_time.o \
$(top_builddir)/extensions/openpower-pels/callout.o \
$(top_builddir)/extensions/openpower-pels/callouts.o \
+ $(top_builddir)/extensions/openpower-pels/device_callouts.o \
$(top_builddir)/extensions/openpower-pels/data_interface.o \
$(top_builddir)/extensions/openpower-pels/extended_user_header.o \
$(top_builddir)/extensions/openpower-pels/fru_identity.o \
@@ -377,3 +381,13 @@
event_logger_test_LDADD = \
$(test_ldadd)
event_logger_test_LDFLAGS = $(test_ldflags) $(SDEVENTPLUS_LIBS)
+
+device_callouts_test_SOURCES = \
+ %reldir%/device_callouts_test.cpp
+device_callouts_test_CPPFLAGS = $(test_cppflags)
+device_callouts_test_CXXFLAGS = $(test_cxxflags)
+device_callouts_test_LDADD = \
+ $(test_ldadd) \
+ $(pel_test_utils_ldadd) \
+ $(top_builddir)/extensions/openpower-pels/device_callouts.o
+device_callouts_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/device_callouts_test.cpp b/test/openpower-pels/device_callouts_test.cpp
new file mode 100644
index 0000000..d2947a1
--- /dev/null
+++ b/test/openpower-pels/device_callouts_test.cpp
@@ -0,0 +1,242 @@
+/**
+ * Copyright © 2020 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "extensions/openpower-pels/device_callouts.hpp"
+#include "extensions/openpower-pels/paths.hpp"
+
+#include <fstream>
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels;
+using namespace openpower::pels::device_callouts;
+namespace fs = std::filesystem;
+
+// The callout JSON looks like:
+// "I2C":
+// "<bus>":
+// "<address>":
+// "Callouts": ...
+//
+// "FSI":
+// "<fsi link>":
+// "Callouts": ...
+//
+// "FSI-I2C":
+// "<fsi link>":
+// "<bus>":
+// "<address>":
+// "Callouts": ...
+//
+// "FSI-SPI":
+// "<fsi link>":
+// "<bus>":
+// "Callouts": ...
+
+const auto calloutJSON = R"(
+{
+ "I2C":
+ {
+ "0":
+ {
+ "32":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ },
+ "81":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ }
+ },
+ "14":
+ {
+ "112":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ },
+ "114":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ },
+ {
+ "Name": "/chassis/motherboard",
+ "LocationCode": "P1",
+ "Priority": "M"
+ }
+ ],
+ "Dest": "proc-0 target"
+ }
+ }
+ },
+ "FSI":
+ {
+ "0":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ },
+ "0-1":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H",
+ "MRU": "core"
+ }
+ ],
+ "Dest": "proc-0 target"
+ }
+ },
+ "FSI-I2C":
+ {
+ "0-3":
+ {
+ "7":
+ {
+ "24":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ },
+ "25":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu5",
+ "LocationCode": "P1-C25",
+ "Priority": "H"
+ },
+ {
+ "Name": "/chassis/motherboard",
+ "LocationCode": "P1",
+ "Priority": "M"
+ },
+ {
+ "Name": "/chassis/motherboard/bmc",
+ "LocationCode": "P2",
+ "Priority": "L"
+ }
+ ],
+ "Dest": "proc-5 target"
+ }
+ }
+ }
+ },
+ "FSI-SPI":
+ {
+ "8":
+ {
+ "3":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ },
+ "4":
+ {
+ "Callouts":[
+ {
+ "Name": "/chassis/motherboard/cpu0",
+ "LocationCode": "P1-C19",
+ "Priority": "H"
+ }
+ ],
+ "Dest": "proc-0 target"
+ }
+ }
+ }
+})"_json;
+
+class DeviceCalloutsTest : public ::testing::Test
+{
+ public:
+ static void SetUpTestCase()
+ {
+ dataPath = getPELReadOnlyDataPath();
+ std::ofstream file{dataPath / filename};
+ file << calloutJSON.dump();
+ }
+
+ static void TearDownTestCase()
+ {
+ fs::remove_all(dataPath);
+ }
+
+ static std::string filename;
+ static fs::path dataPath;
+};
+
+std::string DeviceCalloutsTest::filename = "systemA_dev_callouts.json";
+fs::path DeviceCalloutsTest::dataPath;
+
+// Test looking up the JSON file based on the system compatible names
+TEST_F(DeviceCalloutsTest, getJSONFilenameTest)
+{
+ {
+ std::vector<std::string> compatibles{"system1", "systemA", "system3"};
+ EXPECT_EQ(util::getJSONFilename(compatibles),
+ fs::path{dataPath / filename});
+ }
+
+ // Actual filename not in compatibles
+ {
+ std::vector<std::string> compatibles{"system5", "system6"};
+ EXPECT_THROW(util::getJSONFilename(compatibles), std::invalid_argument);
+ }
+}