blob: 2c53fd9ec7869e49183f94d7798a840212151db9 [file] [log] [blame]
Matt Spinler05f0c6d2020-08-05 14:21:06 -05001/**
2 * Copyright © 2020 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 */
16#include "extensions/openpower-pels/service_indicators.hpp"
17#include "mocks.hpp"
18#include "pel_utils.hpp"
19
20#include <gtest/gtest.h>
21
22using namespace openpower::pels;
23using CalloutVector = std::vector<std::unique_ptr<src::Callout>>;
24using ::testing::_;
25using ::testing::Return;
26using ::testing::Throw;
27
28// Test the ignore() function works
29TEST(ServiceIndicatorsTest, IgnoreTest)
30{
31 MockDataInterface dataIface;
32 service_indicators::LightPath lightPath{dataIface};
33
34 // PEL must have serviceable action flag set and be created
35 // by the BMC or Hostboot.
36 std::vector<std::tuple<char, uint16_t, bool>> testParams{
37 {'O', 0xA400, false}, // BMC serviceable, don't ignore
38 {'B', 0xA400, false}, // Hostboot serviceable, don't ignore
39 {'H', 0xA400, true}, // PHYP serviceable, ignore
40 {'O', 0x2400, true}, // BMC not serviceable, ignore
41 {'B', 0x2400, true}, // Hostboot not serviceable, ignore
42 {'H', 0x2400, true}, // PHYP not serviceable, ignore
43 };
44
45 for (const auto& test : testParams)
46 {
47 auto data = pelFactory(1, std::get<char>(test), 0x20,
48 std::get<uint16_t>(test), 500);
49 PEL pel{data};
50
51 EXPECT_EQ(lightPath.ignore(pel), std::get<bool>(test));
52 }
53}
54
55// Test that only high, medium, and medium group A hardware
56// callouts have their location codes extracted.
57TEST(ServiceIndicatorsTest, OneCalloutPriorityTest)
58{
59 MockDataInterface dataIface;
60 service_indicators::LightPath lightPath{dataIface};
61
62 // The priorities to test, with the expected getLocationCodes results.
63 std::vector<std::tuple<CalloutPriority, std::vector<std::string>>>
64 testCallouts{{CalloutPriority::high, {"U27-P1"}},
65 {CalloutPriority::medium, {"U27-P1"}},
66 {CalloutPriority::mediumGroupA, {"U27-P1"}},
67 {CalloutPriority::mediumGroupB, {}},
68 {CalloutPriority::mediumGroupC, {}},
69 {CalloutPriority::low, {}}};
70
71 for (const auto& test : testCallouts)
72 {
73 auto callout = std::make_unique<src::Callout>(
74 std::get<CalloutPriority>(test), "U27-P1", "1234567", "aaaa",
75 "123456789ABC");
76
77 CalloutVector callouts;
78 callouts.push_back(std::move(callout));
79
80 EXPECT_EQ(lightPath.getLocationCodes(callouts),
81 std::get<std::vector<std::string>>(test));
82 }
83}
84
85// Test that only normal hardware callouts and symbolic FRU
86// callouts with trusted location codes have their location
87// codes extracted.
88TEST(ServiceIndicatorsTest, OneCalloutTypeTest)
89{
90 MockDataInterface dataIface;
91 service_indicators::LightPath lightPath{dataIface};
92
93 // Regular hardware callout
94 {
95 CalloutVector callouts;
96 callouts.push_back(
97 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P1",
98 "1234567", "aaaa", "123456789ABC"));
99
100 EXPECT_EQ(lightPath.getLocationCodes(callouts),
101 std::vector<std::string>{"U27-P1"});
102 }
103
104 // Symbolic FRU with trusted loc code callout
105 {
106 CalloutVector callouts;
107 callouts.push_back(std::make_unique<src::Callout>(
108 CalloutPriority::high, "service_docs", "U27-P1", true));
109
110 EXPECT_EQ(lightPath.getLocationCodes(callouts),
111 std::vector<std::string>{"U27-P1"});
112 }
113
114 // Symbolic FRU without trusted loc code callout
115 {
116 CalloutVector callouts;
117 callouts.push_back(std::make_unique<src::Callout>(
118 CalloutPriority::high, "service_docs", "U27-P1", false));
119
120 EXPECT_EQ(lightPath.getLocationCodes(callouts),
121 std::vector<std::string>{});
122 }
123
124 // Procedure callout
125 {
126 CalloutVector callouts;
127 callouts.push_back(
128 std::make_unique<src::Callout>(CalloutPriority::high, "bmc_code"));
129
130 EXPECT_EQ(lightPath.getLocationCodes(callouts),
131 std::vector<std::string>{});
132 }
133}
134
135// Test that only the callouts in the first group have their location
136// codes extracted, where a group is one or more callouts listed
137// together with priorities of high, medium, or medium group A
138// (and medium is only ever contains 1 item).
139TEST(ServiceIndicatorsTest, CalloutGroupingTest)
140{
141 MockDataInterface dataIface;
142 service_indicators::LightPath lightPath{dataIface};
143
144 // high/high/medium/high just grabs the first 2
145 {
146 CalloutVector callouts;
147 callouts.push_back(
148 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P1",
149 "1234567", "aaaa", "123456789ABC"));
150 callouts.push_back(
151 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P2",
152 "1234567", "aaaa", "123456789ABC"));
153 callouts.push_back(
154 std::make_unique<src::Callout>(CalloutPriority::medium, "U27-P3",
155 "1234567", "aaaa", "123456789ABC"));
156 // This high priority callout after a medium isn't actually valid, since
157 // callouts are sorted, but test it anyway.
158 callouts.push_back(
159 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P4",
160 "1234567", "aaaa", "123456789ABC"));
161
162 EXPECT_EQ(lightPath.getLocationCodes(callouts),
163 (std::vector<std::string>{"U27-P1", "U27-P2"}));
164 }
165
166 // medium/medium just grabs the first medium
167 {
168 CalloutVector callouts;
169 callouts.push_back(
170 std::make_unique<src::Callout>(CalloutPriority::medium, "U27-P1",
171 "1234567", "aaaa", "123456789ABC"));
172 callouts.push_back(
173 std::make_unique<src::Callout>(CalloutPriority::medium, "U27-P2",
174 "1234567", "aaaa", "123456789ABC"));
175
176 EXPECT_EQ(lightPath.getLocationCodes(callouts),
177 std::vector<std::string>{"U27-P1"});
178 }
179
180 // mediumA/mediumA/medium just grabs the first 2
181 {
182 CalloutVector callouts;
183 callouts.push_back(std::make_unique<src::Callout>(
184 CalloutPriority::mediumGroupA, "U27-P1", "1234567", "aaaa",
185 "123456789ABC"));
186
187 callouts.push_back(std::make_unique<src::Callout>(
188 CalloutPriority::mediumGroupA, "U27-P2", "1234567", "aaaa",
189 "123456789ABC"));
190
191 callouts.push_back(
192 std::make_unique<src::Callout>(CalloutPriority::medium, "U27-P3",
193 "1234567", "aaaa", "123456789ABC"));
194
195 EXPECT_EQ(lightPath.getLocationCodes(callouts),
196 (std::vector<std::string>{"U27-P1", "U27-P2"}));
197 }
198}
199
200// Test that if any callouts in group are not HW/trusted symbolic
201// FRU callouts then no location codes will be extracted
202TEST(ServiceIndicatorsTest, CalloutMixedTypesTest)
203{
204 MockDataInterface dataIface;
205 service_indicators::LightPath lightPath{dataIface};
206
207 // Mixing FRU with trusted symbolic FRU is OK
208 {
209 CalloutVector callouts;
210 callouts.push_back(
211 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P1",
212 "1234567", "aaaa", "123456789ABC"));
213 callouts.push_back(std::make_unique<src::Callout>(
214 CalloutPriority::high, "service_docs", "U27-P2", true));
215
216 EXPECT_EQ(lightPath.getLocationCodes(callouts),
217 (std::vector<std::string>{"U27-P1", "U27-P2"}));
218 }
219
220 // Normal FRU callout with a non-trusted symbolic FRU callout not OK
221 {
222 CalloutVector callouts;
223 callouts.push_back(
224 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P1",
225 "1234567", "aaaa", "123456789ABC"));
226 callouts.push_back(std::make_unique<src::Callout>(
227 CalloutPriority::high, "service_docs", "U27-P2", false));
228
229 EXPECT_EQ(lightPath.getLocationCodes(callouts),
230 (std::vector<std::string>{}));
231 }
232
233 // Normal FRU callout with a procedure callout not OK
234 {
235 CalloutVector callouts;
236 callouts.push_back(
237 std::make_unique<src::Callout>(CalloutPriority::high, "U27-P1",
238 "1234567", "aaaa", "123456789ABC"));
239 callouts.push_back(
240 std::make_unique<src::Callout>(CalloutPriority::high, "bmc_code"));
241
242 EXPECT_EQ(lightPath.getLocationCodes(callouts),
243 (std::vector<std::string>{}));
244 }
245
246 // Trusted symbolic FRU callout with a non-trusted symbolic
247 // FRU callout not OK
248 {
249 CalloutVector callouts;
250 callouts.push_back(std::make_unique<src::Callout>(
251 CalloutPriority::high, "service_docs", "U27-P2", true));
252
253 callouts.push_back(std::make_unique<src::Callout>(
254 CalloutPriority::high, "service_docs", "U27-P2", false));
255
256 EXPECT_EQ(lightPath.getLocationCodes(callouts),
257 (std::vector<std::string>{}));
258 }
259}
Matt Spinler34a904c2020-08-05 14:53:28 -0500260
261// Test the activate() function
262TEST(ServiceIndicatorsTest, ActivateTest)
263{
264 // pelFactory() will create a PEL with 1 callout with location code
265 // U42. Test the LED for that gets activated.
266 {
267 MockDataInterface dataIface;
268 service_indicators::LightPath lightPath{dataIface};
269
270 EXPECT_CALL(dataIface, getInventoryFromLocCode("U42", 0, true))
271 .WillOnce(Return("/system/chassis/processor"));
272
Matt Spinler993168d2021-04-07 16:05:03 -0500273 EXPECT_CALL(dataIface,
274 setFunctional("/system/chassis/processor", false))
Matt Spinler34a904c2020-08-05 14:53:28 -0500275 .Times(1);
276
Sumit Kumar76198a22021-07-15 05:59:57 -0500277 EXPECT_CALL(dataIface,
278 setCriticalAssociation("/system/chassis/processor"))
279 .Times(1);
280
Matt Spinler34a904c2020-08-05 14:53:28 -0500281 auto data = pelFactory(1, 'O', 0x20, 0xA400, 500);
282 PEL pel{data};
283
284 lightPath.activate(pel);
285 }
286
Matt Spinler48c44db2020-08-25 12:47:13 -0500287 // A non-info BMC PEL with no callouts will set the platform SAI LED.
288 {
289 MockDataInterface dataIface;
290 service_indicators::LightPath lightPath{dataIface};
291
292 EXPECT_CALL(dataIface,
293 assertLEDGroup("/xyz/openbmc_project/led/groups/"
294 "platform_system_attention_indicator",
295 true))
296 .Times(1);
297
298 auto data = pelDataFactory(TestPELType::pelSimple);
299 PEL pel{data};
300
301 lightPath.activate(pel);
302 }
303
304 // Make getInventoryFromLocCode fail - will set the platform SAI LED
Matt Spinler34a904c2020-08-05 14:53:28 -0500305 {
306 MockDataInterface dataIface;
307 service_indicators::LightPath lightPath{dataIface};
308
309 EXPECT_CALL(dataIface, getInventoryFromLocCode("U42", 0, true))
310 .WillOnce(Throw(std::runtime_error("Fail")));
311
Matt Spinler993168d2021-04-07 16:05:03 -0500312 EXPECT_CALL(dataIface, setFunctional).Times(0);
Matt Spinler34a904c2020-08-05 14:53:28 -0500313
Matt Spinler48c44db2020-08-25 12:47:13 -0500314 EXPECT_CALL(dataIface,
315 assertLEDGroup("/xyz/openbmc_project/led/groups/"
316 "platform_system_attention_indicator",
317 true))
318 .Times(1);
Matt Spinler34a904c2020-08-05 14:53:28 -0500319
320 auto data = pelFactory(1, 'O', 0x20, 0xA400, 500);
321 PEL pel{data};
322
323 lightPath.activate(pel);
324 }
325
Matt Spinler993168d2021-04-07 16:05:03 -0500326 // Make setFunctional fail
Matt Spinler34a904c2020-08-05 14:53:28 -0500327 {
328 MockDataInterface dataIface;
329 service_indicators::LightPath lightPath{dataIface};
330
331 EXPECT_CALL(dataIface, getInventoryFromLocCode("U42", 0, true))
332 .WillOnce(Return("/system/chassis/processor"));
333
Matt Spinler48c44db2020-08-25 12:47:13 -0500334 EXPECT_CALL(dataIface,
Matt Spinler993168d2021-04-07 16:05:03 -0500335 setFunctional("/system/chassis/processor", false))
Matt Spinler34a904c2020-08-05 14:53:28 -0500336 .WillOnce(Throw(std::runtime_error("Fail")));
337
338 auto data = pelFactory(1, 'O', 0x20, 0xA400, 500);
339 PEL pel{data};
340
341 lightPath.activate(pel);
342 }
Sumit Kumar76198a22021-07-15 05:59:57 -0500343
344 // Test setCriticalAssociation fail
345 {
346 MockDataInterface dataIface;
347 service_indicators::LightPath lightPath{dataIface};
348
349 EXPECT_CALL(dataIface, getInventoryFromLocCode("U42", 0, true))
350 .WillOnce(Return("/system/chassis/processor"));
351
352 EXPECT_CALL(dataIface,
353 setCriticalAssociation("/system/chassis/processor"))
354 .WillOnce(Throw(std::runtime_error("Fail")));
355
356 auto data = pelFactory(1, 'O', 0x20, 0xA400, 500);
357 PEL pel{data};
358
359 lightPath.activate(pel);
360 }
Matt Spinler34a904c2020-08-05 14:53:28 -0500361}