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