blob: a16370fa693ecc1268a52efced61e9ff39001bdb [file] [log] [blame]
Matt Spinler367144c2019-09-19 15:33:52 -05001#include "extensions/openpower-pels/registry.hpp"
2
3#include <filesystem>
4#include <fstream>
5#include <nlohmann/json.hpp>
6
7#include <gtest/gtest.h>
8
9using namespace openpower::pels::message;
10namespace fs = std::filesystem;
11
12const auto registryData = R"(
13{
14 "PELs":
15 [
16 {
17 "Name": "xyz.openbmc_project.Power.Fault",
18 "Subsystem": "power_supply",
19 "ActionFlags": ["service_action", "report"],
20
21 "SRC":
22 {
23 "ReasonCode": "0x2030"
24 }
25 },
26
27 {
28 "Name": "xyz.openbmc_project.Power.OverVoltage",
29 "Subsystem": "power_control_hw",
30 "Severity": "unrecoverable",
31 "MfgSeverity": "non_error",
32 "ActionFlags": ["service_action", "report", "call_home"],
33 "MfgActionFlags": ["hidden"],
34
35 "SRC":
36 {
37 "ReasonCode": "0x2333",
38 "Type": "BD",
39 "SymptomIDFields": ["SRCWord5", "SRCWord6", "SRCWord7"],
40 "PowerFault": true,
41 "Words6To9":
42 {
43 "6":
44 {
45 "description": "Failing unit number",
46 "AdditionalDataPropSource": "PS_NUM"
47 },
48
49 "7":
50 {
51 "description": "bad voltage",
52 "AdditionalDataPropSource": "VOLTAGE"
53 }
54 }
55 }
56 }
57 ]
58}
59)";
60
61class RegistryTest : public ::testing::Test
62{
63 protected:
64 static void SetUpTestCase()
65 {
66 char path[] = "/tmp/regtestXXXXXX";
67 regDir = mkdtemp(path);
68 }
69
70 static void TearDownTestCase()
71 {
72 fs::remove_all(regDir);
73 }
74
75 static std::string writeData(const char* data)
76 {
77 fs::path path = regDir / "registry.json";
78 std::ofstream stream{path};
79 stream << data;
80 return path;
81 }
82
83 static fs::path regDir;
84};
85
86fs::path RegistryTest::regDir{};
87
88TEST_F(RegistryTest, TestNoEntry)
89{
90 auto path = RegistryTest::writeData(registryData);
91 Registry registry{path};
92
93 auto entry = registry.lookup("foo");
94 EXPECT_FALSE(entry);
95}
96
97TEST_F(RegistryTest, TestFindEntry)
98{
99 auto path = RegistryTest::writeData(registryData);
100 Registry registry{path};
101
102 auto entry = registry.lookup("xyz.openbmc_project.Power.OverVoltage");
103 ASSERT_TRUE(entry);
104 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage");
105 EXPECT_EQ(entry->subsystem, 0x62);
106 EXPECT_EQ(*(entry->severity), 0x40);
107 EXPECT_EQ(*(entry->mfgSeverity), 0x00);
108 EXPECT_EQ(entry->actionFlags, 0xA800);
109 EXPECT_EQ(*(entry->mfgActionFlags), 0x4000);
Matt Spinler93e29322019-09-20 11:16:15 -0500110 EXPECT_EQ(entry->componentID, 0x2300);
Matt Spinler367144c2019-09-19 15:33:52 -0500111 EXPECT_FALSE(entry->eventType);
112 EXPECT_FALSE(entry->eventScope);
113
Matt Spinler93e29322019-09-20 11:16:15 -0500114 EXPECT_EQ(entry->src.type, 0xBD);
115 EXPECT_EQ(entry->src.reasonCode, 0x2333);
116 EXPECT_EQ(*(entry->src.powerFault), true);
117
118 auto& hexwords = entry->src.hexwordADFields;
119 EXPECT_TRUE(hexwords);
120 EXPECT_EQ((*hexwords).size(), 2);
121
122 auto word = (*hexwords).find(6);
123 EXPECT_NE(word, (*hexwords).end());
124 EXPECT_EQ(word->second, "PS_NUM");
125
126 word = (*hexwords).find(7);
127 EXPECT_NE(word, (*hexwords).end());
128 EXPECT_EQ(word->second, "VOLTAGE");
129
130 auto& sid = entry->src.symptomID;
131 EXPECT_TRUE(sid);
132 EXPECT_EQ((*sid).size(), 3);
133 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 5), (*sid).end());
134 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 6), (*sid).end());
135 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 7), (*sid).end());
Matt Spinler367144c2019-09-19 15:33:52 -0500136}
137
138// Check the entry that mostly uses defaults
139TEST_F(RegistryTest, TestFindEntryMinimal)
140{
141 auto path = RegistryTest::writeData(registryData);
142 Registry registry{path};
143
144 auto entry = registry.lookup("xyz.openbmc_project.Power.Fault");
145 ASSERT_TRUE(entry);
146 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.Fault");
147 EXPECT_EQ(entry->subsystem, 0x61);
148 EXPECT_FALSE(entry->severity);
149 EXPECT_FALSE(entry->mfgSeverity);
150 EXPECT_FALSE(entry->mfgActionFlags);
151 EXPECT_EQ(entry->actionFlags, 0xA000);
Matt Spinler93e29322019-09-20 11:16:15 -0500152 EXPECT_EQ(entry->componentID, 0x2000);
Matt Spinler367144c2019-09-19 15:33:52 -0500153 EXPECT_FALSE(entry->eventType);
154 EXPECT_FALSE(entry->eventScope);
Matt Spinler93e29322019-09-20 11:16:15 -0500155
156 EXPECT_EQ(entry->src.reasonCode, 0x2030);
157 EXPECT_EQ(entry->src.type, 0xBD);
158 EXPECT_FALSE(entry->src.powerFault);
159 EXPECT_FALSE(entry->src.hexwordADFields);
160 EXPECT_FALSE(entry->src.symptomID);
Matt Spinler367144c2019-09-19 15:33:52 -0500161}
162
163TEST_F(RegistryTest, TestBadJSON)
164{
165 auto path = RegistryTest::writeData("bad {} json");
166
167 Registry registry{path};
168
169 EXPECT_FALSE(registry.lookup("foo"));
170}
171
172// Test the helper functions the use the pel_values data.
173TEST_F(RegistryTest, TestHelperFunctions)
174{
175 using namespace openpower::pels::message::helper;
176 EXPECT_EQ(getSubsystem("input_power_source"), 0xA1);
177 EXPECT_THROW(getSubsystem("foo"), std::runtime_error);
178
179 EXPECT_EQ(getSeverity("symptom_recovered"), 0x71);
180 EXPECT_THROW(getSeverity("foo"), std::runtime_error);
181
182 EXPECT_EQ(getEventType("dump_notification"), 0x08);
183 EXPECT_THROW(getEventType("foo"), std::runtime_error);
184
185 EXPECT_EQ(getEventScope("possibly_multiple_platforms"), 0x04);
186 EXPECT_THROW(getEventScope("foo"), std::runtime_error);
187
188 std::vector<std::string> flags{"service_action", "dont_report",
189 "termination"};
190 EXPECT_EQ(getActionFlags(flags), 0x9100);
191
192 flags.clear();
193 flags.push_back("foo");
194 EXPECT_THROW(getActionFlags(flags), std::runtime_error);
195}
Matt Spinler93e29322019-09-20 11:16:15 -0500196
197TEST_F(RegistryTest, TestGetSRCReasonCode)
198{
199 using namespace openpower::pels::message::helper;
200 EXPECT_EQ(getSRCReasonCode(R"({"ReasonCode": "0x5555"})"_json, "foo"),
201 0x5555);
202
203 EXPECT_THROW(getSRCReasonCode(R"({"ReasonCode": "ZZZZ"})"_json, "foo"),
204 std::runtime_error);
205}
206
207TEST_F(RegistryTest, TestGetSRCType)
208{
209 using namespace openpower::pels::message::helper;
210 EXPECT_EQ(getSRCType(R"({"Type": "11"})"_json, "foo"), 0x11);
211 EXPECT_EQ(getSRCType(R"({"Type": "BF"})"_json, "foo"), 0xBF);
212
213 EXPECT_THROW(getSRCType(R"({"Type": "1"})"_json, "foo"),
214 std::runtime_error);
215
216 EXPECT_THROW(getSRCType(R"({"Type": "111"})"_json, "foo"),
217 std::runtime_error);
218}
219
220TEST_F(RegistryTest, TestGetSRCHexwordFields)
221{
222 using namespace openpower::pels::message::helper;
223 const auto hexwords = R"(
224 {"Words6To9":
225 {
226 "8":
227 {
228 "AdditionalDataPropSource": "TEST"
229 }
230 }
231 })"_json;
232
233 auto fields = getSRCHexwordFields(hexwords, "foo");
234 EXPECT_TRUE(fields);
235 auto word = fields->find(8);
236 EXPECT_NE(word, fields->end());
237
238 const auto theInvalidRWord = R"(
239 {"Words6To9":
240 {
241 "R":
242 {
243 "AdditionalDataPropSource": "TEST"
244 }
245 }
246 })"_json;
247
248 EXPECT_THROW(getSRCHexwordFields(theInvalidRWord, "foo"),
249 std::runtime_error);
250}
251
252TEST_F(RegistryTest, TestGetSRCSymptomIDFields)
253{
254 using namespace openpower::pels::message::helper;
255 const auto sID = R"(
256 {
257 "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord5"]
258 })"_json;
259
260 auto fields = getSRCSymptomIDFields(sID, "foo");
261 EXPECT_NE(std::find(fields->begin(), fields->end(), 3), fields->end());
262 EXPECT_NE(std::find(fields->begin(), fields->end(), 4), fields->end());
263 EXPECT_NE(std::find(fields->begin(), fields->end(), 5), fields->end());
264
265 const auto badField = R"(
266 {
267 "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord"]
268 })"_json;
269
270 EXPECT_THROW(getSRCSymptomIDFields(badField, "foo"), std::runtime_error);
271}
272
273TEST_F(RegistryTest, TestGetComponentID)
274{
275 using namespace openpower::pels::message::helper;
276
277 // Get it from the JSON
278 auto id =
279 getComponentID(0xBD, 0x4200, R"({"ComponentID":"0x4200"})"_json, "foo");
280 EXPECT_EQ(id, 0x4200);
281
282 // Get it from the reason code on a 0xBD SRC
283 id = getComponentID(0xBD, 0x6700, R"({})"_json, "foo");
284 EXPECT_EQ(id, 0x6700);
285
286 // Not present on a 0x11 SRC
287 EXPECT_THROW(getComponentID(0x11, 0x8800, R"({})"_json, "foo"),
288 std::runtime_error);
289}