diff options
Diffstat (limited to 'test/openpower-pels/registry_test.cpp')
-rw-r--r-- | test/openpower-pels/registry_test.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/test/openpower-pels/registry_test.cpp b/test/openpower-pels/registry_test.cpp new file mode 100644 index 0000000..2944ce0 --- /dev/null +++ b/test/openpower-pels/registry_test.cpp @@ -0,0 +1,336 @@ +/** + * Copyright © 2019 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/registry.hpp" + +#include <filesystem> +#include <fstream> +#include <nlohmann/json.hpp> + +#include <gtest/gtest.h> + +using namespace openpower::pels::message; +namespace fs = std::filesystem; + +const auto registryData = R"( +{ + "PELs": + [ + { + "Name": "xyz.openbmc_project.Power.Fault", + "Subsystem": "power_supply", + + "SRC": + { + "ReasonCode": "0x2030" + }, + + "Documentation": + { + "Description": "A PGOOD Fault", + "Message": "PS had a PGOOD Fault" + } + }, + + { + "Name": "xyz.openbmc_project.Power.OverVoltage", + "Subsystem": "power_control_hw", + "Severity": "unrecoverable", + "MfgSeverity": "non_error", + "ActionFlags": ["service_action", "report", "call_home"], + "MfgActionFlags": ["hidden"], + + "SRC": + { + "ReasonCode": "0x2333", + "Type": "BD", + "SymptomIDFields": ["SRCWord5", "SRCWord6", "SRCWord7"], + "PowerFault": true, + "Words6To9": + { + "6": + { + "description": "Failing unit number", + "AdditionalDataPropSource": "PS_NUM" + }, + + "7": + { + "description": "bad voltage", + "AdditionalDataPropSource": "VOLTAGE" + } + } + }, + + "Documentation": + { + "Description": "A PGOOD Fault", + "Message": "PS %1 had a PGOOD Fault", + "MessageArgSources": + [ + "SRCWord6" + ], + "Notes": [ + "In the UserData section there is a JSON", + "dump that provides debug information." + ] + } + } + ] +} +)"; + +class RegistryTest : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + char path[] = "/tmp/regtestXXXXXX"; + regDir = mkdtemp(path); + } + + static void TearDownTestCase() + { + fs::remove_all(regDir); + } + + static std::string writeData(const char* data) + { + fs::path path = regDir / "registry.json"; + std::ofstream stream{path}; + stream << data; + return path; + } + + static fs::path regDir; +}; + +fs::path RegistryTest::regDir{}; + +TEST_F(RegistryTest, TestNoEntry) +{ + auto path = RegistryTest::writeData(registryData); + Registry registry{path}; + + auto entry = registry.lookup("foo", LookupType::name); + EXPECT_FALSE(entry); +} + +TEST_F(RegistryTest, TestFindEntry) +{ + auto path = RegistryTest::writeData(registryData); + Registry registry{path}; + + auto entry = registry.lookup("xyz.openbmc_project.Power.OverVoltage", + LookupType::name); + ASSERT_TRUE(entry); + EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage"); + EXPECT_EQ(entry->subsystem, 0x62); + EXPECT_EQ(*(entry->severity), 0x40); + EXPECT_EQ(*(entry->mfgSeverity), 0x00); + EXPECT_EQ(*(entry->actionFlags), 0xA800); + EXPECT_EQ(*(entry->mfgActionFlags), 0x4000); + EXPECT_EQ(entry->componentID, 0x2300); + EXPECT_FALSE(entry->eventType); + EXPECT_FALSE(entry->eventScope); + + EXPECT_EQ(entry->src.type, 0xBD); + EXPECT_EQ(entry->src.reasonCode, 0x2333); + EXPECT_EQ(*(entry->src.powerFault), true); + + auto& hexwords = entry->src.hexwordADFields; + EXPECT_TRUE(hexwords); + EXPECT_EQ((*hexwords).size(), 2); + + auto word = (*hexwords).find(6); + EXPECT_NE(word, (*hexwords).end()); + EXPECT_EQ(word->second, "PS_NUM"); + + word = (*hexwords).find(7); + EXPECT_NE(word, (*hexwords).end()); + EXPECT_EQ(word->second, "VOLTAGE"); + + auto& sid = entry->src.symptomID; + EXPECT_TRUE(sid); + EXPECT_EQ((*sid).size(), 3); + EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 5), (*sid).end()); + EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 6), (*sid).end()); + EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 7), (*sid).end()); + + EXPECT_EQ(entry->doc.description, "A PGOOD Fault"); + EXPECT_EQ(entry->doc.message, "PS %1 had a PGOOD Fault"); + auto& hexwordSource = entry->doc.messageArgSources; + EXPECT_TRUE(hexwordSource); + EXPECT_EQ((*hexwordSource).size(), 1); + EXPECT_EQ((*hexwordSource).front(), "SRCWord6"); + + entry = registry.lookup("0x2333", LookupType::reasonCode); + ASSERT_TRUE(entry); + EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage"); +} + +// Check the entry that mostly uses defaults +TEST_F(RegistryTest, TestFindEntryMinimal) +{ + auto path = RegistryTest::writeData(registryData); + Registry registry{path}; + + auto entry = + registry.lookup("xyz.openbmc_project.Power.Fault", LookupType::name); + ASSERT_TRUE(entry); + EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.Fault"); + EXPECT_EQ(entry->subsystem, 0x61); + EXPECT_FALSE(entry->severity); + EXPECT_FALSE(entry->mfgSeverity); + EXPECT_FALSE(entry->mfgActionFlags); + EXPECT_FALSE(entry->actionFlags); + EXPECT_EQ(entry->componentID, 0x2000); + EXPECT_FALSE(entry->eventType); + EXPECT_FALSE(entry->eventScope); + + EXPECT_EQ(entry->src.reasonCode, 0x2030); + EXPECT_EQ(entry->src.type, 0xBD); + EXPECT_FALSE(entry->src.powerFault); + EXPECT_FALSE(entry->src.hexwordADFields); + EXPECT_FALSE(entry->src.symptomID); +} + +TEST_F(RegistryTest, TestBadJSON) +{ + auto path = RegistryTest::writeData("bad {} json"); + + Registry registry{path}; + + EXPECT_FALSE(registry.lookup("foo", LookupType::name)); +} + +// Test the helper functions the use the pel_values data. +TEST_F(RegistryTest, TestHelperFunctions) +{ + using namespace openpower::pels::message::helper; + EXPECT_EQ(getSubsystem("input_power_source"), 0xA1); + EXPECT_THROW(getSubsystem("foo"), std::runtime_error); + + EXPECT_EQ(getSeverity("symptom_recovered"), 0x71); + EXPECT_THROW(getSeverity("foo"), std::runtime_error); + + EXPECT_EQ(getEventType("dump_notification"), 0x08); + EXPECT_THROW(getEventType("foo"), std::runtime_error); + + EXPECT_EQ(getEventScope("possibly_multiple_platforms"), 0x04); + EXPECT_THROW(getEventScope("foo"), std::runtime_error); + + std::vector<std::string> flags{"service_action", "dont_report", + "termination"}; + EXPECT_EQ(getActionFlags(flags), 0x9100); + + flags.clear(); + flags.push_back("foo"); + EXPECT_THROW(getActionFlags(flags), std::runtime_error); +} + +TEST_F(RegistryTest, TestGetSRCReasonCode) +{ + using namespace openpower::pels::message::helper; + EXPECT_EQ(getSRCReasonCode(R"({"ReasonCode": "0x5555"})"_json, "foo"), + 0x5555); + + EXPECT_THROW(getSRCReasonCode(R"({"ReasonCode": "ZZZZ"})"_json, "foo"), + std::runtime_error); +} + +TEST_F(RegistryTest, TestGetSRCType) +{ + using namespace openpower::pels::message::helper; + EXPECT_EQ(getSRCType(R"({"Type": "11"})"_json, "foo"), 0x11); + EXPECT_EQ(getSRCType(R"({"Type": "BF"})"_json, "foo"), 0xBF); + + EXPECT_THROW(getSRCType(R"({"Type": "1"})"_json, "foo"), + std::runtime_error); + + EXPECT_THROW(getSRCType(R"({"Type": "111"})"_json, "foo"), + std::runtime_error); +} + +TEST_F(RegistryTest, TestGetSRCHexwordFields) +{ + using namespace openpower::pels::message::helper; + const auto hexwords = R"( + {"Words6To9": + { + "8": + { + "AdditionalDataPropSource": "TEST" + } + } + })"_json; + + auto fields = getSRCHexwordFields(hexwords, "foo"); + EXPECT_TRUE(fields); + auto word = fields->find(8); + EXPECT_NE(word, fields->end()); + + const auto theInvalidRWord = R"( + {"Words6To9": + { + "R": + { + "AdditionalDataPropSource": "TEST" + } + } + })"_json; + + EXPECT_THROW(getSRCHexwordFields(theInvalidRWord, "foo"), + std::runtime_error); +} + +TEST_F(RegistryTest, TestGetSRCSymptomIDFields) +{ + using namespace openpower::pels::message::helper; + const auto sID = R"( + { + "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord5"] + })"_json; + + auto fields = getSRCSymptomIDFields(sID, "foo"); + EXPECT_NE(std::find(fields->begin(), fields->end(), 3), fields->end()); + EXPECT_NE(std::find(fields->begin(), fields->end(), 4), fields->end()); + EXPECT_NE(std::find(fields->begin(), fields->end(), 5), fields->end()); + + const auto badField = R"( + { + "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord"] + })"_json; + + EXPECT_THROW(getSRCSymptomIDFields(badField, "foo"), std::runtime_error); +} + +TEST_F(RegistryTest, TestGetComponentID) +{ + using namespace openpower::pels::message::helper; + + // Get it from the JSON + auto id = + getComponentID(0xBD, 0x4200, R"({"ComponentID":"0x4200"})"_json, "foo"); + EXPECT_EQ(id, 0x4200); + + // Get it from the reason code on a 0xBD SRC + id = getComponentID(0xBD, 0x6700, R"({})"_json, "foo"); + EXPECT_EQ(id, 0x6700); + + // Not present on a 0x11 SRC + EXPECT_THROW(getComponentID(0x11, 0x8800, R"({})"_json, "foo"), + std::runtime_error); +} |