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