blob: 2944ce0ab689101c1e6c78a0dc9852e379896e51 [file] [log] [blame]
Matt Spinler97f7abc2019-11-06 09:40:23 -06001/**
2 * Copyright © 2019 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 */
Matt Spinler367144c2019-09-19 15:33:52 -050016#include "extensions/openpower-pels/registry.hpp"
17
18#include <filesystem>
19#include <fstream>
20#include <nlohmann/json.hpp>
21
22#include <gtest/gtest.h>
23
24using namespace openpower::pels::message;
25namespace fs = std::filesystem;
26
27const auto registryData = R"(
28{
29 "PELs":
30 [
31 {
32 "Name": "xyz.openbmc_project.Power.Fault",
33 "Subsystem": "power_supply",
Matt Spinler367144c2019-09-19 15:33:52 -050034
35 "SRC":
36 {
37 "ReasonCode": "0x2030"
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080038 },
39
40 "Documentation":
41 {
42 "Description": "A PGOOD Fault",
43 "Message": "PS had a PGOOD Fault"
Matt Spinler367144c2019-09-19 15:33:52 -050044 }
45 },
46
47 {
48 "Name": "xyz.openbmc_project.Power.OverVoltage",
49 "Subsystem": "power_control_hw",
50 "Severity": "unrecoverable",
51 "MfgSeverity": "non_error",
52 "ActionFlags": ["service_action", "report", "call_home"],
53 "MfgActionFlags": ["hidden"],
54
55 "SRC":
56 {
57 "ReasonCode": "0x2333",
58 "Type": "BD",
59 "SymptomIDFields": ["SRCWord5", "SRCWord6", "SRCWord7"],
60 "PowerFault": true,
61 "Words6To9":
62 {
63 "6":
64 {
65 "description": "Failing unit number",
66 "AdditionalDataPropSource": "PS_NUM"
67 },
68
69 "7":
70 {
71 "description": "bad voltage",
72 "AdditionalDataPropSource": "VOLTAGE"
73 }
74 }
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080075 },
76
77 "Documentation":
78 {
79 "Description": "A PGOOD Fault",
80 "Message": "PS %1 had a PGOOD Fault",
81 "MessageArgSources":
82 [
83 "SRCWord6"
84 ],
85 "Notes": [
86 "In the UserData section there is a JSON",
87 "dump that provides debug information."
88 ]
Matt Spinler367144c2019-09-19 15:33:52 -050089 }
90 }
91 ]
92}
93)";
94
95class RegistryTest : public ::testing::Test
96{
97 protected:
98 static void SetUpTestCase()
99 {
100 char path[] = "/tmp/regtestXXXXXX";
101 regDir = mkdtemp(path);
102 }
103
104 static void TearDownTestCase()
105 {
106 fs::remove_all(regDir);
107 }
108
109 static std::string writeData(const char* data)
110 {
111 fs::path path = regDir / "registry.json";
112 std::ofstream stream{path};
113 stream << data;
114 return path;
115 }
116
117 static fs::path regDir;
118};
119
120fs::path RegistryTest::regDir{};
121
122TEST_F(RegistryTest, TestNoEntry)
123{
124 auto path = RegistryTest::writeData(registryData);
125 Registry registry{path};
126
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800127 auto entry = registry.lookup("foo", LookupType::name);
Matt Spinler367144c2019-09-19 15:33:52 -0500128 EXPECT_FALSE(entry);
129}
130
131TEST_F(RegistryTest, TestFindEntry)
132{
133 auto path = RegistryTest::writeData(registryData);
134 Registry registry{path};
135
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800136 auto entry = registry.lookup("xyz.openbmc_project.Power.OverVoltage",
137 LookupType::name);
Matt Spinler367144c2019-09-19 15:33:52 -0500138 ASSERT_TRUE(entry);
139 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage");
140 EXPECT_EQ(entry->subsystem, 0x62);
141 EXPECT_EQ(*(entry->severity), 0x40);
142 EXPECT_EQ(*(entry->mfgSeverity), 0x00);
Matt Spinlere07f9152019-11-01 10:48:36 -0500143 EXPECT_EQ(*(entry->actionFlags), 0xA800);
Matt Spinler367144c2019-09-19 15:33:52 -0500144 EXPECT_EQ(*(entry->mfgActionFlags), 0x4000);
Matt Spinler93e29322019-09-20 11:16:15 -0500145 EXPECT_EQ(entry->componentID, 0x2300);
Matt Spinler367144c2019-09-19 15:33:52 -0500146 EXPECT_FALSE(entry->eventType);
147 EXPECT_FALSE(entry->eventScope);
148
Matt Spinler93e29322019-09-20 11:16:15 -0500149 EXPECT_EQ(entry->src.type, 0xBD);
150 EXPECT_EQ(entry->src.reasonCode, 0x2333);
151 EXPECT_EQ(*(entry->src.powerFault), true);
152
153 auto& hexwords = entry->src.hexwordADFields;
154 EXPECT_TRUE(hexwords);
155 EXPECT_EQ((*hexwords).size(), 2);
156
157 auto word = (*hexwords).find(6);
158 EXPECT_NE(word, (*hexwords).end());
159 EXPECT_EQ(word->second, "PS_NUM");
160
161 word = (*hexwords).find(7);
162 EXPECT_NE(word, (*hexwords).end());
163 EXPECT_EQ(word->second, "VOLTAGE");
164
165 auto& sid = entry->src.symptomID;
166 EXPECT_TRUE(sid);
167 EXPECT_EQ((*sid).size(), 3);
168 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 5), (*sid).end());
169 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 6), (*sid).end());
170 EXPECT_NE(std::find((*sid).begin(), (*sid).end(), 7), (*sid).end());
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800171
172 EXPECT_EQ(entry->doc.description, "A PGOOD Fault");
173 EXPECT_EQ(entry->doc.message, "PS %1 had a PGOOD Fault");
174 auto& hexwordSource = entry->doc.messageArgSources;
175 EXPECT_TRUE(hexwordSource);
176 EXPECT_EQ((*hexwordSource).size(), 1);
177 EXPECT_EQ((*hexwordSource).front(), "SRCWord6");
178
179 entry = registry.lookup("0x2333", LookupType::reasonCode);
180 ASSERT_TRUE(entry);
181 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.OverVoltage");
Matt Spinler367144c2019-09-19 15:33:52 -0500182}
183
184// Check the entry that mostly uses defaults
185TEST_F(RegistryTest, TestFindEntryMinimal)
186{
187 auto path = RegistryTest::writeData(registryData);
188 Registry registry{path};
189
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800190 auto entry =
191 registry.lookup("xyz.openbmc_project.Power.Fault", LookupType::name);
Matt Spinler367144c2019-09-19 15:33:52 -0500192 ASSERT_TRUE(entry);
193 EXPECT_EQ(entry->name, "xyz.openbmc_project.Power.Fault");
194 EXPECT_EQ(entry->subsystem, 0x61);
195 EXPECT_FALSE(entry->severity);
196 EXPECT_FALSE(entry->mfgSeverity);
197 EXPECT_FALSE(entry->mfgActionFlags);
Matt Spinlere07f9152019-11-01 10:48:36 -0500198 EXPECT_FALSE(entry->actionFlags);
Matt Spinler93e29322019-09-20 11:16:15 -0500199 EXPECT_EQ(entry->componentID, 0x2000);
Matt Spinler367144c2019-09-19 15:33:52 -0500200 EXPECT_FALSE(entry->eventType);
201 EXPECT_FALSE(entry->eventScope);
Matt Spinler93e29322019-09-20 11:16:15 -0500202
203 EXPECT_EQ(entry->src.reasonCode, 0x2030);
204 EXPECT_EQ(entry->src.type, 0xBD);
205 EXPECT_FALSE(entry->src.powerFault);
206 EXPECT_FALSE(entry->src.hexwordADFields);
207 EXPECT_FALSE(entry->src.symptomID);
Matt Spinler367144c2019-09-19 15:33:52 -0500208}
209
210TEST_F(RegistryTest, TestBadJSON)
211{
212 auto path = RegistryTest::writeData("bad {} json");
213
214 Registry registry{path};
215
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800216 EXPECT_FALSE(registry.lookup("foo", LookupType::name));
Matt Spinler367144c2019-09-19 15:33:52 -0500217}
218
219// Test the helper functions the use the pel_values data.
220TEST_F(RegistryTest, TestHelperFunctions)
221{
222 using namespace openpower::pels::message::helper;
223 EXPECT_EQ(getSubsystem("input_power_source"), 0xA1);
224 EXPECT_THROW(getSubsystem("foo"), std::runtime_error);
225
226 EXPECT_EQ(getSeverity("symptom_recovered"), 0x71);
227 EXPECT_THROW(getSeverity("foo"), std::runtime_error);
228
229 EXPECT_EQ(getEventType("dump_notification"), 0x08);
230 EXPECT_THROW(getEventType("foo"), std::runtime_error);
231
232 EXPECT_EQ(getEventScope("possibly_multiple_platforms"), 0x04);
233 EXPECT_THROW(getEventScope("foo"), std::runtime_error);
234
235 std::vector<std::string> flags{"service_action", "dont_report",
236 "termination"};
237 EXPECT_EQ(getActionFlags(flags), 0x9100);
238
239 flags.clear();
240 flags.push_back("foo");
241 EXPECT_THROW(getActionFlags(flags), std::runtime_error);
242}
Matt Spinler93e29322019-09-20 11:16:15 -0500243
244TEST_F(RegistryTest, TestGetSRCReasonCode)
245{
246 using namespace openpower::pels::message::helper;
247 EXPECT_EQ(getSRCReasonCode(R"({"ReasonCode": "0x5555"})"_json, "foo"),
248 0x5555);
249
250 EXPECT_THROW(getSRCReasonCode(R"({"ReasonCode": "ZZZZ"})"_json, "foo"),
251 std::runtime_error);
252}
253
254TEST_F(RegistryTest, TestGetSRCType)
255{
256 using namespace openpower::pels::message::helper;
257 EXPECT_EQ(getSRCType(R"({"Type": "11"})"_json, "foo"), 0x11);
258 EXPECT_EQ(getSRCType(R"({"Type": "BF"})"_json, "foo"), 0xBF);
259
260 EXPECT_THROW(getSRCType(R"({"Type": "1"})"_json, "foo"),
261 std::runtime_error);
262
263 EXPECT_THROW(getSRCType(R"({"Type": "111"})"_json, "foo"),
264 std::runtime_error);
265}
266
267TEST_F(RegistryTest, TestGetSRCHexwordFields)
268{
269 using namespace openpower::pels::message::helper;
270 const auto hexwords = R"(
271 {"Words6To9":
272 {
273 "8":
274 {
275 "AdditionalDataPropSource": "TEST"
276 }
277 }
278 })"_json;
279
280 auto fields = getSRCHexwordFields(hexwords, "foo");
281 EXPECT_TRUE(fields);
282 auto word = fields->find(8);
283 EXPECT_NE(word, fields->end());
284
285 const auto theInvalidRWord = R"(
286 {"Words6To9":
287 {
288 "R":
289 {
290 "AdditionalDataPropSource": "TEST"
291 }
292 }
293 })"_json;
294
295 EXPECT_THROW(getSRCHexwordFields(theInvalidRWord, "foo"),
296 std::runtime_error);
297}
298
299TEST_F(RegistryTest, TestGetSRCSymptomIDFields)
300{
301 using namespace openpower::pels::message::helper;
302 const auto sID = R"(
303 {
304 "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord5"]
305 })"_json;
306
307 auto fields = getSRCSymptomIDFields(sID, "foo");
308 EXPECT_NE(std::find(fields->begin(), fields->end(), 3), fields->end());
309 EXPECT_NE(std::find(fields->begin(), fields->end(), 4), fields->end());
310 EXPECT_NE(std::find(fields->begin(), fields->end(), 5), fields->end());
311
312 const auto badField = R"(
313 {
314 "SymptomIDFields": ["SRCWord3", "SRCWord4", "SRCWord"]
315 })"_json;
316
317 EXPECT_THROW(getSRCSymptomIDFields(badField, "foo"), std::runtime_error);
318}
319
320TEST_F(RegistryTest, TestGetComponentID)
321{
322 using namespace openpower::pels::message::helper;
323
324 // Get it from the JSON
325 auto id =
326 getComponentID(0xBD, 0x4200, R"({"ComponentID":"0x4200"})"_json, "foo");
327 EXPECT_EQ(id, 0x4200);
328
329 // Get it from the reason code on a 0xBD SRC
330 id = getComponentID(0xBD, 0x6700, R"({})"_json, "foo");
331 EXPECT_EQ(id, 0x6700);
332
333 // Not present on a 0x11 SRC
334 EXPECT_THROW(getComponentID(0x11, 0x8800, R"({})"_json, "foo"),
335 std::runtime_error);
336}