blob: ed8af4bbf690ce9876df391d4ec11514799864e6 [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 Spinlerf9bae182019-10-09 13:37:38 -050016#include "extensions/openpower-pels/src.hpp"
Matt Spinler075e5ba2020-02-21 15:46:00 -060017#include "mocks.hpp"
Matt Spinlerf9bae182019-10-09 13:37:38 -050018#include "pel_utils.hpp"
19
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080020#include <fstream>
21
Matt Spinlerf9bae182019-10-09 13:37:38 -050022#include <gtest/gtest.h>
23
24using namespace openpower::pels;
Matt Spinlered046852020-03-13 13:58:15 -050025using ::testing::_;
William A. Kennington IIIb41fa542021-05-29 14:45:16 -070026using ::testing::DoAll;
Matt Spinlered046852020-03-13 13:58:15 -050027using ::testing::InvokeWithoutArgs;
Matt Spinler075e5ba2020-02-21 15:46:00 -060028using ::testing::NiceMock;
29using ::testing::Return;
Matt Spinlered046852020-03-13 13:58:15 -050030using ::testing::SetArgReferee;
Matt Spinler3bdd0112020-08-27 10:24:34 -050031using ::testing::Throw;
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080032namespace fs = std::filesystem;
Matt Spinlerf9bae182019-10-09 13:37:38 -050033
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +080034const auto testRegistry = R"(
35{
36"PELs":
37[
38 {
39 "Name": "xyz.openbmc_project.Error.Test",
40 "Subsystem": "bmc_firmware",
41 "SRC":
42 {
43 "ReasonCode": "0xABCD",
44 "Words6To9":
45 {
46 "6":
47 {
48 "Description": "Component ID",
49 "AdditionalDataPropSource": "COMPID"
50 },
51 "7":
52 {
53 "Description": "Failure count",
54 "AdditionalDataPropSource": "FREQUENCY"
55 },
56 "8":
57 {
58 "Description": "Time period",
59 "AdditionalDataPropSource": "DURATION"
60 },
61 "9":
62 {
63 "Description": "Error code",
64 "AdditionalDataPropSource": "ERRORCODE"
65 }
66 }
67 },
68 "Documentation":
69 {
70 "Description": "A Component Fault",
71 "Message": "Comp %1 failed %2 times over %3 secs with ErrorCode %4",
72 "MessageArgSources":
73 [
74 "SRCWord6", "SRCWord7", "SRCWord8", "SRCWord9"
75 ]
76 }
77 }
78]
79}
80)";
81
82class SRCTest : public ::testing::Test
83{
84 protected:
85 static void SetUpTestCase()
86 {
87 char path[] = "/tmp/srctestXXXXXX";
88 regDir = mkdtemp(path);
89 }
90
91 static void TearDownTestCase()
92 {
93 fs::remove_all(regDir);
94 }
95
96 static std::string writeData(const char* data)
97 {
98 fs::path path = regDir / "registry.json";
99 std::ofstream stream{path};
100 stream << data;
101 return path;
102 }
103
104 static fs::path regDir;
105};
106
107fs::path SRCTest::regDir{};
108
109TEST_F(SRCTest, UnflattenFlattenTestNoCallouts)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500110{
Matt Spinler42828bd2019-10-11 10:39:30 -0500111 auto data = pelDataFactory(TestPELType::primarySRCSection);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500112
113 Stream stream{data};
114 SRC src{stream};
115
116 EXPECT_TRUE(src.valid());
117
118 EXPECT_EQ(src.header().id, 0x5053);
Matt Spinlerf1b46ff2020-01-22 14:10:04 -0600119 EXPECT_EQ(src.header().size, 0x50);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500120 EXPECT_EQ(src.header().version, 0x01);
121 EXPECT_EQ(src.header().subType, 0x01);
122 EXPECT_EQ(src.header().componentID, 0x0202);
123
124 EXPECT_EQ(src.version(), 0x02);
125 EXPECT_EQ(src.flags(), 0x00);
126 EXPECT_EQ(src.hexWordCount(), 9);
127 EXPECT_EQ(src.size(), 0x48);
128
129 const auto& hexwords = src.hexwordData();
Matt Spinlerbd716f02019-10-15 10:54:11 -0500130 EXPECT_EQ(0x02020255, hexwords[0]);
131 EXPECT_EQ(0x03030310, hexwords[1]);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500132 EXPECT_EQ(0x04040404, hexwords[2]);
133 EXPECT_EQ(0x05050505, hexwords[3]);
134 EXPECT_EQ(0x06060606, hexwords[4]);
135 EXPECT_EQ(0x07070707, hexwords[5]);
136 EXPECT_EQ(0x08080808, hexwords[6]);
137 EXPECT_EQ(0x09090909, hexwords[7]);
138
139 EXPECT_EQ(src.asciiString(), "BD8D5678 ");
140 EXPECT_FALSE(src.callouts());
141
142 // Flatten
143 std::vector<uint8_t> newData;
144 Stream newStream{newData};
145
146 src.flatten(newStream);
147 EXPECT_EQ(data, newData);
148}
149
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800150TEST_F(SRCTest, UnflattenFlattenTest2Callouts)
Matt Spinlerf9bae182019-10-09 13:37:38 -0500151{
Matt Spinler42828bd2019-10-11 10:39:30 -0500152 auto data = pelDataFactory(TestPELType::primarySRCSection2Callouts);
Matt Spinlerf9bae182019-10-09 13:37:38 -0500153
154 Stream stream{data};
155 SRC src{stream};
156
157 EXPECT_TRUE(src.valid());
Matt Spinlerbd716f02019-10-15 10:54:11 -0500158 EXPECT_EQ(src.flags(), 0x01); // Additional sections within the SRC.
Matt Spinlerf9bae182019-10-09 13:37:38 -0500159
160 // Spot check the SRC fields, but they're the same as above
161 EXPECT_EQ(src.asciiString(), "BD8D5678 ");
162
163 // There should be 2 callouts
164 const auto& calloutsSection = src.callouts();
165 ASSERT_TRUE(calloutsSection);
166 const auto& callouts = calloutsSection->callouts();
167 EXPECT_EQ(callouts.size(), 2);
168
169 // spot check that each callout has the right substructures
170 EXPECT_TRUE(callouts.front()->fruIdentity());
171 EXPECT_FALSE(callouts.front()->pceIdentity());
172 EXPECT_FALSE(callouts.front()->mru());
173
174 EXPECT_TRUE(callouts.back()->fruIdentity());
175 EXPECT_TRUE(callouts.back()->pceIdentity());
176 EXPECT_TRUE(callouts.back()->mru());
177
178 // Flatten
179 std::vector<uint8_t> newData;
180 Stream newStream{newData};
181
182 src.flatten(newStream);
183 EXPECT_EQ(data, newData);
184}
Matt Spinlerbd716f02019-10-15 10:54:11 -0500185
186// Create an SRC from the message registry
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800187TEST_F(SRCTest, CreateTestNoCallouts)
Matt Spinlerbd716f02019-10-15 10:54:11 -0500188{
189 message::Entry entry;
190 entry.src.type = 0xBD;
191 entry.src.reasonCode = 0xABCD;
192 entry.subsystem = 0x42;
Harisuddin Mohamed Isa1a1b0df2020-11-23 16:34:36 +0800193 entry.src.hexwordADFields = {
194 {5, {"TEST1", "DESCR1"}}, // Not a user defined word
195 {6, {"TEST1", "DESCR1"}},
196 {7, {"TEST2", "DESCR2"}},
197 {8, {"TEST3", "DESCR3"}},
198 {9, {"TEST4", "DESCR4"}}};
Matt Spinlerbd716f02019-10-15 10:54:11 -0500199
200 // Values for the SRC words pointed to above
201 std::vector<std::string> adData{"TEST1=0x12345678", "TEST2=12345678",
202 "TEST3=0XDEF", "TEST4=Z"};
203 AdditionalData ad{adData};
Matt Spinler075e5ba2020-02-21 15:46:00 -0600204 NiceMock<MockDataInterface> dataIface;
205
206 EXPECT_CALL(dataIface, getMotherboardCCIN).WillOnce(Return("ABCD"));
207
Sumit Kumar9d43a722021-08-24 09:46:19 -0500208 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
209 "system/entry"};
210 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
211 .WillOnce(Return(std::vector<bool>{false, false, false}));
212
Matt Spinler075e5ba2020-02-21 15:46:00 -0600213 SRC src{entry, ad, dataIface};
Matt Spinlerbd716f02019-10-15 10:54:11 -0500214
215 EXPECT_TRUE(src.valid());
Mike Cappsa2d7b772022-03-07 15:47:48 -0500216 EXPECT_FALSE(src.isPowerFaultEvent());
Matt Spinlerbd716f02019-10-15 10:54:11 -0500217 EXPECT_EQ(src.size(), baseSRCSize);
218
219 const auto& hexwords = src.hexwordData();
220
221 // The spec always refers to SRC words 2 - 9, and as the hexwordData()
222 // array index starts at 0 use the math in the [] below to make it easier
223 // to tell what is being accessed.
224 EXPECT_EQ(hexwords[2 - 2] & 0xF0000000, 0); // Partition dump status
225 EXPECT_EQ(hexwords[2 - 2] & 0x00F00000, 0); // Partition boot type
226 EXPECT_EQ(hexwords[2 - 2] & 0x000000FF, 0x55); // SRC format
227 EXPECT_EQ(hexwords[3 - 2] & 0x000000FF, 0x10); // BMC position
Matt Spinler075e5ba2020-02-21 15:46:00 -0600228 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0xABCD0000); // Motherboard CCIN
Matt Spinlerbd716f02019-10-15 10:54:11 -0500229
230 // Validate more fields here as the code starts filling them in.
231
232 // Ensure hex word 5 wasn't allowed to be set to TEST1's contents
Matt Spinler3fe93e92023-04-14 14:06:59 -0500233 // And that none of the error status flags are set
Matt Spinlerbd716f02019-10-15 10:54:11 -0500234 EXPECT_EQ(hexwords[5 - 2], 0);
235
236 // The user defined hex word fields specifed in the additional data.
237 EXPECT_EQ(hexwords[6 - 2], 0x12345678); // TEST1
238 EXPECT_EQ(hexwords[7 - 2], 12345678); // TEST2
239 EXPECT_EQ(hexwords[8 - 2], 0xdef); // TEST3
240 EXPECT_EQ(hexwords[9 - 2], 0); // TEST4, but can't convert a 'Z'
241
242 EXPECT_EQ(src.asciiString(), "BD42ABCD ");
243
244 // No callouts
245 EXPECT_FALSE(src.callouts());
246
247 // May as well spot check the flatten/unflatten
248 std::vector<uint8_t> data;
249 Stream stream{data};
250 src.flatten(stream);
251
252 stream.offset(0);
253 SRC newSRC{stream};
254
255 EXPECT_TRUE(newSRC.valid());
Matt Spinlerbd716f02019-10-15 10:54:11 -0500256 EXPECT_EQ(newSRC.asciiString(), src.asciiString());
257 EXPECT_FALSE(newSRC.callouts());
258}
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800259
Matt Spinler075e5ba2020-02-21 15:46:00 -0600260// Test when the CCIN string isn't a 4 character number
261TEST_F(SRCTest, BadCCINTest)
262{
263 message::Entry entry;
264 entry.src.type = 0xBD;
265 entry.src.reasonCode = 0xABCD;
266 entry.subsystem = 0x42;
Matt Spinler075e5ba2020-02-21 15:46:00 -0600267
268 std::vector<std::string> adData{};
269 AdditionalData ad{adData};
270 NiceMock<MockDataInterface> dataIface;
271
Sumit Kumar9d43a722021-08-24 09:46:19 -0500272 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
273 "system/entry"};
274 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
275 .WillRepeatedly(Return(std::vector<bool>{false, false, false}));
276
Matt Spinler075e5ba2020-02-21 15:46:00 -0600277 // First it isn't a number, then it is too long,
278 // then it is empty.
279 EXPECT_CALL(dataIface, getMotherboardCCIN)
280 .WillOnce(Return("X"))
281 .WillOnce(Return("12345"))
282 .WillOnce(Return(""));
283
284 // The CCIN in the first half should still be 0 each time.
285 {
286 SRC src{entry, ad, dataIface};
287 EXPECT_TRUE(src.valid());
288 const auto& hexwords = src.hexwordData();
289 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
290 }
291
292 {
293 SRC src{entry, ad, dataIface};
294 EXPECT_TRUE(src.valid());
295 const auto& hexwords = src.hexwordData();
296 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
297 }
298
299 {
300 SRC src{entry, ad, dataIface};
301 EXPECT_TRUE(src.valid());
302 const auto& hexwords = src.hexwordData();
303 EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
304 }
305}
306
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800307// Test the getErrorDetails function
308TEST_F(SRCTest, MessageSubstitutionTest)
309{
310 auto path = SRCTest::writeData(testRegistry);
311 message::Registry registry{path};
312 auto entry = registry.lookup("0xABCD", message::LookupType::reasonCode);
313
314 std::vector<std::string> adData{"COMPID=0x1", "FREQUENCY=0x4",
315 "DURATION=30", "ERRORCODE=0x01ABCDEF"};
316 AdditionalData ad{adData};
Matt Spinler075e5ba2020-02-21 15:46:00 -0600317 NiceMock<MockDataInterface> dataIface;
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800318
Sumit Kumar9d43a722021-08-24 09:46:19 -0500319 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
320 "system/entry"};
321 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
322 .WillOnce(Return(std::vector<bool>{false, false, false}));
323
Matt Spinler075e5ba2020-02-21 15:46:00 -0600324 SRC src{*entry, ad, dataIface};
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800325 EXPECT_TRUE(src.valid());
326
327 auto errorDetails = src.getErrorDetails(registry, DetailLevel::message);
328 ASSERT_TRUE(errorDetails);
Zane Shelley39936e32021-11-13 16:19:34 -0600329 EXPECT_EQ(errorDetails.value(),
330 "Comp 0x00000001 failed 0x00000004 times over 0x0000001E secs "
331 "with ErrorCode 0x01ABCDEF");
Harisuddin Mohamed Isa6fd0c1e2020-02-06 14:25:57 +0800332}
Matt Spinlered046852020-03-13 13:58:15 -0500333// Test that an inventory path callout string is
334// converted into the appropriate FRU callout.
335TEST_F(SRCTest, InventoryCalloutTest)
336{
337 message::Entry entry;
338 entry.src.type = 0xBD;
339 entry.src.reasonCode = 0xABCD;
340 entry.subsystem = 0x42;
Matt Spinlered046852020-03-13 13:58:15 -0500341
342 std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
343 AdditionalData ad{adData};
344 NiceMock<MockDataInterface> dataIface;
345
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500346 EXPECT_CALL(dataIface, getLocationCode("motherboard"))
347 .WillOnce(Return("UTMS-P1"));
348
349 EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
Matt Spinlered046852020-03-13 13:58:15 -0500350 .Times(1)
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500351 .WillOnce(DoAll(SetArgReferee<1>("1234567"), SetArgReferee<2>("CCCC"),
352 SetArgReferee<3>("123456789ABC")));
Matt Spinlered046852020-03-13 13:58:15 -0500353
Sumit Kumar9d43a722021-08-24 09:46:19 -0500354 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
355 "system/entry"};
356 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
357 .WillOnce(Return(std::vector<bool>{false, false, false}));
358
Matt Spinlered046852020-03-13 13:58:15 -0500359 SRC src{entry, ad, dataIface};
360 EXPECT_TRUE(src.valid());
361
362 ASSERT_TRUE(src.callouts());
363
364 EXPECT_EQ(src.callouts()->callouts().size(), 1);
365
366 auto& callout = src.callouts()->callouts().front();
367
368 EXPECT_EQ(callout->locationCode(), "UTMS-P1");
Matt Spinler717de422020-06-04 13:10:14 -0500369 EXPECT_EQ(callout->priority(), 'H');
Matt Spinlered046852020-03-13 13:58:15 -0500370
371 auto& fru = callout->fruIdentity();
372
373 EXPECT_EQ(fru->getPN().value(), "1234567");
374 EXPECT_EQ(fru->getCCIN().value(), "CCCC");
375 EXPECT_EQ(fru->getSN().value(), "123456789ABC");
376
377 // flatten and unflatten
378 std::vector<uint8_t> data;
379 Stream stream{data};
380 src.flatten(stream);
381
382 stream.offset(0);
383 SRC newSRC{stream};
384 EXPECT_TRUE(newSRC.valid());
385 ASSERT_TRUE(src.callouts());
386 EXPECT_EQ(src.callouts()->callouts().size(), 1);
387}
388
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500389// Test that when the location code can't be obtained that
Matt Spinler479b6922021-08-17 16:34:59 -0500390// no callout is added.
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500391TEST_F(SRCTest, InventoryCalloutNoLocCodeTest)
392{
393 message::Entry entry;
394 entry.src.type = 0xBD;
395 entry.src.reasonCode = 0xABCD;
396 entry.subsystem = 0x42;
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500397
398 std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
399 AdditionalData ad{adData};
400 NiceMock<MockDataInterface> dataIface;
401
402 auto func = []() {
403 throw sdbusplus::exception::SdBusError(5, "Error");
404 return std::string{};
405 };
406
407 EXPECT_CALL(dataIface, getLocationCode("motherboard"))
408 .Times(1)
409 .WillOnce(InvokeWithoutArgs(func));
410
Sumit Kumar9d43a722021-08-24 09:46:19 -0500411 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
412 "system/entry"};
413 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
414 .WillOnce(Return(std::vector<bool>{false, false, false}));
415
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500416 EXPECT_CALL(dataIface, getHWCalloutFields(_, _, _, _)).Times(0);
417
418 SRC src{entry, ad, dataIface};
419 EXPECT_TRUE(src.valid());
420
Matt Spinler479b6922021-08-17 16:34:59 -0500421 ASSERT_FALSE(src.callouts());
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500422
423 // flatten and unflatten
424 std::vector<uint8_t> data;
425 Stream stream{data};
426 src.flatten(stream);
427
428 stream.offset(0);
429 SRC newSRC{stream};
430 EXPECT_TRUE(newSRC.valid());
Matt Spinler479b6922021-08-17 16:34:59 -0500431 ASSERT_FALSE(src.callouts());
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500432}
433
434// Test that when the VPD can't be obtained that
435// a callout is still created.
Matt Spinlered046852020-03-13 13:58:15 -0500436TEST_F(SRCTest, InventoryCalloutNoVPDTest)
437{
438 message::Entry entry;
439 entry.src.type = 0xBD;
440 entry.src.reasonCode = 0xABCD;
441 entry.subsystem = 0x42;
Matt Spinlered046852020-03-13 13:58:15 -0500442
443 std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
444 AdditionalData ad{adData};
445 NiceMock<MockDataInterface> dataIface;
446
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500447 EXPECT_CALL(dataIface, getLocationCode("motherboard"))
448 .Times(1)
449 .WillOnce(Return("UTMS-P10"));
450
Matt Spinlered046852020-03-13 13:58:15 -0500451 auto func = []() { throw sdbusplus::exception::SdBusError(5, "Error"); };
452
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500453 EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
Matt Spinlered046852020-03-13 13:58:15 -0500454 .Times(1)
455 .WillOnce(InvokeWithoutArgs(func));
456
Sumit Kumar9d43a722021-08-24 09:46:19 -0500457 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
458 "system/entry"};
459 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
460 .WillOnce(Return(std::vector<bool>{false, false, false}));
461
Matt Spinlered046852020-03-13 13:58:15 -0500462 SRC src{entry, ad, dataIface};
463 EXPECT_TRUE(src.valid());
Matt Spinlered046852020-03-13 13:58:15 -0500464 ASSERT_TRUE(src.callouts());
Matt Spinlered046852020-03-13 13:58:15 -0500465 EXPECT_EQ(src.callouts()->callouts().size(), 1);
466
467 auto& callout = src.callouts()->callouts().front();
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500468 EXPECT_EQ(callout->locationCode(), "UTMS-P10");
Matt Spinler717de422020-06-04 13:10:14 -0500469 EXPECT_EQ(callout->priority(), 'H');
Matt Spinlered046852020-03-13 13:58:15 -0500470
471 auto& fru = callout->fruIdentity();
472
Matt Spinler9b90e2a2020-04-14 10:59:04 -0500473 EXPECT_EQ(fru->getPN(), "");
474 EXPECT_EQ(fru->getCCIN(), "");
475 EXPECT_EQ(fru->getSN(), "");
476 EXPECT_FALSE(fru->getMaintProc());
477
Matt Spinlered046852020-03-13 13:58:15 -0500478 // flatten and unflatten
479 std::vector<uint8_t> data;
480 Stream stream{data};
481 src.flatten(stream);
482
483 stream.offset(0);
484 SRC newSRC{stream};
485 EXPECT_TRUE(newSRC.valid());
486 ASSERT_TRUE(src.callouts());
487 EXPECT_EQ(src.callouts()->callouts().size(), 1);
488}
Matt Spinler03984582020-04-09 13:17:58 -0500489
490TEST_F(SRCTest, RegistryCalloutTest)
491{
492 message::Entry entry;
493 entry.src.type = 0xBD;
494 entry.src.reasonCode = 0xABCD;
Matt Spinler3fe93e92023-04-14 14:06:59 -0500495 entry.src.deconfigFlag = true;
Matt Spinler03984582020-04-09 13:17:58 -0500496 entry.subsystem = 0x42;
Matt Spinler03984582020-04-09 13:17:58 -0500497
498 entry.callouts = R"(
499 [
500 {
501 "System": "systemA",
502 "CalloutList":
503 [
504 {
505 "Priority": "high",
506 "SymbolicFRU": "service_docs"
507 },
508 {
509 "Priority": "medium",
Matt Spinler479b6922021-08-17 16:34:59 -0500510 "Procedure": "bmc_code"
Matt Spinler03984582020-04-09 13:17:58 -0500511 }
512 ]
513 },
514 {
515 "System": "systemB",
516 "CalloutList":
517 [
518 {
519 "Priority": "high",
520 "LocCode": "P0-C8",
521 "SymbolicFRUTrusted": "service_docs"
522 },
523 {
524 "Priority": "medium",
525 "SymbolicFRUTrusted": "service_docs"
526 }
527 ]
Matt Spinleraf191c72020-06-04 11:35:13 -0500528 },
529 {
530 "System": "systemC",
531 "CalloutList":
532 [
533 {
534 "Priority": "high",
535 "LocCode": "P0-C8"
536 },
537 {
538 "Priority": "medium",
539 "LocCode": "P0-C9"
540 }
541 ]
Matt Spinler03984582020-04-09 13:17:58 -0500542 }
543 ])"_json;
544
545 {
546 // Call out a symbolic FRU and a procedure
547 AdditionalData ad;
548 NiceMock<MockDataInterface> dataIface;
Matt Spinler6ea4d5f2020-05-20 13:31:07 -0500549 std::vector<std::string> names{"systemA"};
550
Matt Spinler1ab66962020-10-29 13:21:44 -0500551 EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
Matt Spinler03984582020-04-09 13:17:58 -0500552
Sumit Kumar9d43a722021-08-24 09:46:19 -0500553 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
554 "system/entry"};
555 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
556 .WillOnce(Return(std::vector<bool>{false, false, false}));
557
Matt Spinler03984582020-04-09 13:17:58 -0500558 SRC src{entry, ad, dataIface};
559
Matt Spinler3fe93e92023-04-14 14:06:59 -0500560 const auto& hexwords = src.hexwordData();
561 auto mask = static_cast<uint32_t>(SRC::ErrorStatusFlags::deconfigured);
562 EXPECT_EQ(hexwords[5 - 2] & mask, mask);
563
Matt Spinler03984582020-04-09 13:17:58 -0500564 auto& callouts = src.callouts()->callouts();
565 ASSERT_EQ(callouts.size(), 2);
566
567 EXPECT_EQ(callouts[0]->locationCodeSize(), 0);
568 EXPECT_EQ(callouts[0]->priority(), 'H');
569
570 EXPECT_EQ(callouts[1]->locationCodeSize(), 0);
571 EXPECT_EQ(callouts[1]->priority(), 'M');
572
573 auto& fru1 = callouts[0]->fruIdentity();
574 EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
575 EXPECT_EQ(fru1->failingComponentType(), src::FRUIdentity::symbolicFRU);
576 EXPECT_FALSE(fru1->getMaintProc());
577 EXPECT_FALSE(fru1->getSN());
578 EXPECT_FALSE(fru1->getCCIN());
579
580 auto& fru2 = callouts[1]->fruIdentity();
Matt Spinlerea2873d2021-08-18 10:35:40 -0500581 EXPECT_EQ(fru2->getMaintProc().value(), "BMC0001");
Matt Spinler03984582020-04-09 13:17:58 -0500582 EXPECT_EQ(fru2->failingComponentType(),
583 src::FRUIdentity::maintenanceProc);
584 EXPECT_FALSE(fru2->getPN());
585 EXPECT_FALSE(fru2->getSN());
586 EXPECT_FALSE(fru2->getCCIN());
587 }
588
589 {
590 // Call out a trusted symbolic FRU with a location code, and
591 // another one without.
592 AdditionalData ad;
593 NiceMock<MockDataInterface> dataIface;
Matt Spinler6ea4d5f2020-05-20 13:31:07 -0500594 std::vector<std::string> names{"systemB"};
595
Matt Spinleraf191c72020-06-04 11:35:13 -0500596 EXPECT_CALL(dataIface, expandLocationCode).WillOnce(Return("P0-C8"));
Matt Spinler1ab66962020-10-29 13:21:44 -0500597 EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
Matt Spinler03984582020-04-09 13:17:58 -0500598
Sumit Kumar9d43a722021-08-24 09:46:19 -0500599 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
600 "system/entry"};
601 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
602 .WillOnce(Return(std::vector<bool>{false, false, false}));
603
Matt Spinler03984582020-04-09 13:17:58 -0500604 SRC src{entry, ad, dataIface};
605
606 auto& callouts = src.callouts()->callouts();
607 EXPECT_EQ(callouts.size(), 2);
608
609 EXPECT_EQ(callouts[0]->locationCode(), "P0-C8");
610 EXPECT_EQ(callouts[0]->priority(), 'H');
611
612 EXPECT_EQ(callouts[1]->locationCodeSize(), 0);
613 EXPECT_EQ(callouts[1]->priority(), 'M');
614
615 auto& fru1 = callouts[0]->fruIdentity();
616 EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
617 EXPECT_EQ(fru1->failingComponentType(),
618 src::FRUIdentity::symbolicFRUTrustedLocCode);
619 EXPECT_FALSE(fru1->getMaintProc());
620 EXPECT_FALSE(fru1->getSN());
621 EXPECT_FALSE(fru1->getCCIN());
622
623 // It asked for a trusted symbolic FRU, but no location code
624 // was provided so it is switched back to a normal one
625 auto& fru2 = callouts[1]->fruIdentity();
626 EXPECT_EQ(fru2->getPN().value(), "SVCDOCS");
627 EXPECT_EQ(fru2->failingComponentType(), src::FRUIdentity::symbolicFRU);
628 EXPECT_FALSE(fru2->getMaintProc());
629 EXPECT_FALSE(fru2->getSN());
630 EXPECT_FALSE(fru2->getCCIN());
631 }
Matt Spinleraf191c72020-06-04 11:35:13 -0500632
633 {
634 // Two hardware callouts
635 AdditionalData ad;
636 NiceMock<MockDataInterface> dataIface;
637 std::vector<std::string> names{"systemC"};
638
Sumit Kumar9d43a722021-08-24 09:46:19 -0500639 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
640 "system/entry"};
641 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
642 .WillOnce(Return(std::vector<bool>{false, false, false}));
643
Matt Spinler1ab66962020-10-29 13:21:44 -0500644 EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
Matt Spinleraf191c72020-06-04 11:35:13 -0500645
646 EXPECT_CALL(dataIface, expandLocationCode("P0-C8", 0))
647 .WillOnce(Return("UXXX-P0-C8"));
648
649 EXPECT_CALL(dataIface, expandLocationCode("P0-C9", 0))
650 .WillOnce(Return("UXXX-P0-C9"));
651
Matt Spinler2f9225a2020-08-05 12:58:49 -0500652 EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C8", 0, false))
Matt Spinlerbad056b2023-01-25 14:16:57 -0600653 .WillOnce(Return(std::vector<std::string>{
654 "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0"}));
Matt Spinleraf191c72020-06-04 11:35:13 -0500655
Matt Spinler2f9225a2020-08-05 12:58:49 -0500656 EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C9", 0, false))
Matt Spinlerbad056b2023-01-25 14:16:57 -0600657 .WillOnce(Return(std::vector<std::string>{
658 "/xyz/openbmc_project/inventory/chassis/motherboard/cpu1"}));
Matt Spinleraf191c72020-06-04 11:35:13 -0500659
660 EXPECT_CALL(
661 dataIface,
662 getHWCalloutFields(
663 "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0", _, _,
664 _))
665 .Times(1)
666 .WillOnce(DoAll(SetArgReferee<1>("1234567"),
667 SetArgReferee<2>("CCCC"),
668 SetArgReferee<3>("123456789ABC")));
669
670 EXPECT_CALL(
671 dataIface,
672 getHWCalloutFields(
673 "/xyz/openbmc_project/inventory/chassis/motherboard/cpu1", _, _,
674 _))
675 .Times(1)
676 .WillOnce(DoAll(SetArgReferee<1>("2345678"),
677 SetArgReferee<2>("DDDD"),
678 SetArgReferee<3>("23456789ABCD")));
679
680 SRC src{entry, ad, dataIface};
681
682 auto& callouts = src.callouts()->callouts();
683 EXPECT_EQ(callouts.size(), 2);
684
685 EXPECT_EQ(callouts[0]->locationCode(), "UXXX-P0-C8");
686 EXPECT_EQ(callouts[0]->priority(), 'H');
687
688 auto& fru1 = callouts[0]->fruIdentity();
689 EXPECT_EQ(fru1->getPN().value(), "1234567");
690 EXPECT_EQ(fru1->getCCIN().value(), "CCCC");
691 EXPECT_EQ(fru1->getSN().value(), "123456789ABC");
692
693 EXPECT_EQ(callouts[1]->locationCode(), "UXXX-P0-C9");
694 EXPECT_EQ(callouts[1]->priority(), 'M');
695
696 auto& fru2 = callouts[1]->fruIdentity();
697 EXPECT_EQ(fru2->getPN().value(), "2345678");
698 EXPECT_EQ(fru2->getCCIN().value(), "DDDD");
699 EXPECT_EQ(fru2->getSN().value(), "23456789ABCD");
700 }
Matt Spinler03984582020-04-09 13:17:58 -0500701}
Matt Spinler717de422020-06-04 13:10:14 -0500702
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500703// Test that a symbolic FRU with a trusted location code callout
704// from the registry can get its location from the
705// CALLOUT_INVENTORY_PATH AdditionalData entry.
706TEST_F(SRCTest, SymbolicFRUWithInvPathTest)
707{
708 message::Entry entry;
709 entry.src.type = 0xBD;
710 entry.src.reasonCode = 0xABCD;
711 entry.subsystem = 0x42;
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500712
713 entry.callouts = R"(
714 [{
715 "CalloutList":
716 [
717 {
718 "Priority": "high",
719 "SymbolicFRUTrusted": "service_docs",
720 "UseInventoryLocCode": true
721 },
722 {
723 "Priority": "medium",
724 "LocCode": "P0-C8",
725 "SymbolicFRUTrusted": "pwrsply"
726 }
727 ]
728 }])"_json;
729
730 {
731 // The location code for the first symbolic FRU callout will
732 // come from this inventory path since UseInventoryLocCode is set.
733 // In this case there will be no normal FRU callout for the motherboard.
734 std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
735 AdditionalData ad{adData};
736 NiceMock<MockDataInterface> dataIface;
737 std::vector<std::string> names{"systemA"};
738
Sumit Kumar9d43a722021-08-24 09:46:19 -0500739 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
740 "system/entry"};
741 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
742 .WillOnce(Return(std::vector<bool>{false, false, false}));
743
Matt Spinler1ab66962020-10-29 13:21:44 -0500744 EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500745
746 EXPECT_CALL(dataIface, getLocationCode("motherboard"))
747 .Times(1)
748 .WillOnce(Return("Ufcs-P10"));
749
750 EXPECT_CALL(dataIface, expandLocationCode("P0-C8", 0))
751 .WillOnce(Return("Ufcs-P0-C8"));
752
753 SRC src{entry, ad, dataIface};
754
755 auto& callouts = src.callouts()->callouts();
756 EXPECT_EQ(callouts.size(), 2);
757
758 // The location code for the first symbolic FRU callout with a
759 // trusted location code comes from the motherboard.
760 EXPECT_EQ(callouts[0]->locationCode(), "Ufcs-P10");
761 EXPECT_EQ(callouts[0]->priority(), 'H');
762 auto& fru1 = callouts[0]->fruIdentity();
763 EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
764 EXPECT_EQ(fru1->failingComponentType(),
765 src::FRUIdentity::symbolicFRUTrustedLocCode);
766
767 // The second trusted symbolic FRU callouts uses the location
768 // code in the registry as usual.
769 EXPECT_EQ(callouts[1]->locationCode(), "Ufcs-P0-C8");
770 EXPECT_EQ(callouts[1]->priority(), 'M');
771 auto& fru2 = callouts[1]->fruIdentity();
772 EXPECT_EQ(fru2->getPN().value(), "PWRSPLY");
773 EXPECT_EQ(fru2->failingComponentType(),
774 src::FRUIdentity::symbolicFRUTrustedLocCode);
775 }
776
777 {
778 // This time say we want to use the location code from
779 // the inventory, but don't pass it in and the callout should
780 // end up a regular symbolic FRU
781 entry.callouts = R"(
782 [{
783 "CalloutList":
784 [
785 {
786 "Priority": "high",
787 "SymbolicFRUTrusted": "service_docs",
788 "UseInventoryLocCode": true
789 }
790 ]
791 }])"_json;
792
793 AdditionalData ad;
794 NiceMock<MockDataInterface> dataIface;
795 std::vector<std::string> names{"systemA"};
796
Sumit Kumar9d43a722021-08-24 09:46:19 -0500797 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
798 "system/entry"};
799 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
800 .WillOnce(Return(std::vector<bool>{false, false, false}));
801
Matt Spinler1ab66962020-10-29 13:21:44 -0500802 EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500803
804 SRC src{entry, ad, dataIface};
805
806 auto& callouts = src.callouts()->callouts();
807 EXPECT_EQ(callouts.size(), 1);
808
809 EXPECT_EQ(callouts[0]->locationCode(), "");
810 EXPECT_EQ(callouts[0]->priority(), 'H');
811 auto& fru1 = callouts[0]->fruIdentity();
812 EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
813 EXPECT_EQ(fru1->failingComponentType(), src::FRUIdentity::symbolicFRU);
814 }
815}
816
Matt Spinler717de422020-06-04 13:10:14 -0500817// Test looking up device path fails in the callout jSON.
818TEST_F(SRCTest, DevicePathCalloutTest)
819{
820 message::Entry entry;
821 entry.src.type = 0xBD;
822 entry.src.reasonCode = 0xABCD;
823 entry.subsystem = 0x42;
Matt Spinler717de422020-06-04 13:10:14 -0500824
825 const auto calloutJSON = R"(
826 {
827 "I2C":
828 {
829 "14":
830 {
831 "114":
832 {
833 "Callouts":[
834 {
835 "Name": "/chassis/motherboard/cpu0",
836 "LocationCode": "P1-C40",
837 "Priority": "H"
838 },
839 {
840 "Name": "/chassis/motherboard",
841 "LocationCode": "P1",
842 "Priority": "M"
843 },
844 {
845 "Name": "/chassis/motherboard/bmc",
846 "LocationCode": "P1-C15",
847 "Priority": "L"
848 }
849 ],
850 "Dest": "proc 0 target"
851 }
852 }
853 }
854 })";
855
856 auto dataPath = getPELReadOnlyDataPath();
857 std::ofstream file{dataPath / "systemA_dev_callouts.json"};
858 file << calloutJSON;
859 file.close();
860
861 NiceMock<MockDataInterface> dataIface;
862 std::vector<std::string> names{"systemA"};
863
Sumit Kumar9d43a722021-08-24 09:46:19 -0500864 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
865 "system/entry"};
866 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
867 .WillRepeatedly(Return(std::vector<bool>{false, false, false}));
868
Matt Spinler717de422020-06-04 13:10:14 -0500869 EXPECT_CALL(dataIface, getSystemNames)
870 .Times(5)
Matt Spinler1ab66962020-10-29 13:21:44 -0500871 .WillRepeatedly(Return(names));
Matt Spinler717de422020-06-04 13:10:14 -0500872
Matt Spinler2f9225a2020-08-05 12:58:49 -0500873 EXPECT_CALL(dataIface, getInventoryFromLocCode("P1-C40", 0, false))
Matt Spinler717de422020-06-04 13:10:14 -0500874 .Times(3)
Matt Spinlerbad056b2023-01-25 14:16:57 -0600875 .WillRepeatedly(Return(std::vector<std::string>{
876 "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0"}));
Matt Spinler717de422020-06-04 13:10:14 -0500877
Matt Spinler2f9225a2020-08-05 12:58:49 -0500878 EXPECT_CALL(dataIface, getInventoryFromLocCode("P1", 0, false))
Matt Spinler717de422020-06-04 13:10:14 -0500879 .Times(3)
Matt Spinlerbad056b2023-01-25 14:16:57 -0600880 .WillRepeatedly(Return(std::vector<std::string>{
881 "/xyz/openbmc_project/inventory/chassis/motherboard"}));
Matt Spinler717de422020-06-04 13:10:14 -0500882
Matt Spinler2f9225a2020-08-05 12:58:49 -0500883 EXPECT_CALL(dataIface, getInventoryFromLocCode("P1-C15", 0, false))
Matt Spinler717de422020-06-04 13:10:14 -0500884 .Times(3)
Matt Spinlerbad056b2023-01-25 14:16:57 -0600885 .WillRepeatedly(Return(std::vector<std::string>{
886 "/xyz/openbmc_project/inventory/chassis/motherboard/bmc"}));
Matt Spinler717de422020-06-04 13:10:14 -0500887
Matt Spinler0d92b522021-06-16 13:28:17 -0600888 EXPECT_CALL(dataIface, expandLocationCode("P1-C40", 0))
Matt Spinler717de422020-06-04 13:10:14 -0500889 .Times(3)
890 .WillRepeatedly(Return("Ufcs-P1-C40"));
Matt Spinler0d92b522021-06-16 13:28:17 -0600891
892 EXPECT_CALL(dataIface, expandLocationCode("P1", 0))
Matt Spinler717de422020-06-04 13:10:14 -0500893 .Times(3)
894 .WillRepeatedly(Return("Ufcs-P1"));
Matt Spinler0d92b522021-06-16 13:28:17 -0600895
896 EXPECT_CALL(dataIface, expandLocationCode("P1-C15", 0))
Matt Spinler717de422020-06-04 13:10:14 -0500897 .Times(3)
898 .WillRepeatedly(Return("Ufcs-P1-C15"));
899
900 EXPECT_CALL(
901 dataIface,
902 getHWCalloutFields(
903 "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0", _, _, _))
904 .Times(3)
905 .WillRepeatedly(DoAll(SetArgReferee<1>("1234567"),
906 SetArgReferee<2>("CCCC"),
907 SetArgReferee<3>("123456789ABC")));
908 EXPECT_CALL(
909 dataIface,
910 getHWCalloutFields("/xyz/openbmc_project/inventory/chassis/motherboard",
911 _, _, _))
912 .Times(3)
913 .WillRepeatedly(DoAll(SetArgReferee<1>("7654321"),
914 SetArgReferee<2>("MMMM"),
915 SetArgReferee<3>("CBA987654321")));
916 EXPECT_CALL(
917 dataIface,
918 getHWCalloutFields(
919 "/xyz/openbmc_project/inventory/chassis/motherboard/bmc", _, _, _))
920 .Times(3)
921 .WillRepeatedly(DoAll(SetArgReferee<1>("7123456"),
922 SetArgReferee<2>("BBBB"),
923 SetArgReferee<3>("C123456789AB")));
924
925 // Call this below with different AdditionalData values that
926 // result in the same callouts.
927 auto checkCallouts = [&entry, &dataIface](const auto& items) {
928 AdditionalData ad{items};
929 SRC src{entry, ad, dataIface};
930
931 ASSERT_TRUE(src.callouts());
932 auto& callouts = src.callouts()->callouts();
933
934 ASSERT_EQ(callouts.size(), 3);
935
936 {
937 EXPECT_EQ(callouts[0]->priority(), 'H');
938 EXPECT_EQ(callouts[0]->locationCode(), "Ufcs-P1-C40");
939
940 auto& fru = callouts[0]->fruIdentity();
941 EXPECT_EQ(fru->getPN().value(), "1234567");
942 EXPECT_EQ(fru->getCCIN().value(), "CCCC");
943 EXPECT_EQ(fru->getSN().value(), "123456789ABC");
944 }
945 {
946 EXPECT_EQ(callouts[1]->priority(), 'M');
947 EXPECT_EQ(callouts[1]->locationCode(), "Ufcs-P1");
948
949 auto& fru = callouts[1]->fruIdentity();
950 EXPECT_EQ(fru->getPN().value(), "7654321");
951 EXPECT_EQ(fru->getCCIN().value(), "MMMM");
952 EXPECT_EQ(fru->getSN().value(), "CBA987654321");
953 }
954 {
955 EXPECT_EQ(callouts[2]->priority(), 'L');
956 EXPECT_EQ(callouts[2]->locationCode(), "Ufcs-P1-C15");
957
958 auto& fru = callouts[2]->fruIdentity();
959 EXPECT_EQ(fru->getPN().value(), "7123456");
960 EXPECT_EQ(fru->getCCIN().value(), "BBBB");
961 EXPECT_EQ(fru->getSN().value(), "C123456789AB");
962 }
963 };
964
965 {
966 // Callouts based on the device path
967 std::vector<std::string> items{
968 "CALLOUT_ERRNO=5",
969 "CALLOUT_DEVICE_PATH=/sys/devices/platform/ahb/ahb:apb/"
970 "ahb:apb:bus@1e78a000/1e78a340.i2c-bus/i2c-14/14-0072"};
971
972 checkCallouts(items);
973 }
974
975 {
976 // Callouts based on the I2C bus and address
977 std::vector<std::string> items{"CALLOUT_ERRNO=5", "CALLOUT_IIC_BUS=14",
978 "CALLOUT_IIC_ADDR=0x72"};
979 checkCallouts(items);
980 }
981
982 {
983 // Also based on I2C bus and address, but with bus = /dev/i2c-14
984 std::vector<std::string> items{"CALLOUT_ERRNO=5", "CALLOUT_IIC_BUS=14",
985 "CALLOUT_IIC_ADDR=0x72"};
986 checkCallouts(items);
987 }
988
989 {
990 // Callout not found
991 std::vector<std::string> items{
992 "CALLOUT_ERRNO=5",
993 "CALLOUT_DEVICE_PATH=/sys/devices/platform/ahb/ahb:apb/"
994 "ahb:apb:bus@1e78a000/1e78a340.i2c-bus/i2c-24/24-0012"};
995
996 AdditionalData ad{items};
997 SRC src{entry, ad, dataIface};
998
999 EXPECT_FALSE(src.callouts());
1000 ASSERT_EQ(src.getDebugData().size(), 1);
1001 EXPECT_EQ(src.getDebugData()[0],
1002 "Problem looking up I2C callouts on 24 18: "
1003 "[json.exception.out_of_range.403] key '24' not found");
1004 }
1005
1006 {
1007 // Callout not found
1008 std::vector<std::string> items{"CALLOUT_ERRNO=5", "CALLOUT_IIC_BUS=22",
1009 "CALLOUT_IIC_ADDR=0x99"};
1010 AdditionalData ad{items};
1011 SRC src{entry, ad, dataIface};
1012
1013 EXPECT_FALSE(src.callouts());
1014 ASSERT_EQ(src.getDebugData().size(), 1);
1015 EXPECT_EQ(src.getDebugData()[0],
1016 "Problem looking up I2C callouts on 22 153: "
1017 "[json.exception.out_of_range.403] key '22' not found");
1018 }
1019
1020 fs::remove_all(dataPath);
1021}
Matt Spinler3bdd0112020-08-27 10:24:34 -05001022
1023// Test when callouts are passed in via JSON
1024TEST_F(SRCTest, JsonCalloutsTest)
1025{
1026 const auto jsonCallouts = R"(
1027 [
1028 {
1029 "LocationCode": "P0-C1",
1030 "Priority": "H",
1031 "MRUs": [
1032 {
1033 "ID": 42,
1034 "Priority": "H"
1035 },
1036 {
1037 "ID": 43,
1038 "Priority": "M"
1039 }
1040 ]
1041 },
1042 {
1043 "InventoryPath": "/inv/system/chassis/motherboard/cpu0",
1044 "Priority": "M",
1045 "Guarded": true,
1046 "Deconfigured": true
1047 },
1048 {
1049 "Procedure": "PROCEDU",
1050 "Priority": "A"
1051 },
1052 {
1053 "SymbolicFRU": "TRUSTED",
1054 "Priority": "B",
1055 "TrustedLocationCode": true,
1056 "LocationCode": "P1-C23"
1057 },
1058 {
1059 "SymbolicFRU": "FRUTST1",
1060 "Priority": "C",
1061 "LocationCode": "P1-C24"
1062 },
1063 {
1064 "SymbolicFRU": "FRUTST2LONG",
1065 "Priority": "L"
Matt Spinler3c7ec6d2022-05-06 08:50:20 -05001066 },
1067 {
1068 "Procedure": "fsi_path",
1069 "Priority": "L"
1070 },
1071 {
1072 "SymbolicFRU": "ambient_temp",
1073 "Priority": "L"
Matt Spinler3bdd0112020-08-27 10:24:34 -05001074 }
1075 ]
1076 )"_json;
1077
1078 message::Entry entry;
1079 entry.src.type = 0xBD;
1080 entry.src.reasonCode = 0xABCD;
1081 entry.subsystem = 0x42;
Matt Spinler3bdd0112020-08-27 10:24:34 -05001082
1083 AdditionalData ad;
1084 NiceMock<MockDataInterface> dataIface;
1085
Sumit Kumar9d43a722021-08-24 09:46:19 -05001086 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
1087 "system/entry"};
1088 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1089 .WillOnce(Return(std::vector<bool>{false, false, false}));
1090
Matt Spinler3bdd0112020-08-27 10:24:34 -05001091 // Callout 0 mock calls
1092 {
1093 EXPECT_CALL(dataIface, expandLocationCode("P0-C1", 0))
1094 .Times(1)
1095 .WillOnce(Return("UXXX-P0-C1"));
1096 EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C1", 0, false))
1097 .Times(1)
Matt Spinlerbad056b2023-01-25 14:16:57 -06001098 .WillOnce(Return(std::vector<std::string>{
1099 "/inv/system/chassis/motherboard/bmc"}));
Matt Spinler3bdd0112020-08-27 10:24:34 -05001100 EXPECT_CALL(
1101 dataIface,
1102 getHWCalloutFields("/inv/system/chassis/motherboard/bmc", _, _, _))
1103 .Times(1)
1104 .WillOnce(DoAll(SetArgReferee<1>("1234567"),
1105 SetArgReferee<2>("CCCC"),
1106 SetArgReferee<3>("123456789ABC")));
1107 }
1108 // Callout 1 mock calls
1109 {
1110 EXPECT_CALL(dataIface,
1111 getLocationCode("/inv/system/chassis/motherboard/cpu0"))
1112 .WillOnce(Return("UYYY-P5"));
1113 EXPECT_CALL(
1114 dataIface,
1115 getHWCalloutFields("/inv/system/chassis/motherboard/cpu0", _, _, _))
1116 .Times(1)
1117 .WillOnce(DoAll(SetArgReferee<1>("2345678"),
1118 SetArgReferee<2>("DDDD"),
1119 SetArgReferee<3>("23456789ABCD")));
1120 }
1121 // Callout 3 mock calls
1122 {
1123 EXPECT_CALL(dataIface, expandLocationCode("P1-C23", 0))
1124 .Times(1)
1125 .WillOnce(Return("UXXX-P1-C23"));
1126 }
1127 // Callout 4 mock calls
1128 {
1129 EXPECT_CALL(dataIface, expandLocationCode("P1-C24", 0))
1130 .Times(1)
1131 .WillOnce(Return("UXXX-P1-C24"));
1132 }
1133
1134 SRC src{entry, ad, jsonCallouts, dataIface};
1135 ASSERT_TRUE(src.callouts());
1136
Matt Spinlerafa2c792020-08-27 11:01:39 -05001137 // Check the guarded and deconfigured flags
1138 EXPECT_TRUE(src.hexwordData()[3] & 0x03000000);
1139
Matt Spinler3bdd0112020-08-27 10:24:34 -05001140 const auto& callouts = src.callouts()->callouts();
Matt Spinler3c7ec6d2022-05-06 08:50:20 -05001141 ASSERT_EQ(callouts.size(), 8);
Matt Spinler3bdd0112020-08-27 10:24:34 -05001142
1143 // Check callout 0
1144 {
1145 EXPECT_EQ(callouts[0]->priority(), 'H');
1146 EXPECT_EQ(callouts[0]->locationCode(), "UXXX-P0-C1");
1147
1148 auto& fru = callouts[0]->fruIdentity();
1149 EXPECT_EQ(fru->getPN().value(), "1234567");
1150 EXPECT_EQ(fru->getCCIN().value(), "CCCC");
1151 EXPECT_EQ(fru->getSN().value(), "123456789ABC");
1152 EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::hardwareFRU);
Matt Spinlerb8cb60f2020-08-27 10:55:55 -05001153
1154 auto& mruCallouts = callouts[0]->mru();
1155 ASSERT_TRUE(mruCallouts);
1156 auto& mrus = mruCallouts->mrus();
1157 ASSERT_EQ(mrus.size(), 2);
1158 EXPECT_EQ(mrus[0].id, 42);
1159 EXPECT_EQ(mrus[0].priority, 'H');
1160 EXPECT_EQ(mrus[1].id, 43);
1161 EXPECT_EQ(mrus[1].priority, 'M');
Matt Spinler3bdd0112020-08-27 10:24:34 -05001162 }
1163
1164 // Check callout 1
1165 {
1166 EXPECT_EQ(callouts[1]->priority(), 'M');
1167 EXPECT_EQ(callouts[1]->locationCode(), "UYYY-P5");
1168
1169 auto& fru = callouts[1]->fruIdentity();
1170 EXPECT_EQ(fru->getPN().value(), "2345678");
1171 EXPECT_EQ(fru->getCCIN().value(), "DDDD");
1172 EXPECT_EQ(fru->getSN().value(), "23456789ABCD");
1173 EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::hardwareFRU);
1174 }
1175
1176 // Check callout 2
1177 {
1178 EXPECT_EQ(callouts[2]->priority(), 'A');
1179 EXPECT_EQ(callouts[2]->locationCode(), "");
1180
1181 auto& fru = callouts[2]->fruIdentity();
1182 EXPECT_EQ(fru->getMaintProc().value(), "PROCEDU");
1183 EXPECT_EQ(fru->failingComponentType(),
1184 src::FRUIdentity::maintenanceProc);
1185 }
1186
1187 // Check callout 3
1188 {
1189 EXPECT_EQ(callouts[3]->priority(), 'B');
1190 EXPECT_EQ(callouts[3]->locationCode(), "UXXX-P1-C23");
1191
1192 auto& fru = callouts[3]->fruIdentity();
1193 EXPECT_EQ(fru->getPN().value(), "TRUSTED");
1194 EXPECT_EQ(fru->failingComponentType(),
1195 src::FRUIdentity::symbolicFRUTrustedLocCode);
1196 }
1197
1198 // Check callout 4
1199 {
1200 EXPECT_EQ(callouts[4]->priority(), 'C');
1201 EXPECT_EQ(callouts[4]->locationCode(), "UXXX-P1-C24");
1202
1203 auto& fru = callouts[4]->fruIdentity();
1204 EXPECT_EQ(fru->getPN().value(), "FRUTST1");
1205 EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::symbolicFRU);
1206 }
1207
1208 // Check callout 5
1209 {
1210 EXPECT_EQ(callouts[5]->priority(), 'L');
1211 EXPECT_EQ(callouts[5]->locationCode(), "");
1212
1213 auto& fru = callouts[5]->fruIdentity();
1214 EXPECT_EQ(fru->getPN().value(), "FRUTST2");
1215 EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::symbolicFRU);
1216 }
1217
Matt Spinler3c7ec6d2022-05-06 08:50:20 -05001218 // Check callout 6
1219 {
1220 EXPECT_EQ(callouts[6]->priority(), 'L');
1221 EXPECT_EQ(callouts[6]->locationCode(), "");
1222
1223 auto& fru = callouts[6]->fruIdentity();
1224 EXPECT_EQ(fru->getMaintProc().value(), "BMC0004");
1225 EXPECT_EQ(fru->failingComponentType(),
1226 src::FRUIdentity::maintenanceProc);
1227 }
1228
1229 // Check callout 7
1230 {
1231 EXPECT_EQ(callouts[7]->priority(), 'L');
1232 EXPECT_EQ(callouts[7]->locationCode(), "");
1233
1234 auto& fru = callouts[7]->fruIdentity();
1235 EXPECT_EQ(fru->getPN().value(), "AMBTEMP");
1236 EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::symbolicFRU);
1237 }
1238
Matt Spinler3bdd0112020-08-27 10:24:34 -05001239 // Check that it didn't find any errors
1240 const auto& data = src.getDebugData();
1241 EXPECT_TRUE(data.empty());
1242}
1243
1244TEST_F(SRCTest, JsonBadCalloutsTest)
1245{
1246 // The first call will have a Throw in a mock call.
1247 // The second will have a different Throw in a mock call.
1248 // The others have issues with the Priority field.
1249 const auto jsonCallouts = R"(
1250 [
1251 {
1252 "LocationCode": "P0-C1",
1253 "Priority": "H"
1254 },
1255 {
1256 "LocationCode": "P0-C2",
1257 "Priority": "H"
1258 },
1259 {
1260 "LocationCode": "P0-C3"
1261 },
1262 {
1263 "LocationCode": "P0-C4",
1264 "Priority": "X"
1265 }
1266 ]
1267 )"_json;
1268
1269 message::Entry entry;
1270 entry.src.type = 0xBD;
1271 entry.src.reasonCode = 0xABCD;
1272 entry.subsystem = 0x42;
Matt Spinler3bdd0112020-08-27 10:24:34 -05001273
1274 AdditionalData ad;
1275 NiceMock<MockDataInterface> dataIface;
1276
Sumit Kumar9d43a722021-08-24 09:46:19 -05001277 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
1278 "system/entry"};
1279 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1280 .WillRepeatedly(Return(std::vector<bool>{false, false, false}));
1281
Matt Spinler3bdd0112020-08-27 10:24:34 -05001282 // Callout 0 mock calls
1283 // Expand location code will fail, so the unexpanded location
1284 // code should show up in the callout instead.
1285 {
1286 EXPECT_CALL(dataIface, expandLocationCode("P0-C1", 0))
1287 .WillOnce(Throw(std::runtime_error("Fail")));
1288
1289 EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C1", 0, false))
1290 .Times(1)
Matt Spinlerbad056b2023-01-25 14:16:57 -06001291 .WillOnce(Return(std::vector<std::string>{
1292 "/inv/system/chassis/motherboard/bmc"}));
Matt Spinler3bdd0112020-08-27 10:24:34 -05001293 EXPECT_CALL(
1294 dataIface,
1295 getHWCalloutFields("/inv/system/chassis/motherboard/bmc", _, _, _))
1296 .Times(1)
1297 .WillOnce(DoAll(SetArgReferee<1>("1234567"),
1298 SetArgReferee<2>("CCCC"),
1299 SetArgReferee<3>("123456789ABC")));
1300 }
1301
1302 // Callout 1 mock calls
1303 // getInventoryFromLocCode will fail
1304 {
1305 EXPECT_CALL(dataIface, expandLocationCode("P0-C2", 0))
1306 .Times(1)
1307 .WillOnce(Return("UXXX-P0-C2"));
1308
1309 EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C2", 0, false))
1310 .Times(1)
1311 .WillOnce(Throw(std::runtime_error("Fail")));
1312 }
1313
1314 SRC src{entry, ad, jsonCallouts, dataIface};
1315
1316 ASSERT_TRUE(src.callouts());
1317
1318 const auto& callouts = src.callouts()->callouts();
1319
1320 // Only the first callout was successful
1321 ASSERT_EQ(callouts.size(), 1);
1322
1323 {
1324 EXPECT_EQ(callouts[0]->priority(), 'H');
1325 EXPECT_EQ(callouts[0]->locationCode(), "P0-C1");
1326
1327 auto& fru = callouts[0]->fruIdentity();
1328 EXPECT_EQ(fru->getPN().value(), "1234567");
1329 EXPECT_EQ(fru->getCCIN().value(), "CCCC");
1330 EXPECT_EQ(fru->getSN().value(), "123456789ABC");
1331 EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::hardwareFRU);
1332 }
1333
1334 const auto& data = src.getDebugData();
1335 ASSERT_EQ(data.size(), 4);
1336 EXPECT_STREQ(data[0].c_str(), "Unable to expand location code P0-C1: Fail");
1337 EXPECT_STREQ(data[1].c_str(),
1338 "Failed extracting callout data from JSON: Unable to "
1339 "get inventory path from location code: P0-C2: Fail");
1340 EXPECT_STREQ(data[2].c_str(),
1341 "Failed extracting callout data from JSON: "
1342 "[json.exception.out_of_range.403] key 'Priority' not found");
1343 EXPECT_STREQ(data[3].c_str(),
1344 "Failed extracting callout data from JSON: Invalid "
1345 "priority 'X' found in JSON callout");
1346}
Miguel Gomez53ef1552020-10-14 21:16:32 +00001347
1348// Test that an inventory path callout can have
1349// a different priority than H.
1350TEST_F(SRCTest, InventoryCalloutTestPriority)
1351{
1352 message::Entry entry;
1353 entry.src.type = 0xBD;
1354 entry.src.reasonCode = 0xABCD;
1355 entry.subsystem = 0x42;
Miguel Gomez53ef1552020-10-14 21:16:32 +00001356
1357 std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard",
1358 "CALLOUT_PRIORITY=M"};
1359 AdditionalData ad{adData};
1360 NiceMock<MockDataInterface> dataIface;
1361
Sumit Kumar9d43a722021-08-24 09:46:19 -05001362 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
1363 "system/entry"};
1364 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1365 .WillOnce(Return(std::vector<bool>{false, false, false}));
1366
Miguel Gomez53ef1552020-10-14 21:16:32 +00001367 EXPECT_CALL(dataIface, getLocationCode("motherboard"))
1368 .WillOnce(Return("UTMS-P1"));
1369
1370 EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
1371 .Times(1)
1372 .WillOnce(DoAll(SetArgReferee<1>("1234567"), SetArgReferee<2>("CCCC"),
1373 SetArgReferee<3>("123456789ABC")));
1374
1375 SRC src{entry, ad, dataIface};
1376 EXPECT_TRUE(src.valid());
1377
1378 ASSERT_TRUE(src.callouts());
1379
1380 EXPECT_EQ(src.callouts()->callouts().size(), 1);
1381
1382 auto& callout = src.callouts()->callouts().front();
1383
1384 EXPECT_EQ(callout->locationCode(), "UTMS-P1");
1385 EXPECT_EQ(callout->priority(), 'M');
Harisuddin Mohamed Isa1a1b0df2020-11-23 16:34:36 +08001386}
Sumit Kumar9d43a722021-08-24 09:46:19 -05001387
1388// Test for bmc & platform dump status bits
1389TEST_F(SRCTest, DumpStatusBitsCheck)
1390{
1391 message::Entry entry;
1392 entry.src.type = 0xBD;
1393 entry.src.reasonCode = 0xABCD;
1394 entry.subsystem = 0x42;
Sumit Kumar9d43a722021-08-24 09:46:19 -05001395
1396 AdditionalData ad;
1397 NiceMock<MockDataInterface> dataIface;
1398 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
1399 "system/entry"};
1400
1401 {
1402 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1403 .WillOnce(Return(std::vector<bool>{true, false, false}));
1404
1405 SRC src{entry, ad, dataIface};
1406 EXPECT_TRUE(src.valid());
1407
1408 const auto& hexwords = src.hexwordData();
1409 EXPECT_EQ(0x00080055, hexwords[0]);
1410 }
1411
1412 {
1413 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1414 .WillOnce(Return(std::vector<bool>{false, true, false}));
1415
1416 SRC src{entry, ad, dataIface};
1417 EXPECT_TRUE(src.valid());
1418
1419 const auto& hexwords = src.hexwordData();
1420 EXPECT_EQ(0x00000255, hexwords[0]);
1421 }
1422
1423 {
1424 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1425 .WillOnce(Return(std::vector<bool>{false, false, true}));
1426
1427 SRC src{entry, ad, dataIface};
1428 EXPECT_TRUE(src.valid());
1429
1430 const auto& hexwords = src.hexwordData();
1431 EXPECT_EQ(0x00000455, hexwords[0]);
1432 }
1433
1434 {
1435 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1436 .WillOnce(Return(std::vector<bool>{true, true, true}));
1437
1438 SRC src{entry, ad, dataIface};
1439 EXPECT_TRUE(src.valid());
1440
1441 const auto& hexwords = src.hexwordData();
1442 EXPECT_EQ(0x00080655, hexwords[0]);
1443 }
1444}
Sumit Kumar50bfa692022-01-06 06:48:26 -06001445
1446// Test SRC with additional data - PEL_SUBSYSTEM
1447TEST_F(SRCTest, TestPELSubsystem)
1448{
1449 message::Entry entry;
1450 entry.src.type = 0xBD;
1451 entry.src.reasonCode = 0xABCD;
1452 entry.subsystem = 0x42;
Sumit Kumar50bfa692022-01-06 06:48:26 -06001453
1454 // Values for the SRC words pointed to above
1455 std::vector<std::string> adData{"PEL_SUBSYSTEM=0x20"};
1456 AdditionalData ad{adData};
1457 NiceMock<MockDataInterface> dataIface;
1458
1459 EXPECT_CALL(dataIface, getMotherboardCCIN).WillOnce(Return("ABCD"));
1460
1461 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
1462 "system/entry"};
1463 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1464 .WillOnce(Return(std::vector<bool>{false, false, false}));
1465
1466 SRC src{entry, ad, dataIface};
1467
1468 EXPECT_TRUE(src.valid());
1469
1470 EXPECT_EQ(src.asciiString(), "BD20ABCD ");
1471}
Vijay Lobo875b6c72021-10-20 17:38:56 -05001472
1473void setAsciiString(std::vector<uint8_t>& src, const std::string& value)
1474{
1475 assert(40 + value.size() <= src.size());
1476
1477 for (size_t i = 0; i < value.size(); i++)
1478 {
1479 src[40 + i] = value[i];
1480 }
1481}
1482
1483TEST_F(SRCTest, TestGetProgressCode)
1484{
1485 {
1486 // A real SRC with CC009184
1487 std::vector<uint8_t> src{
1488 2, 8, 0, 9, 0, 0, 0, 72, 0, 0, 0, 224, 0, 0, 0,
1489 0, 204, 0, 145, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1490 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 48, 48, 57,
1491 49, 56, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1492 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
1493
1494 EXPECT_EQ(SRC::getProgressCode(src), 0xCC009184);
1495 }
1496
1497 {
1498 // A real SRC with STANDBY
1499 std::vector<uint8_t> src{
1500 2, 0, 0, 1, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0,
1501 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1502 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 84, 65, 78, 68,
1503 66, 89, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1504 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
1505
1506 EXPECT_EQ(SRC::getProgressCode(src), 0);
1507 }
1508
1509 {
1510 // A real SRC with CC009184, but 1 byte too short
1511 std::vector<uint8_t> src{
1512 2, 8, 0, 9, 0, 0, 0, 72, 0, 0, 0, 224, 0, 0, 0,
1513 0, 204, 0, 145, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 48, 48, 57,
1515 49, 56, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1516 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
1517 src.resize(71);
1518 EXPECT_EQ(SRC::getProgressCode(src), 0);
1519 }
1520
1521 {
1522 // A few different ones
1523 const std::map<std::string, uint32_t> progressCodes{
1524 {"12345678", 0x12345678}, {"ABCDEF00", 0xABCDEF00},
1525 {"abcdef00", 0xABCDEF00}, {"X1234567", 0},
1526 {"1234567X", 0}, {"1 ", 0}};
1527
1528 std::vector<uint8_t> src(72, 0x0);
1529
1530 for (const auto& [code, expected] : progressCodes)
1531 {
1532 setAsciiString(src, code);
1533 EXPECT_EQ(SRC::getProgressCode(src), expected);
1534 }
1535
1536 // empty
1537 src.clear();
1538 EXPECT_EQ(SRC::getProgressCode(src), 0);
1539 }
1540}
1541
1542// Test progress is in right SRC hex data field
1543TEST_F(SRCTest, TestProgressCodeField)
1544{
1545 message::Entry entry;
1546 entry.src.type = 0xBD;
1547 entry.src.reasonCode = 0xABCD;
1548 entry.subsystem = 0x42;
1549
1550 AdditionalData ad;
1551 NiceMock<MockDataInterface> dataIface;
1552 std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
1553 "system/entry"};
1554 EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
1555 .WillOnce(Return(std::vector<bool>{false, false, false}));
1556 EXPECT_CALL(dataIface, getRawProgressSRC())
1557 .WillOnce(Return(std::vector<uint8_t>{
1558 2, 8, 0, 9, 0, 0, 0, 72, 0, 0, 0, 224, 0, 0, 0,
1559 0, 204, 0, 145, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1560 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 48, 48, 57,
1561 49, 56, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1562 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}));
1563
1564 SRC src{entry, ad, dataIface};
1565 EXPECT_TRUE(src.valid());
1566
1567 // Verify that the hex vlue is set at the right hexword
1568 EXPECT_EQ(src.hexwordData()[2], 0xCC009184);
1569}