197f7abcfSMatt Spinler /**
297f7abcfSMatt Spinler * Copyright © 2019 IBM Corporation
397f7abcfSMatt Spinler *
497f7abcfSMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License");
597f7abcfSMatt Spinler * you may not use this file except in compliance with the License.
697f7abcfSMatt Spinler * You may obtain a copy of the License at
797f7abcfSMatt Spinler *
897f7abcfSMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0
997f7abcfSMatt Spinler *
1097f7abcfSMatt Spinler * Unless required by applicable law or agreed to in writing, software
1197f7abcfSMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS,
1297f7abcfSMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1397f7abcfSMatt Spinler * See the License for the specific language governing permissions and
1497f7abcfSMatt Spinler * limitations under the License.
1597f7abcfSMatt Spinler */
16f9bae185SMatt Spinler #include "extensions/openpower-pels/src.hpp"
17075e5bafSMatt Spinler #include "mocks.hpp"
18f9bae185SMatt Spinler #include "pel_utils.hpp"
19f9bae185SMatt Spinler
206fd0c1e7SHarisuddin Mohamed Isa #include <fstream>
216fd0c1e7SHarisuddin Mohamed Isa
22f9bae185SMatt Spinler #include <gtest/gtest.h>
23f9bae185SMatt Spinler
24f9bae185SMatt Spinler using namespace openpower::pels;
25ed046856SMatt Spinler using ::testing::_;
26b41fa54bSWilliam A. Kennington III using ::testing::DoAll;
27ed046856SMatt Spinler using ::testing::InvokeWithoutArgs;
28075e5bafSMatt Spinler using ::testing::NiceMock;
29075e5bafSMatt Spinler using ::testing::Return;
30ed046856SMatt Spinler using ::testing::SetArgReferee;
313bdd0110SMatt Spinler using ::testing::Throw;
326fd0c1e7SHarisuddin Mohamed Isa namespace fs = std::filesystem;
33f9bae185SMatt Spinler
346fd0c1e7SHarisuddin Mohamed Isa const auto testRegistry = R"(
356fd0c1e7SHarisuddin Mohamed Isa {
366fd0c1e7SHarisuddin Mohamed Isa "PELs":
376fd0c1e7SHarisuddin Mohamed Isa [
386fd0c1e7SHarisuddin Mohamed Isa {
396fd0c1e7SHarisuddin Mohamed Isa "Name": "xyz.openbmc_project.Error.Test",
406fd0c1e7SHarisuddin Mohamed Isa "Subsystem": "bmc_firmware",
416fd0c1e7SHarisuddin Mohamed Isa "SRC":
426fd0c1e7SHarisuddin Mohamed Isa {
436fd0c1e7SHarisuddin Mohamed Isa "ReasonCode": "0xABCD",
446fd0c1e7SHarisuddin Mohamed Isa "Words6To9":
456fd0c1e7SHarisuddin Mohamed Isa {
466fd0c1e7SHarisuddin Mohamed Isa "6":
476fd0c1e7SHarisuddin Mohamed Isa {
486fd0c1e7SHarisuddin Mohamed Isa "Description": "Component ID",
496fd0c1e7SHarisuddin Mohamed Isa "AdditionalDataPropSource": "COMPID"
506fd0c1e7SHarisuddin Mohamed Isa },
516fd0c1e7SHarisuddin Mohamed Isa "7":
526fd0c1e7SHarisuddin Mohamed Isa {
536fd0c1e7SHarisuddin Mohamed Isa "Description": "Failure count",
546fd0c1e7SHarisuddin Mohamed Isa "AdditionalDataPropSource": "FREQUENCY"
556fd0c1e7SHarisuddin Mohamed Isa },
566fd0c1e7SHarisuddin Mohamed Isa "8":
576fd0c1e7SHarisuddin Mohamed Isa {
586fd0c1e7SHarisuddin Mohamed Isa "Description": "Time period",
596fd0c1e7SHarisuddin Mohamed Isa "AdditionalDataPropSource": "DURATION"
606fd0c1e7SHarisuddin Mohamed Isa },
616fd0c1e7SHarisuddin Mohamed Isa "9":
626fd0c1e7SHarisuddin Mohamed Isa {
636fd0c1e7SHarisuddin Mohamed Isa "Description": "Error code",
646fd0c1e7SHarisuddin Mohamed Isa "AdditionalDataPropSource": "ERRORCODE"
656fd0c1e7SHarisuddin Mohamed Isa }
666fd0c1e7SHarisuddin Mohamed Isa }
676fd0c1e7SHarisuddin Mohamed Isa },
686fd0c1e7SHarisuddin Mohamed Isa "Documentation":
696fd0c1e7SHarisuddin Mohamed Isa {
706fd0c1e7SHarisuddin Mohamed Isa "Description": "A Component Fault",
716fd0c1e7SHarisuddin Mohamed Isa "Message": "Comp %1 failed %2 times over %3 secs with ErrorCode %4",
726fd0c1e7SHarisuddin Mohamed Isa "MessageArgSources":
736fd0c1e7SHarisuddin Mohamed Isa [
746fd0c1e7SHarisuddin Mohamed Isa "SRCWord6", "SRCWord7", "SRCWord8", "SRCWord9"
756fd0c1e7SHarisuddin Mohamed Isa ]
766fd0c1e7SHarisuddin Mohamed Isa }
776fd0c1e7SHarisuddin Mohamed Isa }
786fd0c1e7SHarisuddin Mohamed Isa ]
796fd0c1e7SHarisuddin Mohamed Isa }
806fd0c1e7SHarisuddin Mohamed Isa )";
816fd0c1e7SHarisuddin Mohamed Isa
826fd0c1e7SHarisuddin Mohamed Isa class SRCTest : public ::testing::Test
836fd0c1e7SHarisuddin Mohamed Isa {
846fd0c1e7SHarisuddin Mohamed Isa protected:
SetUpTestCase()856fd0c1e7SHarisuddin Mohamed Isa static void SetUpTestCase()
866fd0c1e7SHarisuddin Mohamed Isa {
876fd0c1e7SHarisuddin Mohamed Isa char path[] = "/tmp/srctestXXXXXX";
886fd0c1e7SHarisuddin Mohamed Isa regDir = mkdtemp(path);
896fd0c1e7SHarisuddin Mohamed Isa }
906fd0c1e7SHarisuddin Mohamed Isa
TearDownTestCase()916fd0c1e7SHarisuddin Mohamed Isa static void TearDownTestCase()
926fd0c1e7SHarisuddin Mohamed Isa {
936fd0c1e7SHarisuddin Mohamed Isa fs::remove_all(regDir);
946fd0c1e7SHarisuddin Mohamed Isa }
956fd0c1e7SHarisuddin Mohamed Isa
writeData(const char * data)966fd0c1e7SHarisuddin Mohamed Isa static std::string writeData(const char* data)
976fd0c1e7SHarisuddin Mohamed Isa {
986fd0c1e7SHarisuddin Mohamed Isa fs::path path = regDir / "registry.json";
996fd0c1e7SHarisuddin Mohamed Isa std::ofstream stream{path};
1006fd0c1e7SHarisuddin Mohamed Isa stream << data;
1016fd0c1e7SHarisuddin Mohamed Isa return path;
1026fd0c1e7SHarisuddin Mohamed Isa }
1036fd0c1e7SHarisuddin Mohamed Isa
1046fd0c1e7SHarisuddin Mohamed Isa static fs::path regDir;
1056fd0c1e7SHarisuddin Mohamed Isa };
1066fd0c1e7SHarisuddin Mohamed Isa
1076fd0c1e7SHarisuddin Mohamed Isa fs::path SRCTest::regDir{};
1086fd0c1e7SHarisuddin Mohamed Isa
TEST_F(SRCTest,UnflattenFlattenTestNoCallouts)1096fd0c1e7SHarisuddin Mohamed Isa TEST_F(SRCTest, UnflattenFlattenTestNoCallouts)
110f9bae185SMatt Spinler {
11142828bd9SMatt Spinler auto data = pelDataFactory(TestPELType::primarySRCSection);
112f9bae185SMatt Spinler
113f9bae185SMatt Spinler Stream stream{data};
114f9bae185SMatt Spinler SRC src{stream};
115f9bae185SMatt Spinler
116f9bae185SMatt Spinler EXPECT_TRUE(src.valid());
117f9bae185SMatt Spinler
118f9bae185SMatt Spinler EXPECT_EQ(src.header().id, 0x5053);
119f1b46ff4SMatt Spinler EXPECT_EQ(src.header().size, 0x50);
120f9bae185SMatt Spinler EXPECT_EQ(src.header().version, 0x01);
121f9bae185SMatt Spinler EXPECT_EQ(src.header().subType, 0x01);
122f9bae185SMatt Spinler EXPECT_EQ(src.header().componentID, 0x0202);
123f9bae185SMatt Spinler
124f9bae185SMatt Spinler EXPECT_EQ(src.version(), 0x02);
125f9bae185SMatt Spinler EXPECT_EQ(src.flags(), 0x00);
126f9bae185SMatt Spinler EXPECT_EQ(src.hexWordCount(), 9);
127f9bae185SMatt Spinler EXPECT_EQ(src.size(), 0x48);
128f9bae185SMatt Spinler
129f9bae185SMatt Spinler const auto& hexwords = src.hexwordData();
130bd716f00SMatt Spinler EXPECT_EQ(0x02020255, hexwords[0]);
131bd716f00SMatt Spinler EXPECT_EQ(0x03030310, hexwords[1]);
132f9bae185SMatt Spinler EXPECT_EQ(0x04040404, hexwords[2]);
133f9bae185SMatt Spinler EXPECT_EQ(0x05050505, hexwords[3]);
134f9bae185SMatt Spinler EXPECT_EQ(0x06060606, hexwords[4]);
135f9bae185SMatt Spinler EXPECT_EQ(0x07070707, hexwords[5]);
136f9bae185SMatt Spinler EXPECT_EQ(0x08080808, hexwords[6]);
137f9bae185SMatt Spinler EXPECT_EQ(0x09090909, hexwords[7]);
138f9bae185SMatt Spinler
139f9bae185SMatt Spinler EXPECT_EQ(src.asciiString(), "BD8D5678 ");
140f9bae185SMatt Spinler EXPECT_FALSE(src.callouts());
141f9bae185SMatt Spinler
142f9bae185SMatt Spinler // Flatten
143f9bae185SMatt Spinler std::vector<uint8_t> newData;
144f9bae185SMatt Spinler Stream newStream{newData};
145f9bae185SMatt Spinler
146f9bae185SMatt Spinler src.flatten(newStream);
147f9bae185SMatt Spinler EXPECT_EQ(data, newData);
148f9bae185SMatt Spinler }
149f9bae185SMatt Spinler
TEST_F(SRCTest,UnflattenFlattenTest2Callouts)1506fd0c1e7SHarisuddin Mohamed Isa TEST_F(SRCTest, UnflattenFlattenTest2Callouts)
151f9bae185SMatt Spinler {
15242828bd9SMatt Spinler auto data = pelDataFactory(TestPELType::primarySRCSection2Callouts);
153f9bae185SMatt Spinler
154f9bae185SMatt Spinler Stream stream{data};
155f9bae185SMatt Spinler SRC src{stream};
156f9bae185SMatt Spinler
157f9bae185SMatt Spinler EXPECT_TRUE(src.valid());
158bd716f00SMatt Spinler EXPECT_EQ(src.flags(), 0x01); // Additional sections within the SRC.
159f9bae185SMatt Spinler
160f9bae185SMatt Spinler // Spot check the SRC fields, but they're the same as above
161f9bae185SMatt Spinler EXPECT_EQ(src.asciiString(), "BD8D5678 ");
162f9bae185SMatt Spinler
163f9bae185SMatt Spinler // There should be 2 callouts
164f9bae185SMatt Spinler const auto& calloutsSection = src.callouts();
165f9bae185SMatt Spinler ASSERT_TRUE(calloutsSection);
166f9bae185SMatt Spinler const auto& callouts = calloutsSection->callouts();
167f9bae185SMatt Spinler EXPECT_EQ(callouts.size(), 2);
168f9bae185SMatt Spinler
169f9bae185SMatt Spinler // spot check that each callout has the right substructures
170f9bae185SMatt Spinler EXPECT_TRUE(callouts.front()->fruIdentity());
171f9bae185SMatt Spinler EXPECT_FALSE(callouts.front()->pceIdentity());
172f9bae185SMatt Spinler EXPECT_FALSE(callouts.front()->mru());
173f9bae185SMatt Spinler
174f9bae185SMatt Spinler EXPECT_TRUE(callouts.back()->fruIdentity());
175f9bae185SMatt Spinler EXPECT_TRUE(callouts.back()->pceIdentity());
176f9bae185SMatt Spinler EXPECT_TRUE(callouts.back()->mru());
177f9bae185SMatt Spinler
178f9bae185SMatt Spinler // Flatten
179f9bae185SMatt Spinler std::vector<uint8_t> newData;
180f9bae185SMatt Spinler Stream newStream{newData};
181f9bae185SMatt Spinler
182f9bae185SMatt Spinler src.flatten(newStream);
183f9bae185SMatt Spinler EXPECT_EQ(data, newData);
184f9bae185SMatt Spinler }
185bd716f00SMatt Spinler
186bd716f00SMatt Spinler // Create an SRC from the message registry
TEST_F(SRCTest,CreateTestNoCallouts)1876fd0c1e7SHarisuddin Mohamed Isa TEST_F(SRCTest, CreateTestNoCallouts)
188bd716f00SMatt Spinler {
189bd716f00SMatt Spinler message::Entry entry;
190bd716f00SMatt Spinler entry.src.type = 0xBD;
191bd716f00SMatt Spinler entry.src.reasonCode = 0xABCD;
192bd716f00SMatt Spinler entry.subsystem = 0x42;
1931a1b0dfbSHarisuddin Mohamed Isa entry.src.hexwordADFields = {
1941a1b0dfbSHarisuddin Mohamed Isa {5, {"TEST1", "DESCR1"}}, // Not a user defined word
1951a1b0dfbSHarisuddin Mohamed Isa {6, {"TEST1", "DESCR1"}},
1961a1b0dfbSHarisuddin Mohamed Isa {7, {"TEST2", "DESCR2"}},
1971a1b0dfbSHarisuddin Mohamed Isa {8, {"TEST3", "DESCR3"}},
1981a1b0dfbSHarisuddin Mohamed Isa {9, {"TEST4", "DESCR4"}}};
199bd716f00SMatt Spinler
200bd716f00SMatt Spinler // Values for the SRC words pointed to above
201bd716f00SMatt Spinler std::vector<std::string> adData{"TEST1=0x12345678", "TEST2=12345678",
202bd716f00SMatt Spinler "TEST3=0XDEF", "TEST4=Z"};
203bd716f00SMatt Spinler AdditionalData ad{adData};
204075e5bafSMatt Spinler NiceMock<MockDataInterface> dataIface;
205075e5bafSMatt Spinler
206075e5bafSMatt Spinler EXPECT_CALL(dataIface, getMotherboardCCIN).WillOnce(Return("ABCD"));
207075e5bafSMatt Spinler
208075e5bafSMatt Spinler SRC src{entry, ad, dataIface};
209bd716f00SMatt Spinler
210bd716f00SMatt Spinler EXPECT_TRUE(src.valid());
211a2d7b775SMike Capps EXPECT_FALSE(src.isPowerFaultEvent());
212bd716f00SMatt Spinler EXPECT_EQ(src.size(), baseSRCSize);
213bd716f00SMatt Spinler
214bd716f00SMatt Spinler const auto& hexwords = src.hexwordData();
215bd716f00SMatt Spinler
216bd716f00SMatt Spinler // The spec always refers to SRC words 2 - 9, and as the hexwordData()
217bd716f00SMatt Spinler // array index starts at 0 use the math in the [] below to make it easier
218bd716f00SMatt Spinler // to tell what is being accessed.
219bd716f00SMatt Spinler EXPECT_EQ(hexwords[2 - 2] & 0xF0000000, 0); // Partition dump status
220bd716f00SMatt Spinler EXPECT_EQ(hexwords[2 - 2] & 0x00F00000, 0); // Partition boot type
221bd716f00SMatt Spinler EXPECT_EQ(hexwords[2 - 2] & 0x000000FF, 0x55); // SRC format
222bd716f00SMatt Spinler EXPECT_EQ(hexwords[3 - 2] & 0x000000FF, 0x10); // BMC position
223075e5bafSMatt Spinler EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0xABCD0000); // Motherboard CCIN
224bd716f00SMatt Spinler
225bd716f00SMatt Spinler // Validate more fields here as the code starts filling them in.
226bd716f00SMatt Spinler
227bd716f00SMatt Spinler // Ensure hex word 5 wasn't allowed to be set to TEST1's contents
2283fe93e96SMatt Spinler // And that none of the error status flags are set
229bd716f00SMatt Spinler EXPECT_EQ(hexwords[5 - 2], 0);
230bd716f00SMatt Spinler
231bd716f00SMatt Spinler // The user defined hex word fields specifed in the additional data.
232bd716f00SMatt Spinler EXPECT_EQ(hexwords[6 - 2], 0x12345678); // TEST1
233bd716f00SMatt Spinler EXPECT_EQ(hexwords[7 - 2], 12345678); // TEST2
234bd716f00SMatt Spinler EXPECT_EQ(hexwords[8 - 2], 0xdef); // TEST3
235bd716f00SMatt Spinler EXPECT_EQ(hexwords[9 - 2], 0); // TEST4, but can't convert a 'Z'
236bd716f00SMatt Spinler
237bd716f00SMatt Spinler EXPECT_EQ(src.asciiString(), "BD42ABCD ");
238bd716f00SMatt Spinler
239bd716f00SMatt Spinler // No callouts
240bd716f00SMatt Spinler EXPECT_FALSE(src.callouts());
241bd716f00SMatt Spinler
242bd716f00SMatt Spinler // May as well spot check the flatten/unflatten
243bd716f00SMatt Spinler std::vector<uint8_t> data;
244bd716f00SMatt Spinler Stream stream{data};
245bd716f00SMatt Spinler src.flatten(stream);
246bd716f00SMatt Spinler
247bd716f00SMatt Spinler stream.offset(0);
248bd716f00SMatt Spinler SRC newSRC{stream};
249bd716f00SMatt Spinler
250bd716f00SMatt Spinler EXPECT_TRUE(newSRC.valid());
251bd716f00SMatt Spinler EXPECT_EQ(newSRC.asciiString(), src.asciiString());
252bd716f00SMatt Spinler EXPECT_FALSE(newSRC.callouts());
253bd716f00SMatt Spinler }
2546fd0c1e7SHarisuddin Mohamed Isa
255075e5bafSMatt Spinler // Test when the CCIN string isn't a 4 character number
TEST_F(SRCTest,BadCCINTest)256075e5bafSMatt Spinler TEST_F(SRCTest, BadCCINTest)
257075e5bafSMatt Spinler {
258075e5bafSMatt Spinler message::Entry entry;
259075e5bafSMatt Spinler entry.src.type = 0xBD;
260075e5bafSMatt Spinler entry.src.reasonCode = 0xABCD;
261075e5bafSMatt Spinler entry.subsystem = 0x42;
262075e5bafSMatt Spinler
263075e5bafSMatt Spinler std::vector<std::string> adData{};
264075e5bafSMatt Spinler AdditionalData ad{adData};
265075e5bafSMatt Spinler NiceMock<MockDataInterface> dataIface;
266075e5bafSMatt Spinler
267075e5bafSMatt Spinler // First it isn't a number, then it is too long,
268075e5bafSMatt Spinler // then it is empty.
269075e5bafSMatt Spinler EXPECT_CALL(dataIface, getMotherboardCCIN)
270075e5bafSMatt Spinler .WillOnce(Return("X"))
271075e5bafSMatt Spinler .WillOnce(Return("12345"))
272075e5bafSMatt Spinler .WillOnce(Return(""));
273075e5bafSMatt Spinler
274075e5bafSMatt Spinler // The CCIN in the first half should still be 0 each time.
275075e5bafSMatt Spinler {
276075e5bafSMatt Spinler SRC src{entry, ad, dataIface};
277075e5bafSMatt Spinler EXPECT_TRUE(src.valid());
278075e5bafSMatt Spinler const auto& hexwords = src.hexwordData();
279075e5bafSMatt Spinler EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
280075e5bafSMatt Spinler }
281075e5bafSMatt Spinler
282075e5bafSMatt Spinler {
283075e5bafSMatt Spinler SRC src{entry, ad, dataIface};
284075e5bafSMatt Spinler EXPECT_TRUE(src.valid());
285075e5bafSMatt Spinler const auto& hexwords = src.hexwordData();
286075e5bafSMatt Spinler EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
287075e5bafSMatt Spinler }
288075e5bafSMatt Spinler
289075e5bafSMatt Spinler {
290075e5bafSMatt Spinler SRC src{entry, ad, dataIface};
291075e5bafSMatt Spinler EXPECT_TRUE(src.valid());
292075e5bafSMatt Spinler const auto& hexwords = src.hexwordData();
293075e5bafSMatt Spinler EXPECT_EQ(hexwords[3 - 2] & 0xFFFF0000, 0x00000000);
294075e5bafSMatt Spinler }
295075e5bafSMatt Spinler }
296075e5bafSMatt Spinler
2976fd0c1e7SHarisuddin Mohamed Isa // Test the getErrorDetails function
TEST_F(SRCTest,MessageSubstitutionTest)2986fd0c1e7SHarisuddin Mohamed Isa TEST_F(SRCTest, MessageSubstitutionTest)
2996fd0c1e7SHarisuddin Mohamed Isa {
3006fd0c1e7SHarisuddin Mohamed Isa auto path = SRCTest::writeData(testRegistry);
3016fd0c1e7SHarisuddin Mohamed Isa message::Registry registry{path};
3026fd0c1e7SHarisuddin Mohamed Isa auto entry = registry.lookup("0xABCD", message::LookupType::reasonCode);
3036fd0c1e7SHarisuddin Mohamed Isa
3046fd0c1e7SHarisuddin Mohamed Isa std::vector<std::string> adData{"COMPID=0x1", "FREQUENCY=0x4",
3056fd0c1e7SHarisuddin Mohamed Isa "DURATION=30", "ERRORCODE=0x01ABCDEF"};
3066fd0c1e7SHarisuddin Mohamed Isa AdditionalData ad{adData};
307075e5bafSMatt Spinler NiceMock<MockDataInterface> dataIface;
3086fd0c1e7SHarisuddin Mohamed Isa
309075e5bafSMatt Spinler SRC src{*entry, ad, dataIface};
3106fd0c1e7SHarisuddin Mohamed Isa EXPECT_TRUE(src.valid());
3116fd0c1e7SHarisuddin Mohamed Isa
3126fd0c1e7SHarisuddin Mohamed Isa auto errorDetails = src.getErrorDetails(registry, DetailLevel::message);
3136fd0c1e7SHarisuddin Mohamed Isa ASSERT_TRUE(errorDetails);
31439936e34SZane Shelley EXPECT_EQ(errorDetails.value(),
31539936e34SZane Shelley "Comp 0x00000001 failed 0x00000004 times over 0x0000001E secs "
31639936e34SZane Shelley "with ErrorCode 0x01ABCDEF");
3176fd0c1e7SHarisuddin Mohamed Isa }
318ed046856SMatt Spinler // Test that an inventory path callout string is
319ed046856SMatt Spinler // converted into the appropriate FRU callout.
TEST_F(SRCTest,InventoryCalloutTest)320ed046856SMatt Spinler TEST_F(SRCTest, InventoryCalloutTest)
321ed046856SMatt Spinler {
322ed046856SMatt Spinler message::Entry entry;
323ed046856SMatt Spinler entry.src.type = 0xBD;
324ed046856SMatt Spinler entry.src.reasonCode = 0xABCD;
325ed046856SMatt Spinler entry.subsystem = 0x42;
326ed046856SMatt Spinler
327ed046856SMatt Spinler std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
328ed046856SMatt Spinler AdditionalData ad{adData};
329ed046856SMatt Spinler NiceMock<MockDataInterface> dataIface;
330ed046856SMatt Spinler
3319b90e2a2SMatt Spinler EXPECT_CALL(dataIface, getLocationCode("motherboard"))
3329b90e2a2SMatt Spinler .WillOnce(Return("UTMS-P1"));
3339b90e2a2SMatt Spinler
3349b90e2a2SMatt Spinler EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
335ed046856SMatt Spinler .Times(1)
3369b90e2a2SMatt Spinler .WillOnce(DoAll(SetArgReferee<1>("1234567"), SetArgReferee<2>("CCCC"),
3379b90e2a2SMatt Spinler SetArgReferee<3>("123456789ABC")));
338ed046856SMatt Spinler
339ed046856SMatt Spinler SRC src{entry, ad, dataIface};
340ed046856SMatt Spinler EXPECT_TRUE(src.valid());
341ed046856SMatt Spinler
342ed046856SMatt Spinler ASSERT_TRUE(src.callouts());
343ed046856SMatt Spinler
344ed046856SMatt Spinler EXPECT_EQ(src.callouts()->callouts().size(), 1);
345ed046856SMatt Spinler
346ed046856SMatt Spinler auto& callout = src.callouts()->callouts().front();
347ed046856SMatt Spinler
348ed046856SMatt Spinler EXPECT_EQ(callout->locationCode(), "UTMS-P1");
349717de428SMatt Spinler EXPECT_EQ(callout->priority(), 'H');
350ed046856SMatt Spinler
351ed046856SMatt Spinler auto& fru = callout->fruIdentity();
352ed046856SMatt Spinler
353ed046856SMatt Spinler EXPECT_EQ(fru->getPN().value(), "1234567");
354ed046856SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "CCCC");
355ed046856SMatt Spinler EXPECT_EQ(fru->getSN().value(), "123456789ABC");
356ed046856SMatt Spinler
357ed046856SMatt Spinler // flatten and unflatten
358ed046856SMatt Spinler std::vector<uint8_t> data;
359ed046856SMatt Spinler Stream stream{data};
360ed046856SMatt Spinler src.flatten(stream);
361ed046856SMatt Spinler
362ed046856SMatt Spinler stream.offset(0);
363ed046856SMatt Spinler SRC newSRC{stream};
364ed046856SMatt Spinler EXPECT_TRUE(newSRC.valid());
365ed046856SMatt Spinler ASSERT_TRUE(src.callouts());
366ed046856SMatt Spinler EXPECT_EQ(src.callouts()->callouts().size(), 1);
367ed046856SMatt Spinler }
368ed046856SMatt Spinler
3699b90e2a2SMatt Spinler // Test that when the location code can't be obtained that
370479b6927SMatt Spinler // no callout is added.
TEST_F(SRCTest,InventoryCalloutNoLocCodeTest)3719b90e2a2SMatt Spinler TEST_F(SRCTest, InventoryCalloutNoLocCodeTest)
3729b90e2a2SMatt Spinler {
3739b90e2a2SMatt Spinler message::Entry entry;
3749b90e2a2SMatt Spinler entry.src.type = 0xBD;
3759b90e2a2SMatt Spinler entry.src.reasonCode = 0xABCD;
3769b90e2a2SMatt Spinler entry.subsystem = 0x42;
3779b90e2a2SMatt Spinler
3789b90e2a2SMatt Spinler std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
3799b90e2a2SMatt Spinler AdditionalData ad{adData};
3809b90e2a2SMatt Spinler NiceMock<MockDataInterface> dataIface;
3819b90e2a2SMatt Spinler
3829b90e2a2SMatt Spinler auto func = []() {
3839b90e2a2SMatt Spinler throw sdbusplus::exception::SdBusError(5, "Error");
3849b90e2a2SMatt Spinler return std::string{};
3859b90e2a2SMatt Spinler };
3869b90e2a2SMatt Spinler
3879b90e2a2SMatt Spinler EXPECT_CALL(dataIface, getLocationCode("motherboard"))
3889b90e2a2SMatt Spinler .Times(1)
3899b90e2a2SMatt Spinler .WillOnce(InvokeWithoutArgs(func));
3909b90e2a2SMatt Spinler
3919b90e2a2SMatt Spinler EXPECT_CALL(dataIface, getHWCalloutFields(_, _, _, _)).Times(0);
3929b90e2a2SMatt Spinler
3939b90e2a2SMatt Spinler SRC src{entry, ad, dataIface};
3949b90e2a2SMatt Spinler EXPECT_TRUE(src.valid());
3959b90e2a2SMatt Spinler
396479b6927SMatt Spinler ASSERT_FALSE(src.callouts());
3979b90e2a2SMatt Spinler
3989b90e2a2SMatt Spinler // flatten and unflatten
3999b90e2a2SMatt Spinler std::vector<uint8_t> data;
4009b90e2a2SMatt Spinler Stream stream{data};
4019b90e2a2SMatt Spinler src.flatten(stream);
4029b90e2a2SMatt Spinler
4039b90e2a2SMatt Spinler stream.offset(0);
4049b90e2a2SMatt Spinler SRC newSRC{stream};
4059b90e2a2SMatt Spinler EXPECT_TRUE(newSRC.valid());
406479b6927SMatt Spinler ASSERT_FALSE(src.callouts());
4079b90e2a2SMatt Spinler }
4089b90e2a2SMatt Spinler
4099b90e2a2SMatt Spinler // Test that when the VPD can't be obtained that
4109b90e2a2SMatt Spinler // a callout is still created.
TEST_F(SRCTest,InventoryCalloutNoVPDTest)411ed046856SMatt Spinler TEST_F(SRCTest, InventoryCalloutNoVPDTest)
412ed046856SMatt Spinler {
413ed046856SMatt Spinler message::Entry entry;
414ed046856SMatt Spinler entry.src.type = 0xBD;
415ed046856SMatt Spinler entry.src.reasonCode = 0xABCD;
416ed046856SMatt Spinler entry.subsystem = 0x42;
417ed046856SMatt Spinler
418ed046856SMatt Spinler std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
419ed046856SMatt Spinler AdditionalData ad{adData};
420ed046856SMatt Spinler NiceMock<MockDataInterface> dataIface;
421ed046856SMatt Spinler
4229b90e2a2SMatt Spinler EXPECT_CALL(dataIface, getLocationCode("motherboard"))
4239b90e2a2SMatt Spinler .Times(1)
4249b90e2a2SMatt Spinler .WillOnce(Return("UTMS-P10"));
4259b90e2a2SMatt Spinler
426ed046856SMatt Spinler auto func = []() { throw sdbusplus::exception::SdBusError(5, "Error"); };
427ed046856SMatt Spinler
4289b90e2a2SMatt Spinler EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
429ed046856SMatt Spinler .Times(1)
430ed046856SMatt Spinler .WillOnce(InvokeWithoutArgs(func));
431ed046856SMatt Spinler
432ed046856SMatt Spinler SRC src{entry, ad, dataIface};
433ed046856SMatt Spinler EXPECT_TRUE(src.valid());
434ed046856SMatt Spinler ASSERT_TRUE(src.callouts());
435ed046856SMatt Spinler EXPECT_EQ(src.callouts()->callouts().size(), 1);
436ed046856SMatt Spinler
437ed046856SMatt Spinler auto& callout = src.callouts()->callouts().front();
4389b90e2a2SMatt Spinler EXPECT_EQ(callout->locationCode(), "UTMS-P10");
439717de428SMatt Spinler EXPECT_EQ(callout->priority(), 'H');
440ed046856SMatt Spinler
441ed046856SMatt Spinler auto& fru = callout->fruIdentity();
442ed046856SMatt Spinler
4439b90e2a2SMatt Spinler EXPECT_EQ(fru->getPN(), "");
4449b90e2a2SMatt Spinler EXPECT_EQ(fru->getCCIN(), "");
4459b90e2a2SMatt Spinler EXPECT_EQ(fru->getSN(), "");
4469b90e2a2SMatt Spinler EXPECT_FALSE(fru->getMaintProc());
4479b90e2a2SMatt Spinler
448ed046856SMatt Spinler // flatten and unflatten
449ed046856SMatt Spinler std::vector<uint8_t> data;
450ed046856SMatt Spinler Stream stream{data};
451ed046856SMatt Spinler src.flatten(stream);
452ed046856SMatt Spinler
453ed046856SMatt Spinler stream.offset(0);
454ed046856SMatt Spinler SRC newSRC{stream};
455ed046856SMatt Spinler EXPECT_TRUE(newSRC.valid());
456ed046856SMatt Spinler ASSERT_TRUE(src.callouts());
457ed046856SMatt Spinler EXPECT_EQ(src.callouts()->callouts().size(), 1);
458ed046856SMatt Spinler }
4590398458dSMatt Spinler
TEST_F(SRCTest,RegistryCalloutTest)4600398458dSMatt Spinler TEST_F(SRCTest, RegistryCalloutTest)
4610398458dSMatt Spinler {
4620398458dSMatt Spinler message::Entry entry;
4630398458dSMatt Spinler entry.src.type = 0xBD;
4640398458dSMatt Spinler entry.src.reasonCode = 0xABCD;
4653fe93e96SMatt Spinler entry.src.deconfigFlag = true;
466da5b76b2SMatt Spinler entry.src.checkstopFlag = true;
4670398458dSMatt Spinler entry.subsystem = 0x42;
4680398458dSMatt Spinler
4690398458dSMatt Spinler entry.callouts = R"(
4700398458dSMatt Spinler [
4710398458dSMatt Spinler {
4720398458dSMatt Spinler "System": "systemA",
4730398458dSMatt Spinler "CalloutList":
4740398458dSMatt Spinler [
4750398458dSMatt Spinler {
4760398458dSMatt Spinler "Priority": "high",
4770398458dSMatt Spinler "SymbolicFRU": "service_docs"
4780398458dSMatt Spinler },
4790398458dSMatt Spinler {
4800398458dSMatt Spinler "Priority": "medium",
481*2edce4e2SMatt Spinler "Procedure": "BMC0001"
4820398458dSMatt Spinler }
4830398458dSMatt Spinler ]
4840398458dSMatt Spinler },
4850398458dSMatt Spinler {
4860398458dSMatt Spinler "System": "systemB",
4870398458dSMatt Spinler "CalloutList":
4880398458dSMatt Spinler [
4890398458dSMatt Spinler {
4900398458dSMatt Spinler "Priority": "high",
4910398458dSMatt Spinler "LocCode": "P0-C8",
4920398458dSMatt Spinler "SymbolicFRUTrusted": "service_docs"
4930398458dSMatt Spinler },
4940398458dSMatt Spinler {
4950398458dSMatt Spinler "Priority": "medium",
4960398458dSMatt Spinler "SymbolicFRUTrusted": "service_docs"
4970398458dSMatt Spinler }
4980398458dSMatt Spinler ]
499af191c7aSMatt Spinler },
500af191c7aSMatt Spinler {
501af191c7aSMatt Spinler "System": "systemC",
502af191c7aSMatt Spinler "CalloutList":
503af191c7aSMatt Spinler [
504af191c7aSMatt Spinler {
505af191c7aSMatt Spinler "Priority": "high",
506af191c7aSMatt Spinler "LocCode": "P0-C8"
507af191c7aSMatt Spinler },
508af191c7aSMatt Spinler {
509af191c7aSMatt Spinler "Priority": "medium",
510af191c7aSMatt Spinler "LocCode": "P0-C9"
511af191c7aSMatt Spinler }
512af191c7aSMatt Spinler ]
5130398458dSMatt Spinler }
5140398458dSMatt Spinler ])"_json;
5150398458dSMatt Spinler
5160398458dSMatt Spinler {
5170398458dSMatt Spinler // Call out a symbolic FRU and a procedure
5180398458dSMatt Spinler AdditionalData ad;
5190398458dSMatt Spinler NiceMock<MockDataInterface> dataIface;
5206ea4d5f7SMatt Spinler std::vector<std::string> names{"systemA"};
5216ea4d5f7SMatt Spinler
5221ab6696fSMatt Spinler EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
5230398458dSMatt Spinler
5240398458dSMatt Spinler SRC src{entry, ad, dataIface};
5250398458dSMatt Spinler
526da5b76b2SMatt Spinler EXPECT_TRUE(
527da5b76b2SMatt Spinler src.getErrorStatusFlag(SRC::ErrorStatusFlags::deconfigured));
528da5b76b2SMatt Spinler EXPECT_TRUE(src.getErrorStatusFlag(SRC::ErrorStatusFlags::hwCheckstop));
529da5b76b2SMatt Spinler
5303fe93e96SMatt Spinler const auto& hexwords = src.hexwordData();
531da5b76b2SMatt Spinler auto mask = static_cast<uint32_t>(SRC::ErrorStatusFlags::deconfigured) |
532da5b76b2SMatt Spinler static_cast<uint32_t>(SRC::ErrorStatusFlags::hwCheckstop);
5333fe93e96SMatt Spinler EXPECT_EQ(hexwords[5 - 2] & mask, mask);
5343fe93e96SMatt Spinler
5350398458dSMatt Spinler auto& callouts = src.callouts()->callouts();
5360398458dSMatt Spinler ASSERT_EQ(callouts.size(), 2);
5370398458dSMatt Spinler
5380398458dSMatt Spinler EXPECT_EQ(callouts[0]->locationCodeSize(), 0);
5390398458dSMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
5400398458dSMatt Spinler
5410398458dSMatt Spinler EXPECT_EQ(callouts[1]->locationCodeSize(), 0);
5420398458dSMatt Spinler EXPECT_EQ(callouts[1]->priority(), 'M');
5430398458dSMatt Spinler
5440398458dSMatt Spinler auto& fru1 = callouts[0]->fruIdentity();
5450398458dSMatt Spinler EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
5460398458dSMatt Spinler EXPECT_EQ(fru1->failingComponentType(), src::FRUIdentity::symbolicFRU);
5470398458dSMatt Spinler EXPECT_FALSE(fru1->getMaintProc());
5480398458dSMatt Spinler EXPECT_FALSE(fru1->getSN());
5490398458dSMatt Spinler EXPECT_FALSE(fru1->getCCIN());
5500398458dSMatt Spinler
5510398458dSMatt Spinler auto& fru2 = callouts[1]->fruIdentity();
552ea2873ddSMatt Spinler EXPECT_EQ(fru2->getMaintProc().value(), "BMC0001");
5530398458dSMatt Spinler EXPECT_EQ(fru2->failingComponentType(),
5540398458dSMatt Spinler src::FRUIdentity::maintenanceProc);
5550398458dSMatt Spinler EXPECT_FALSE(fru2->getPN());
5560398458dSMatt Spinler EXPECT_FALSE(fru2->getSN());
5570398458dSMatt Spinler EXPECT_FALSE(fru2->getCCIN());
5580398458dSMatt Spinler }
5590398458dSMatt Spinler
5600398458dSMatt Spinler {
5610398458dSMatt Spinler // Call out a trusted symbolic FRU with a location code, and
5620398458dSMatt Spinler // another one without.
5630398458dSMatt Spinler AdditionalData ad;
5640398458dSMatt Spinler NiceMock<MockDataInterface> dataIface;
5656ea4d5f7SMatt Spinler std::vector<std::string> names{"systemB"};
5666ea4d5f7SMatt Spinler
567af191c7aSMatt Spinler EXPECT_CALL(dataIface, expandLocationCode).WillOnce(Return("P0-C8"));
5681ab6696fSMatt Spinler EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
5690398458dSMatt Spinler
5700398458dSMatt Spinler SRC src{entry, ad, dataIface};
5710398458dSMatt Spinler
5720398458dSMatt Spinler auto& callouts = src.callouts()->callouts();
5730398458dSMatt Spinler EXPECT_EQ(callouts.size(), 2);
5740398458dSMatt Spinler
5750398458dSMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "P0-C8");
5760398458dSMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
5770398458dSMatt Spinler
5780398458dSMatt Spinler EXPECT_EQ(callouts[1]->locationCodeSize(), 0);
5790398458dSMatt Spinler EXPECT_EQ(callouts[1]->priority(), 'M');
5800398458dSMatt Spinler
5810398458dSMatt Spinler auto& fru1 = callouts[0]->fruIdentity();
5820398458dSMatt Spinler EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
5830398458dSMatt Spinler EXPECT_EQ(fru1->failingComponentType(),
5840398458dSMatt Spinler src::FRUIdentity::symbolicFRUTrustedLocCode);
5850398458dSMatt Spinler EXPECT_FALSE(fru1->getMaintProc());
5860398458dSMatt Spinler EXPECT_FALSE(fru1->getSN());
5870398458dSMatt Spinler EXPECT_FALSE(fru1->getCCIN());
5880398458dSMatt Spinler
5890398458dSMatt Spinler // It asked for a trusted symbolic FRU, but no location code
5900398458dSMatt Spinler // was provided so it is switched back to a normal one
5910398458dSMatt Spinler auto& fru2 = callouts[1]->fruIdentity();
5920398458dSMatt Spinler EXPECT_EQ(fru2->getPN().value(), "SVCDOCS");
5930398458dSMatt Spinler EXPECT_EQ(fru2->failingComponentType(), src::FRUIdentity::symbolicFRU);
5940398458dSMatt Spinler EXPECT_FALSE(fru2->getMaintProc());
5950398458dSMatt Spinler EXPECT_FALSE(fru2->getSN());
5960398458dSMatt Spinler EXPECT_FALSE(fru2->getCCIN());
5970398458dSMatt Spinler }
598af191c7aSMatt Spinler
599af191c7aSMatt Spinler {
600af191c7aSMatt Spinler // Two hardware callouts
601af191c7aSMatt Spinler AdditionalData ad;
602af191c7aSMatt Spinler NiceMock<MockDataInterface> dataIface;
603af191c7aSMatt Spinler std::vector<std::string> names{"systemC"};
604af191c7aSMatt Spinler
6051ab6696fSMatt Spinler EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
606af191c7aSMatt Spinler
607af191c7aSMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P0-C8", 0))
608af191c7aSMatt Spinler .WillOnce(Return("UXXX-P0-C8"));
609af191c7aSMatt Spinler
610af191c7aSMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P0-C9", 0))
611af191c7aSMatt Spinler .WillOnce(Return("UXXX-P0-C9"));
612af191c7aSMatt Spinler
6132f9225a4SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C8", 0, false))
614bad056beSMatt Spinler .WillOnce(Return(std::vector<std::string>{
615bad056beSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0"}));
616af191c7aSMatt Spinler
6172f9225a4SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C9", 0, false))
618bad056beSMatt Spinler .WillOnce(Return(std::vector<std::string>{
619bad056beSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/cpu1"}));
620af191c7aSMatt Spinler
621af191c7aSMatt Spinler EXPECT_CALL(
622af191c7aSMatt Spinler dataIface,
623af191c7aSMatt Spinler getHWCalloutFields(
624af191c7aSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0", _, _,
625af191c7aSMatt Spinler _))
626af191c7aSMatt Spinler .Times(1)
627af191c7aSMatt Spinler .WillOnce(DoAll(SetArgReferee<1>("1234567"),
628af191c7aSMatt Spinler SetArgReferee<2>("CCCC"),
629af191c7aSMatt Spinler SetArgReferee<3>("123456789ABC")));
630af191c7aSMatt Spinler
631af191c7aSMatt Spinler EXPECT_CALL(
632af191c7aSMatt Spinler dataIface,
633af191c7aSMatt Spinler getHWCalloutFields(
634af191c7aSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/cpu1", _, _,
635af191c7aSMatt Spinler _))
636af191c7aSMatt Spinler .Times(1)
637af191c7aSMatt Spinler .WillOnce(DoAll(SetArgReferee<1>("2345678"),
638af191c7aSMatt Spinler SetArgReferee<2>("DDDD"),
639af191c7aSMatt Spinler SetArgReferee<3>("23456789ABCD")));
640af191c7aSMatt Spinler
641af191c7aSMatt Spinler SRC src{entry, ad, dataIface};
642af191c7aSMatt Spinler
643af191c7aSMatt Spinler auto& callouts = src.callouts()->callouts();
644af191c7aSMatt Spinler EXPECT_EQ(callouts.size(), 2);
645af191c7aSMatt Spinler
646af191c7aSMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "UXXX-P0-C8");
647af191c7aSMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
648af191c7aSMatt Spinler
649af191c7aSMatt Spinler auto& fru1 = callouts[0]->fruIdentity();
650af191c7aSMatt Spinler EXPECT_EQ(fru1->getPN().value(), "1234567");
651af191c7aSMatt Spinler EXPECT_EQ(fru1->getCCIN().value(), "CCCC");
652af191c7aSMatt Spinler EXPECT_EQ(fru1->getSN().value(), "123456789ABC");
653af191c7aSMatt Spinler
654af191c7aSMatt Spinler EXPECT_EQ(callouts[1]->locationCode(), "UXXX-P0-C9");
655af191c7aSMatt Spinler EXPECT_EQ(callouts[1]->priority(), 'M');
656af191c7aSMatt Spinler
657af191c7aSMatt Spinler auto& fru2 = callouts[1]->fruIdentity();
658af191c7aSMatt Spinler EXPECT_EQ(fru2->getPN().value(), "2345678");
659af191c7aSMatt Spinler EXPECT_EQ(fru2->getCCIN().value(), "DDDD");
660af191c7aSMatt Spinler EXPECT_EQ(fru2->getSN().value(), "23456789ABCD");
661af191c7aSMatt Spinler }
6620398458dSMatt Spinler }
663717de428SMatt Spinler
664f00f9d0fSMatt Spinler // Test that a symbolic FRU with a trusted location code callout
665f00f9d0fSMatt Spinler // from the registry can get its location from the
666f00f9d0fSMatt Spinler // CALLOUT_INVENTORY_PATH AdditionalData entry.
TEST_F(SRCTest,SymbolicFRUWithInvPathTest)667f00f9d0fSMatt Spinler TEST_F(SRCTest, SymbolicFRUWithInvPathTest)
668f00f9d0fSMatt Spinler {
669f00f9d0fSMatt Spinler message::Entry entry;
670f00f9d0fSMatt Spinler entry.src.type = 0xBD;
671f00f9d0fSMatt Spinler entry.src.reasonCode = 0xABCD;
672f00f9d0fSMatt Spinler entry.subsystem = 0x42;
673f00f9d0fSMatt Spinler
674f00f9d0fSMatt Spinler entry.callouts = R"(
675f00f9d0fSMatt Spinler [{
676f00f9d0fSMatt Spinler "CalloutList":
677f00f9d0fSMatt Spinler [
678f00f9d0fSMatt Spinler {
679f00f9d0fSMatt Spinler "Priority": "high",
680f00f9d0fSMatt Spinler "SymbolicFRUTrusted": "service_docs",
681f00f9d0fSMatt Spinler "UseInventoryLocCode": true
682f00f9d0fSMatt Spinler },
683f00f9d0fSMatt Spinler {
684f00f9d0fSMatt Spinler "Priority": "medium",
685f00f9d0fSMatt Spinler "LocCode": "P0-C8",
686f00f9d0fSMatt Spinler "SymbolicFRUTrusted": "pwrsply"
687f00f9d0fSMatt Spinler }
688f00f9d0fSMatt Spinler ]
689f00f9d0fSMatt Spinler }])"_json;
690f00f9d0fSMatt Spinler
691f00f9d0fSMatt Spinler {
692f00f9d0fSMatt Spinler // The location code for the first symbolic FRU callout will
693f00f9d0fSMatt Spinler // come from this inventory path since UseInventoryLocCode is set.
694f00f9d0fSMatt Spinler // In this case there will be no normal FRU callout for the motherboard.
695f00f9d0fSMatt Spinler std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
696f00f9d0fSMatt Spinler AdditionalData ad{adData};
697f00f9d0fSMatt Spinler NiceMock<MockDataInterface> dataIface;
698f00f9d0fSMatt Spinler std::vector<std::string> names{"systemA"};
699f00f9d0fSMatt Spinler
7001ab6696fSMatt Spinler EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
701f00f9d0fSMatt Spinler
702f00f9d0fSMatt Spinler EXPECT_CALL(dataIface, getLocationCode("motherboard"))
703f00f9d0fSMatt Spinler .Times(1)
704f00f9d0fSMatt Spinler .WillOnce(Return("Ufcs-P10"));
705f00f9d0fSMatt Spinler
706f00f9d0fSMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P0-C8", 0))
707f00f9d0fSMatt Spinler .WillOnce(Return("Ufcs-P0-C8"));
708f00f9d0fSMatt Spinler
709f00f9d0fSMatt Spinler SRC src{entry, ad, dataIface};
710f00f9d0fSMatt Spinler
711f00f9d0fSMatt Spinler auto& callouts = src.callouts()->callouts();
712f00f9d0fSMatt Spinler EXPECT_EQ(callouts.size(), 2);
713f00f9d0fSMatt Spinler
714f00f9d0fSMatt Spinler // The location code for the first symbolic FRU callout with a
715f00f9d0fSMatt Spinler // trusted location code comes from the motherboard.
716f00f9d0fSMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "Ufcs-P10");
717f00f9d0fSMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
718f00f9d0fSMatt Spinler auto& fru1 = callouts[0]->fruIdentity();
719f00f9d0fSMatt Spinler EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
720f00f9d0fSMatt Spinler EXPECT_EQ(fru1->failingComponentType(),
721f00f9d0fSMatt Spinler src::FRUIdentity::symbolicFRUTrustedLocCode);
722f00f9d0fSMatt Spinler
723f00f9d0fSMatt Spinler // The second trusted symbolic FRU callouts uses the location
724f00f9d0fSMatt Spinler // code in the registry as usual.
725f00f9d0fSMatt Spinler EXPECT_EQ(callouts[1]->locationCode(), "Ufcs-P0-C8");
726f00f9d0fSMatt Spinler EXPECT_EQ(callouts[1]->priority(), 'M');
727f00f9d0fSMatt Spinler auto& fru2 = callouts[1]->fruIdentity();
728f00f9d0fSMatt Spinler EXPECT_EQ(fru2->getPN().value(), "PWRSPLY");
729f00f9d0fSMatt Spinler EXPECT_EQ(fru2->failingComponentType(),
730f00f9d0fSMatt Spinler src::FRUIdentity::symbolicFRUTrustedLocCode);
731f00f9d0fSMatt Spinler }
732f00f9d0fSMatt Spinler
733f00f9d0fSMatt Spinler {
734f00f9d0fSMatt Spinler // This time say we want to use the location code from
735f00f9d0fSMatt Spinler // the inventory, but don't pass it in and the callout should
736f00f9d0fSMatt Spinler // end up a regular symbolic FRU
737f00f9d0fSMatt Spinler entry.callouts = R"(
738f00f9d0fSMatt Spinler [{
739f00f9d0fSMatt Spinler "CalloutList":
740f00f9d0fSMatt Spinler [
741f00f9d0fSMatt Spinler {
742f00f9d0fSMatt Spinler "Priority": "high",
743f00f9d0fSMatt Spinler "SymbolicFRUTrusted": "service_docs",
744f00f9d0fSMatt Spinler "UseInventoryLocCode": true
745f00f9d0fSMatt Spinler }
746f00f9d0fSMatt Spinler ]
747f00f9d0fSMatt Spinler }])"_json;
748f00f9d0fSMatt Spinler
749f00f9d0fSMatt Spinler AdditionalData ad;
750f00f9d0fSMatt Spinler NiceMock<MockDataInterface> dataIface;
751f00f9d0fSMatt Spinler std::vector<std::string> names{"systemA"};
752f00f9d0fSMatt Spinler
7531ab6696fSMatt Spinler EXPECT_CALL(dataIface, getSystemNames).WillOnce(Return(names));
754f00f9d0fSMatt Spinler
755f00f9d0fSMatt Spinler SRC src{entry, ad, dataIface};
756f00f9d0fSMatt Spinler
757f00f9d0fSMatt Spinler auto& callouts = src.callouts()->callouts();
758f00f9d0fSMatt Spinler EXPECT_EQ(callouts.size(), 1);
759f00f9d0fSMatt Spinler
760f00f9d0fSMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "");
761f00f9d0fSMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
762f00f9d0fSMatt Spinler auto& fru1 = callouts[0]->fruIdentity();
763f00f9d0fSMatt Spinler EXPECT_EQ(fru1->getPN().value(), "SVCDOCS");
764f00f9d0fSMatt Spinler EXPECT_EQ(fru1->failingComponentType(), src::FRUIdentity::symbolicFRU);
765f00f9d0fSMatt Spinler }
766f00f9d0fSMatt Spinler }
767f00f9d0fSMatt Spinler
768717de428SMatt Spinler // Test looking up device path fails in the callout jSON.
TEST_F(SRCTest,DevicePathCalloutTest)769717de428SMatt Spinler TEST_F(SRCTest, DevicePathCalloutTest)
770717de428SMatt Spinler {
771717de428SMatt Spinler message::Entry entry;
772717de428SMatt Spinler entry.src.type = 0xBD;
773717de428SMatt Spinler entry.src.reasonCode = 0xABCD;
774717de428SMatt Spinler entry.subsystem = 0x42;
775717de428SMatt Spinler
776717de428SMatt Spinler const auto calloutJSON = R"(
777717de428SMatt Spinler {
778717de428SMatt Spinler "I2C":
779717de428SMatt Spinler {
780717de428SMatt Spinler "14":
781717de428SMatt Spinler {
782717de428SMatt Spinler "114":
783717de428SMatt Spinler {
784717de428SMatt Spinler "Callouts":[
785717de428SMatt Spinler {
786717de428SMatt Spinler "Name": "/chassis/motherboard/cpu0",
787717de428SMatt Spinler "LocationCode": "P1-C40",
788717de428SMatt Spinler "Priority": "H"
789717de428SMatt Spinler },
790717de428SMatt Spinler {
791717de428SMatt Spinler "Name": "/chassis/motherboard",
792717de428SMatt Spinler "LocationCode": "P1",
793717de428SMatt Spinler "Priority": "M"
794717de428SMatt Spinler },
795717de428SMatt Spinler {
796717de428SMatt Spinler "Name": "/chassis/motherboard/bmc",
797717de428SMatt Spinler "LocationCode": "P1-C15",
798717de428SMatt Spinler "Priority": "L"
799717de428SMatt Spinler }
800717de428SMatt Spinler ],
801717de428SMatt Spinler "Dest": "proc 0 target"
802717de428SMatt Spinler }
803717de428SMatt Spinler }
804717de428SMatt Spinler }
805717de428SMatt Spinler })";
806717de428SMatt Spinler
807717de428SMatt Spinler auto dataPath = getPELReadOnlyDataPath();
808717de428SMatt Spinler std::ofstream file{dataPath / "systemA_dev_callouts.json"};
809717de428SMatt Spinler file << calloutJSON;
810717de428SMatt Spinler file.close();
811717de428SMatt Spinler
812717de428SMatt Spinler NiceMock<MockDataInterface> dataIface;
813717de428SMatt Spinler std::vector<std::string> names{"systemA"};
814717de428SMatt Spinler
815717de428SMatt Spinler EXPECT_CALL(dataIface, getSystemNames)
816717de428SMatt Spinler .Times(5)
8171ab6696fSMatt Spinler .WillRepeatedly(Return(names));
818717de428SMatt Spinler
8192f9225a4SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P1-C40", 0, false))
820717de428SMatt Spinler .Times(3)
821bad056beSMatt Spinler .WillRepeatedly(Return(std::vector<std::string>{
822bad056beSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0"}));
823717de428SMatt Spinler
8242f9225a4SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P1", 0, false))
825717de428SMatt Spinler .Times(3)
826bad056beSMatt Spinler .WillRepeatedly(Return(std::vector<std::string>{
827bad056beSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard"}));
828717de428SMatt Spinler
8292f9225a4SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P1-C15", 0, false))
830717de428SMatt Spinler .Times(3)
831bad056beSMatt Spinler .WillRepeatedly(Return(std::vector<std::string>{
832bad056beSMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/bmc"}));
833717de428SMatt Spinler
8340d92b528SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P1-C40", 0))
835717de428SMatt Spinler .Times(3)
836717de428SMatt Spinler .WillRepeatedly(Return("Ufcs-P1-C40"));
8370d92b528SMatt Spinler
8380d92b528SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P1", 0))
839717de428SMatt Spinler .Times(3)
840717de428SMatt Spinler .WillRepeatedly(Return("Ufcs-P1"));
8410d92b528SMatt Spinler
8420d92b528SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P1-C15", 0))
843717de428SMatt Spinler .Times(3)
844717de428SMatt Spinler .WillRepeatedly(Return("Ufcs-P1-C15"));
845717de428SMatt Spinler
846717de428SMatt Spinler EXPECT_CALL(
847717de428SMatt Spinler dataIface,
848717de428SMatt Spinler getHWCalloutFields(
849717de428SMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/cpu0", _, _, _))
850717de428SMatt Spinler .Times(3)
851717de428SMatt Spinler .WillRepeatedly(DoAll(SetArgReferee<1>("1234567"),
852717de428SMatt Spinler SetArgReferee<2>("CCCC"),
853717de428SMatt Spinler SetArgReferee<3>("123456789ABC")));
854717de428SMatt Spinler EXPECT_CALL(
855717de428SMatt Spinler dataIface,
856717de428SMatt Spinler getHWCalloutFields("/xyz/openbmc_project/inventory/chassis/motherboard",
857717de428SMatt Spinler _, _, _))
858717de428SMatt Spinler .Times(3)
859717de428SMatt Spinler .WillRepeatedly(DoAll(SetArgReferee<1>("7654321"),
860717de428SMatt Spinler SetArgReferee<2>("MMMM"),
861717de428SMatt Spinler SetArgReferee<3>("CBA987654321")));
862717de428SMatt Spinler EXPECT_CALL(
863717de428SMatt Spinler dataIface,
864717de428SMatt Spinler getHWCalloutFields(
865717de428SMatt Spinler "/xyz/openbmc_project/inventory/chassis/motherboard/bmc", _, _, _))
866717de428SMatt Spinler .Times(3)
867717de428SMatt Spinler .WillRepeatedly(DoAll(SetArgReferee<1>("7123456"),
868717de428SMatt Spinler SetArgReferee<2>("BBBB"),
869717de428SMatt Spinler SetArgReferee<3>("C123456789AB")));
870717de428SMatt Spinler
871717de428SMatt Spinler // Call this below with different AdditionalData values that
872717de428SMatt Spinler // result in the same callouts.
873717de428SMatt Spinler auto checkCallouts = [&entry, &dataIface](const auto& items) {
874717de428SMatt Spinler AdditionalData ad{items};
875717de428SMatt Spinler SRC src{entry, ad, dataIface};
876717de428SMatt Spinler
877717de428SMatt Spinler ASSERT_TRUE(src.callouts());
878717de428SMatt Spinler auto& callouts = src.callouts()->callouts();
879717de428SMatt Spinler
880717de428SMatt Spinler ASSERT_EQ(callouts.size(), 3);
881717de428SMatt Spinler
882717de428SMatt Spinler {
883717de428SMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
884717de428SMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "Ufcs-P1-C40");
885717de428SMatt Spinler
886717de428SMatt Spinler auto& fru = callouts[0]->fruIdentity();
887717de428SMatt Spinler EXPECT_EQ(fru->getPN().value(), "1234567");
888717de428SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "CCCC");
889717de428SMatt Spinler EXPECT_EQ(fru->getSN().value(), "123456789ABC");
890717de428SMatt Spinler }
891717de428SMatt Spinler {
892717de428SMatt Spinler EXPECT_EQ(callouts[1]->priority(), 'M');
893717de428SMatt Spinler EXPECT_EQ(callouts[1]->locationCode(), "Ufcs-P1");
894717de428SMatt Spinler
895717de428SMatt Spinler auto& fru = callouts[1]->fruIdentity();
896717de428SMatt Spinler EXPECT_EQ(fru->getPN().value(), "7654321");
897717de428SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "MMMM");
898717de428SMatt Spinler EXPECT_EQ(fru->getSN().value(), "CBA987654321");
899717de428SMatt Spinler }
900717de428SMatt Spinler {
901717de428SMatt Spinler EXPECT_EQ(callouts[2]->priority(), 'L');
902717de428SMatt Spinler EXPECT_EQ(callouts[2]->locationCode(), "Ufcs-P1-C15");
903717de428SMatt Spinler
904717de428SMatt Spinler auto& fru = callouts[2]->fruIdentity();
905717de428SMatt Spinler EXPECT_EQ(fru->getPN().value(), "7123456");
906717de428SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "BBBB");
907717de428SMatt Spinler EXPECT_EQ(fru->getSN().value(), "C123456789AB");
908717de428SMatt Spinler }
909717de428SMatt Spinler };
910717de428SMatt Spinler
911717de428SMatt Spinler {
912717de428SMatt Spinler // Callouts based on the device path
913717de428SMatt Spinler std::vector<std::string> items{
914717de428SMatt Spinler "CALLOUT_ERRNO=5",
915717de428SMatt Spinler "CALLOUT_DEVICE_PATH=/sys/devices/platform/ahb/ahb:apb/"
916717de428SMatt Spinler "ahb:apb:bus@1e78a000/1e78a340.i2c-bus/i2c-14/14-0072"};
917717de428SMatt Spinler
918717de428SMatt Spinler checkCallouts(items);
919717de428SMatt Spinler }
920717de428SMatt Spinler
921717de428SMatt Spinler {
922717de428SMatt Spinler // Callouts based on the I2C bus and address
923717de428SMatt Spinler std::vector<std::string> items{"CALLOUT_ERRNO=5", "CALLOUT_IIC_BUS=14",
924717de428SMatt Spinler "CALLOUT_IIC_ADDR=0x72"};
925717de428SMatt Spinler checkCallouts(items);
926717de428SMatt Spinler }
927717de428SMatt Spinler
928717de428SMatt Spinler {
929717de428SMatt Spinler // Also based on I2C bus and address, but with bus = /dev/i2c-14
930717de428SMatt Spinler std::vector<std::string> items{"CALLOUT_ERRNO=5", "CALLOUT_IIC_BUS=14",
931717de428SMatt Spinler "CALLOUT_IIC_ADDR=0x72"};
932717de428SMatt Spinler checkCallouts(items);
933717de428SMatt Spinler }
934717de428SMatt Spinler
935717de428SMatt Spinler {
936717de428SMatt Spinler // Callout not found
937717de428SMatt Spinler std::vector<std::string> items{
938717de428SMatt Spinler "CALLOUT_ERRNO=5",
939717de428SMatt Spinler "CALLOUT_DEVICE_PATH=/sys/devices/platform/ahb/ahb:apb/"
940717de428SMatt Spinler "ahb:apb:bus@1e78a000/1e78a340.i2c-bus/i2c-24/24-0012"};
941717de428SMatt Spinler
942717de428SMatt Spinler AdditionalData ad{items};
943717de428SMatt Spinler SRC src{entry, ad, dataIface};
944717de428SMatt Spinler
945717de428SMatt Spinler EXPECT_FALSE(src.callouts());
946717de428SMatt Spinler ASSERT_EQ(src.getDebugData().size(), 1);
947717de428SMatt Spinler EXPECT_EQ(src.getDebugData()[0],
948717de428SMatt Spinler "Problem looking up I2C callouts on 24 18: "
949717de428SMatt Spinler "[json.exception.out_of_range.403] key '24' not found");
950717de428SMatt Spinler }
951717de428SMatt Spinler
952717de428SMatt Spinler {
953717de428SMatt Spinler // Callout not found
954717de428SMatt Spinler std::vector<std::string> items{"CALLOUT_ERRNO=5", "CALLOUT_IIC_BUS=22",
955717de428SMatt Spinler "CALLOUT_IIC_ADDR=0x99"};
956717de428SMatt Spinler AdditionalData ad{items};
957717de428SMatt Spinler SRC src{entry, ad, dataIface};
958717de428SMatt Spinler
959717de428SMatt Spinler EXPECT_FALSE(src.callouts());
960717de428SMatt Spinler ASSERT_EQ(src.getDebugData().size(), 1);
961717de428SMatt Spinler EXPECT_EQ(src.getDebugData()[0],
962717de428SMatt Spinler "Problem looking up I2C callouts on 22 153: "
963717de428SMatt Spinler "[json.exception.out_of_range.403] key '22' not found");
964717de428SMatt Spinler }
965717de428SMatt Spinler
966717de428SMatt Spinler fs::remove_all(dataPath);
967717de428SMatt Spinler }
9683bdd0110SMatt Spinler
9693bdd0110SMatt Spinler // Test when callouts are passed in via JSON
TEST_F(SRCTest,JsonCalloutsTest)9703bdd0110SMatt Spinler TEST_F(SRCTest, JsonCalloutsTest)
9713bdd0110SMatt Spinler {
9723bdd0110SMatt Spinler const auto jsonCallouts = R"(
9733bdd0110SMatt Spinler [
9743bdd0110SMatt Spinler {
9753bdd0110SMatt Spinler "LocationCode": "P0-C1",
9763bdd0110SMatt Spinler "Priority": "H",
9773bdd0110SMatt Spinler "MRUs": [
9783bdd0110SMatt Spinler {
9793bdd0110SMatt Spinler "ID": 42,
9803bdd0110SMatt Spinler "Priority": "H"
9813bdd0110SMatt Spinler },
9823bdd0110SMatt Spinler {
9833bdd0110SMatt Spinler "ID": 43,
9843bdd0110SMatt Spinler "Priority": "M"
9853bdd0110SMatt Spinler }
9863bdd0110SMatt Spinler ]
9873bdd0110SMatt Spinler },
9883bdd0110SMatt Spinler {
9893bdd0110SMatt Spinler "InventoryPath": "/inv/system/chassis/motherboard/cpu0",
9903bdd0110SMatt Spinler "Priority": "M",
9913bdd0110SMatt Spinler "Guarded": true,
9923bdd0110SMatt Spinler "Deconfigured": true
9933bdd0110SMatt Spinler },
9943bdd0110SMatt Spinler {
9953bdd0110SMatt Spinler "Procedure": "PROCEDU",
9963bdd0110SMatt Spinler "Priority": "A"
9973bdd0110SMatt Spinler },
9983bdd0110SMatt Spinler {
9993bdd0110SMatt Spinler "SymbolicFRU": "TRUSTED",
10003bdd0110SMatt Spinler "Priority": "B",
10013bdd0110SMatt Spinler "TrustedLocationCode": true,
10023bdd0110SMatt Spinler "LocationCode": "P1-C23"
10033bdd0110SMatt Spinler },
10043bdd0110SMatt Spinler {
10053bdd0110SMatt Spinler "SymbolicFRU": "FRUTST1",
10063bdd0110SMatt Spinler "Priority": "C",
10073bdd0110SMatt Spinler "LocationCode": "P1-C24"
10083bdd0110SMatt Spinler },
10093bdd0110SMatt Spinler {
10103bdd0110SMatt Spinler "SymbolicFRU": "FRUTST2LONG",
10113bdd0110SMatt Spinler "Priority": "L"
10123c7ec6d8SMatt Spinler },
10133c7ec6d8SMatt Spinler {
10143c7ec6d8SMatt Spinler "Procedure": "fsi_path",
10153c7ec6d8SMatt Spinler "Priority": "L"
10163c7ec6d8SMatt Spinler },
10173c7ec6d8SMatt Spinler {
10183c7ec6d8SMatt Spinler "SymbolicFRU": "ambient_temp",
10193c7ec6d8SMatt Spinler "Priority": "L"
10203bdd0110SMatt Spinler }
10213bdd0110SMatt Spinler ]
10223bdd0110SMatt Spinler )"_json;
10233bdd0110SMatt Spinler
10243bdd0110SMatt Spinler message::Entry entry;
10253bdd0110SMatt Spinler entry.src.type = 0xBD;
10263bdd0110SMatt Spinler entry.src.reasonCode = 0xABCD;
10273bdd0110SMatt Spinler entry.subsystem = 0x42;
10283bdd0110SMatt Spinler
10293bdd0110SMatt Spinler AdditionalData ad;
10303bdd0110SMatt Spinler NiceMock<MockDataInterface> dataIface;
10313bdd0110SMatt Spinler
10323bdd0110SMatt Spinler // Callout 0 mock calls
10333bdd0110SMatt Spinler {
10343bdd0110SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P0-C1", 0))
10353bdd0110SMatt Spinler .Times(1)
10363bdd0110SMatt Spinler .WillOnce(Return("UXXX-P0-C1"));
10373bdd0110SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C1", 0, false))
10383bdd0110SMatt Spinler .Times(1)
1039bad056beSMatt Spinler .WillOnce(Return(std::vector<std::string>{
1040bad056beSMatt Spinler "/inv/system/chassis/motherboard/bmc"}));
10413bdd0110SMatt Spinler EXPECT_CALL(
10423bdd0110SMatt Spinler dataIface,
10433bdd0110SMatt Spinler getHWCalloutFields("/inv/system/chassis/motherboard/bmc", _, _, _))
10443bdd0110SMatt Spinler .Times(1)
10453bdd0110SMatt Spinler .WillOnce(DoAll(SetArgReferee<1>("1234567"),
10463bdd0110SMatt Spinler SetArgReferee<2>("CCCC"),
10473bdd0110SMatt Spinler SetArgReferee<3>("123456789ABC")));
10483bdd0110SMatt Spinler }
10493bdd0110SMatt Spinler // Callout 1 mock calls
10503bdd0110SMatt Spinler {
10513bdd0110SMatt Spinler EXPECT_CALL(dataIface,
10523bdd0110SMatt Spinler getLocationCode("/inv/system/chassis/motherboard/cpu0"))
10533bdd0110SMatt Spinler .WillOnce(Return("UYYY-P5"));
10543bdd0110SMatt Spinler EXPECT_CALL(
10553bdd0110SMatt Spinler dataIface,
10563bdd0110SMatt Spinler getHWCalloutFields("/inv/system/chassis/motherboard/cpu0", _, _, _))
10573bdd0110SMatt Spinler .Times(1)
10583bdd0110SMatt Spinler .WillOnce(DoAll(SetArgReferee<1>("2345678"),
10593bdd0110SMatt Spinler SetArgReferee<2>("DDDD"),
10603bdd0110SMatt Spinler SetArgReferee<3>("23456789ABCD")));
10613bdd0110SMatt Spinler }
10623bdd0110SMatt Spinler // Callout 3 mock calls
10633bdd0110SMatt Spinler {
10643bdd0110SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P1-C23", 0))
10653bdd0110SMatt Spinler .Times(1)
10663bdd0110SMatt Spinler .WillOnce(Return("UXXX-P1-C23"));
10673bdd0110SMatt Spinler }
10683bdd0110SMatt Spinler // Callout 4 mock calls
10693bdd0110SMatt Spinler {
10703bdd0110SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P1-C24", 0))
10713bdd0110SMatt Spinler .Times(1)
10723bdd0110SMatt Spinler .WillOnce(Return("UXXX-P1-C24"));
10733bdd0110SMatt Spinler }
10743bdd0110SMatt Spinler
10753bdd0110SMatt Spinler SRC src{entry, ad, jsonCallouts, dataIface};
10763bdd0110SMatt Spinler ASSERT_TRUE(src.callouts());
10773bdd0110SMatt Spinler
1078afa2c799SMatt Spinler // Check the guarded and deconfigured flags
1079afa2c799SMatt Spinler EXPECT_TRUE(src.hexwordData()[3] & 0x03000000);
1080afa2c799SMatt Spinler
10813bdd0110SMatt Spinler const auto& callouts = src.callouts()->callouts();
10823c7ec6d8SMatt Spinler ASSERT_EQ(callouts.size(), 8);
10833bdd0110SMatt Spinler
10843bdd0110SMatt Spinler // Check callout 0
10853bdd0110SMatt Spinler {
10863bdd0110SMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
10873bdd0110SMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "UXXX-P0-C1");
10883bdd0110SMatt Spinler
10893bdd0110SMatt Spinler auto& fru = callouts[0]->fruIdentity();
10903bdd0110SMatt Spinler EXPECT_EQ(fru->getPN().value(), "1234567");
10913bdd0110SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "CCCC");
10923bdd0110SMatt Spinler EXPECT_EQ(fru->getSN().value(), "123456789ABC");
10933bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::hardwareFRU);
1094b8cb60feSMatt Spinler
1095b8cb60feSMatt Spinler auto& mruCallouts = callouts[0]->mru();
1096b8cb60feSMatt Spinler ASSERT_TRUE(mruCallouts);
1097b8cb60feSMatt Spinler auto& mrus = mruCallouts->mrus();
1098b8cb60feSMatt Spinler ASSERT_EQ(mrus.size(), 2);
1099b8cb60feSMatt Spinler EXPECT_EQ(mrus[0].id, 42);
1100b8cb60feSMatt Spinler EXPECT_EQ(mrus[0].priority, 'H');
1101b8cb60feSMatt Spinler EXPECT_EQ(mrus[1].id, 43);
1102b8cb60feSMatt Spinler EXPECT_EQ(mrus[1].priority, 'M');
11033bdd0110SMatt Spinler }
11043bdd0110SMatt Spinler
11053bdd0110SMatt Spinler // Check callout 1
11063bdd0110SMatt Spinler {
11073bdd0110SMatt Spinler EXPECT_EQ(callouts[1]->priority(), 'M');
11083bdd0110SMatt Spinler EXPECT_EQ(callouts[1]->locationCode(), "UYYY-P5");
11093bdd0110SMatt Spinler
11103bdd0110SMatt Spinler auto& fru = callouts[1]->fruIdentity();
11113bdd0110SMatt Spinler EXPECT_EQ(fru->getPN().value(), "2345678");
11123bdd0110SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "DDDD");
11133bdd0110SMatt Spinler EXPECT_EQ(fru->getSN().value(), "23456789ABCD");
11143bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::hardwareFRU);
11153bdd0110SMatt Spinler }
11163bdd0110SMatt Spinler
11173bdd0110SMatt Spinler // Check callout 2
11183bdd0110SMatt Spinler {
11193bdd0110SMatt Spinler EXPECT_EQ(callouts[2]->priority(), 'A');
11203bdd0110SMatt Spinler EXPECT_EQ(callouts[2]->locationCode(), "");
11213bdd0110SMatt Spinler
11223bdd0110SMatt Spinler auto& fru = callouts[2]->fruIdentity();
11233bdd0110SMatt Spinler EXPECT_EQ(fru->getMaintProc().value(), "PROCEDU");
11243bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(),
11253bdd0110SMatt Spinler src::FRUIdentity::maintenanceProc);
11263bdd0110SMatt Spinler }
11273bdd0110SMatt Spinler
11283bdd0110SMatt Spinler // Check callout 3
11293bdd0110SMatt Spinler {
11303bdd0110SMatt Spinler EXPECT_EQ(callouts[3]->priority(), 'B');
11313bdd0110SMatt Spinler EXPECT_EQ(callouts[3]->locationCode(), "UXXX-P1-C23");
11323bdd0110SMatt Spinler
11333bdd0110SMatt Spinler auto& fru = callouts[3]->fruIdentity();
11343bdd0110SMatt Spinler EXPECT_EQ(fru->getPN().value(), "TRUSTED");
11353bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(),
11363bdd0110SMatt Spinler src::FRUIdentity::symbolicFRUTrustedLocCode);
11373bdd0110SMatt Spinler }
11383bdd0110SMatt Spinler
11393bdd0110SMatt Spinler // Check callout 4
11403bdd0110SMatt Spinler {
11413bdd0110SMatt Spinler EXPECT_EQ(callouts[4]->priority(), 'C');
11423bdd0110SMatt Spinler EXPECT_EQ(callouts[4]->locationCode(), "UXXX-P1-C24");
11433bdd0110SMatt Spinler
11443bdd0110SMatt Spinler auto& fru = callouts[4]->fruIdentity();
11453bdd0110SMatt Spinler EXPECT_EQ(fru->getPN().value(), "FRUTST1");
11463bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::symbolicFRU);
11473bdd0110SMatt Spinler }
11483bdd0110SMatt Spinler
11493bdd0110SMatt Spinler // Check callout 5
11503bdd0110SMatt Spinler {
11513bdd0110SMatt Spinler EXPECT_EQ(callouts[5]->priority(), 'L');
11523bdd0110SMatt Spinler EXPECT_EQ(callouts[5]->locationCode(), "");
11533bdd0110SMatt Spinler
11543bdd0110SMatt Spinler auto& fru = callouts[5]->fruIdentity();
11553bdd0110SMatt Spinler EXPECT_EQ(fru->getPN().value(), "FRUTST2");
11563bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::symbolicFRU);
11573bdd0110SMatt Spinler }
11583bdd0110SMatt Spinler
11593c7ec6d8SMatt Spinler // Check callout 6
11603c7ec6d8SMatt Spinler {
11613c7ec6d8SMatt Spinler EXPECT_EQ(callouts[6]->priority(), 'L');
11623c7ec6d8SMatt Spinler EXPECT_EQ(callouts[6]->locationCode(), "");
11633c7ec6d8SMatt Spinler
11643c7ec6d8SMatt Spinler auto& fru = callouts[6]->fruIdentity();
11653c7ec6d8SMatt Spinler EXPECT_EQ(fru->getMaintProc().value(), "BMC0004");
11663c7ec6d8SMatt Spinler EXPECT_EQ(fru->failingComponentType(),
11673c7ec6d8SMatt Spinler src::FRUIdentity::maintenanceProc);
11683c7ec6d8SMatt Spinler }
11693c7ec6d8SMatt Spinler
11703c7ec6d8SMatt Spinler // Check callout 7
11713c7ec6d8SMatt Spinler {
11723c7ec6d8SMatt Spinler EXPECT_EQ(callouts[7]->priority(), 'L');
11733c7ec6d8SMatt Spinler EXPECT_EQ(callouts[7]->locationCode(), "");
11743c7ec6d8SMatt Spinler
11753c7ec6d8SMatt Spinler auto& fru = callouts[7]->fruIdentity();
11763c7ec6d8SMatt Spinler EXPECT_EQ(fru->getPN().value(), "AMBTEMP");
11773c7ec6d8SMatt Spinler EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::symbolicFRU);
11783c7ec6d8SMatt Spinler }
11793c7ec6d8SMatt Spinler
11803bdd0110SMatt Spinler // Check that it didn't find any errors
11813bdd0110SMatt Spinler const auto& data = src.getDebugData();
11823bdd0110SMatt Spinler EXPECT_TRUE(data.empty());
11833bdd0110SMatt Spinler }
11843bdd0110SMatt Spinler
TEST_F(SRCTest,JsonBadCalloutsTest)11853bdd0110SMatt Spinler TEST_F(SRCTest, JsonBadCalloutsTest)
11863bdd0110SMatt Spinler {
11873bdd0110SMatt Spinler // The first call will have a Throw in a mock call.
11883bdd0110SMatt Spinler // The second will have a different Throw in a mock call.
11893bdd0110SMatt Spinler // The others have issues with the Priority field.
11903bdd0110SMatt Spinler const auto jsonCallouts = R"(
11913bdd0110SMatt Spinler [
11923bdd0110SMatt Spinler {
11933bdd0110SMatt Spinler "LocationCode": "P0-C1",
11943bdd0110SMatt Spinler "Priority": "H"
11953bdd0110SMatt Spinler },
11963bdd0110SMatt Spinler {
11973bdd0110SMatt Spinler "LocationCode": "P0-C2",
11983bdd0110SMatt Spinler "Priority": "H"
11993bdd0110SMatt Spinler },
12003bdd0110SMatt Spinler {
12013bdd0110SMatt Spinler "LocationCode": "P0-C3"
12023bdd0110SMatt Spinler },
12033bdd0110SMatt Spinler {
12043bdd0110SMatt Spinler "LocationCode": "P0-C4",
12053bdd0110SMatt Spinler "Priority": "X"
12063bdd0110SMatt Spinler }
12073bdd0110SMatt Spinler ]
12083bdd0110SMatt Spinler )"_json;
12093bdd0110SMatt Spinler
12103bdd0110SMatt Spinler message::Entry entry;
12113bdd0110SMatt Spinler entry.src.type = 0xBD;
12123bdd0110SMatt Spinler entry.src.reasonCode = 0xABCD;
12133bdd0110SMatt Spinler entry.subsystem = 0x42;
12143bdd0110SMatt Spinler
12153bdd0110SMatt Spinler AdditionalData ad;
12163bdd0110SMatt Spinler NiceMock<MockDataInterface> dataIface;
12173bdd0110SMatt Spinler
12183bdd0110SMatt Spinler // Callout 0 mock calls
12193bdd0110SMatt Spinler // Expand location code will fail, so the unexpanded location
12203bdd0110SMatt Spinler // code should show up in the callout instead.
12213bdd0110SMatt Spinler {
12223bdd0110SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P0-C1", 0))
12233bdd0110SMatt Spinler .WillOnce(Throw(std::runtime_error("Fail")));
12243bdd0110SMatt Spinler
12253bdd0110SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C1", 0, false))
12263bdd0110SMatt Spinler .Times(1)
1227bad056beSMatt Spinler .WillOnce(Return(std::vector<std::string>{
1228bad056beSMatt Spinler "/inv/system/chassis/motherboard/bmc"}));
12293bdd0110SMatt Spinler EXPECT_CALL(
12303bdd0110SMatt Spinler dataIface,
12313bdd0110SMatt Spinler getHWCalloutFields("/inv/system/chassis/motherboard/bmc", _, _, _))
12323bdd0110SMatt Spinler .Times(1)
12333bdd0110SMatt Spinler .WillOnce(DoAll(SetArgReferee<1>("1234567"),
12343bdd0110SMatt Spinler SetArgReferee<2>("CCCC"),
12353bdd0110SMatt Spinler SetArgReferee<3>("123456789ABC")));
12363bdd0110SMatt Spinler }
12373bdd0110SMatt Spinler
12383bdd0110SMatt Spinler // Callout 1 mock calls
12393bdd0110SMatt Spinler // getInventoryFromLocCode will fail
12403bdd0110SMatt Spinler {
12413bdd0110SMatt Spinler EXPECT_CALL(dataIface, expandLocationCode("P0-C2", 0))
12423bdd0110SMatt Spinler .Times(1)
12433bdd0110SMatt Spinler .WillOnce(Return("UXXX-P0-C2"));
12443bdd0110SMatt Spinler
12453bdd0110SMatt Spinler EXPECT_CALL(dataIface, getInventoryFromLocCode("P0-C2", 0, false))
12463bdd0110SMatt Spinler .Times(1)
12473bdd0110SMatt Spinler .WillOnce(Throw(std::runtime_error("Fail")));
12483bdd0110SMatt Spinler }
12493bdd0110SMatt Spinler
12503bdd0110SMatt Spinler SRC src{entry, ad, jsonCallouts, dataIface};
12513bdd0110SMatt Spinler
12523bdd0110SMatt Spinler ASSERT_TRUE(src.callouts());
12533bdd0110SMatt Spinler
12543bdd0110SMatt Spinler const auto& callouts = src.callouts()->callouts();
12553bdd0110SMatt Spinler
12563bdd0110SMatt Spinler // Only the first callout was successful
12573bdd0110SMatt Spinler ASSERT_EQ(callouts.size(), 1);
12583bdd0110SMatt Spinler
12593bdd0110SMatt Spinler {
12603bdd0110SMatt Spinler EXPECT_EQ(callouts[0]->priority(), 'H');
12613bdd0110SMatt Spinler EXPECT_EQ(callouts[0]->locationCode(), "P0-C1");
12623bdd0110SMatt Spinler
12633bdd0110SMatt Spinler auto& fru = callouts[0]->fruIdentity();
12643bdd0110SMatt Spinler EXPECT_EQ(fru->getPN().value(), "1234567");
12653bdd0110SMatt Spinler EXPECT_EQ(fru->getCCIN().value(), "CCCC");
12663bdd0110SMatt Spinler EXPECT_EQ(fru->getSN().value(), "123456789ABC");
12673bdd0110SMatt Spinler EXPECT_EQ(fru->failingComponentType(), src::FRUIdentity::hardwareFRU);
12683bdd0110SMatt Spinler }
12693bdd0110SMatt Spinler
12703bdd0110SMatt Spinler const auto& data = src.getDebugData();
12713bdd0110SMatt Spinler ASSERT_EQ(data.size(), 4);
12723bdd0110SMatt Spinler EXPECT_STREQ(data[0].c_str(), "Unable to expand location code P0-C1: Fail");
12733bdd0110SMatt Spinler EXPECT_STREQ(data[1].c_str(),
12743bdd0110SMatt Spinler "Failed extracting callout data from JSON: Unable to "
12753bdd0110SMatt Spinler "get inventory path from location code: P0-C2: Fail");
12763bdd0110SMatt Spinler EXPECT_STREQ(data[2].c_str(),
12773bdd0110SMatt Spinler "Failed extracting callout data from JSON: "
12783bdd0110SMatt Spinler "[json.exception.out_of_range.403] key 'Priority' not found");
12793bdd0110SMatt Spinler EXPECT_STREQ(data[3].c_str(),
12803bdd0110SMatt Spinler "Failed extracting callout data from JSON: Invalid "
12813bdd0110SMatt Spinler "priority 'X' found in JSON callout");
12823bdd0110SMatt Spinler }
128353ef1552SMiguel Gomez
128453ef1552SMiguel Gomez // Test that an inventory path callout can have
128553ef1552SMiguel Gomez // a different priority than H.
TEST_F(SRCTest,InventoryCalloutTestPriority)128653ef1552SMiguel Gomez TEST_F(SRCTest, InventoryCalloutTestPriority)
128753ef1552SMiguel Gomez {
128853ef1552SMiguel Gomez message::Entry entry;
128953ef1552SMiguel Gomez entry.src.type = 0xBD;
129053ef1552SMiguel Gomez entry.src.reasonCode = 0xABCD;
129153ef1552SMiguel Gomez entry.subsystem = 0x42;
129253ef1552SMiguel Gomez
129353ef1552SMiguel Gomez std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard",
129453ef1552SMiguel Gomez "CALLOUT_PRIORITY=M"};
129553ef1552SMiguel Gomez AdditionalData ad{adData};
129653ef1552SMiguel Gomez NiceMock<MockDataInterface> dataIface;
129753ef1552SMiguel Gomez
129853ef1552SMiguel Gomez EXPECT_CALL(dataIface, getLocationCode("motherboard"))
129953ef1552SMiguel Gomez .WillOnce(Return("UTMS-P1"));
130053ef1552SMiguel Gomez
130153ef1552SMiguel Gomez EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
130253ef1552SMiguel Gomez .Times(1)
130353ef1552SMiguel Gomez .WillOnce(DoAll(SetArgReferee<1>("1234567"), SetArgReferee<2>("CCCC"),
130453ef1552SMiguel Gomez SetArgReferee<3>("123456789ABC")));
130553ef1552SMiguel Gomez
130653ef1552SMiguel Gomez SRC src{entry, ad, dataIface};
130753ef1552SMiguel Gomez EXPECT_TRUE(src.valid());
130853ef1552SMiguel Gomez
130953ef1552SMiguel Gomez ASSERT_TRUE(src.callouts());
131053ef1552SMiguel Gomez
131153ef1552SMiguel Gomez EXPECT_EQ(src.callouts()->callouts().size(), 1);
131253ef1552SMiguel Gomez
131353ef1552SMiguel Gomez auto& callout = src.callouts()->callouts().front();
131453ef1552SMiguel Gomez
131553ef1552SMiguel Gomez EXPECT_EQ(callout->locationCode(), "UTMS-P1");
131653ef1552SMiguel Gomez EXPECT_EQ(callout->priority(), 'M');
131753ef1552SMiguel Gomez }
13189d43a727SSumit Kumar
13199d43a727SSumit Kumar // Test for bmc & platform dump status bits
TEST_F(SRCTest,DumpStatusBitsCheck)13209d43a727SSumit Kumar TEST_F(SRCTest, DumpStatusBitsCheck)
13219d43a727SSumit Kumar {
13229d43a727SSumit Kumar message::Entry entry;
13239d43a727SSumit Kumar entry.src.type = 0xBD;
13249d43a727SSumit Kumar entry.src.reasonCode = 0xABCD;
13259d43a727SSumit Kumar entry.subsystem = 0x42;
13269d43a727SSumit Kumar
13279d43a727SSumit Kumar AdditionalData ad;
13289d43a727SSumit Kumar NiceMock<MockDataInterface> dataIface;
13299d43a727SSumit Kumar std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
13309d43a727SSumit Kumar "system/entry"};
13319d43a727SSumit Kumar
13329d43a727SSumit Kumar {
13339d43a727SSumit Kumar EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
13349d43a727SSumit Kumar .WillOnce(Return(std::vector<bool>{true, false, false}));
13359d43a727SSumit Kumar
13369d43a727SSumit Kumar SRC src{entry, ad, dataIface};
13379d43a727SSumit Kumar EXPECT_TRUE(src.valid());
13389d43a727SSumit Kumar
13399d43a727SSumit Kumar const auto& hexwords = src.hexwordData();
13409d43a727SSumit Kumar EXPECT_EQ(0x00080055, hexwords[0]);
13419d43a727SSumit Kumar }
13429d43a727SSumit Kumar
13439d43a727SSumit Kumar {
13449d43a727SSumit Kumar EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
13459d43a727SSumit Kumar .WillOnce(Return(std::vector<bool>{false, true, false}));
13469d43a727SSumit Kumar
13479d43a727SSumit Kumar SRC src{entry, ad, dataIface};
13489d43a727SSumit Kumar EXPECT_TRUE(src.valid());
13499d43a727SSumit Kumar
13509d43a727SSumit Kumar const auto& hexwords = src.hexwordData();
13519d43a727SSumit Kumar EXPECT_EQ(0x00000255, hexwords[0]);
13529d43a727SSumit Kumar }
13539d43a727SSumit Kumar
13549d43a727SSumit Kumar {
13559d43a727SSumit Kumar EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
13569d43a727SSumit Kumar .WillOnce(Return(std::vector<bool>{false, false, true}));
13579d43a727SSumit Kumar
13589d43a727SSumit Kumar SRC src{entry, ad, dataIface};
13599d43a727SSumit Kumar EXPECT_TRUE(src.valid());
13609d43a727SSumit Kumar
13619d43a727SSumit Kumar const auto& hexwords = src.hexwordData();
13629d43a727SSumit Kumar EXPECT_EQ(0x00000455, hexwords[0]);
13639d43a727SSumit Kumar }
13649d43a727SSumit Kumar
13659d43a727SSumit Kumar {
13669d43a727SSumit Kumar EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
13679d43a727SSumit Kumar .WillOnce(Return(std::vector<bool>{true, true, true}));
13689d43a727SSumit Kumar
13699d43a727SSumit Kumar SRC src{entry, ad, dataIface};
13709d43a727SSumit Kumar EXPECT_TRUE(src.valid());
13719d43a727SSumit Kumar
13729d43a727SSumit Kumar const auto& hexwords = src.hexwordData();
13739d43a727SSumit Kumar EXPECT_EQ(0x00080655, hexwords[0]);
13749d43a727SSumit Kumar }
13759d43a727SSumit Kumar }
137650bfa69aSSumit Kumar
137750bfa69aSSumit Kumar // Test SRC with additional data - PEL_SUBSYSTEM
TEST_F(SRCTest,TestPELSubsystem)137850bfa69aSSumit Kumar TEST_F(SRCTest, TestPELSubsystem)
137950bfa69aSSumit Kumar {
138050bfa69aSSumit Kumar message::Entry entry;
138150bfa69aSSumit Kumar entry.src.type = 0xBD;
138250bfa69aSSumit Kumar entry.src.reasonCode = 0xABCD;
138350bfa69aSSumit Kumar entry.subsystem = 0x42;
138450bfa69aSSumit Kumar
138550bfa69aSSumit Kumar // Values for the SRC words pointed to above
138650bfa69aSSumit Kumar std::vector<std::string> adData{"PEL_SUBSYSTEM=0x20"};
138750bfa69aSSumit Kumar AdditionalData ad{adData};
138850bfa69aSSumit Kumar NiceMock<MockDataInterface> dataIface;
138950bfa69aSSumit Kumar
139050bfa69aSSumit Kumar EXPECT_CALL(dataIface, getMotherboardCCIN).WillOnce(Return("ABCD"));
139150bfa69aSSumit Kumar
139250bfa69aSSumit Kumar SRC src{entry, ad, dataIface};
139350bfa69aSSumit Kumar
139450bfa69aSSumit Kumar EXPECT_TRUE(src.valid());
139550bfa69aSSumit Kumar
139650bfa69aSSumit Kumar EXPECT_EQ(src.asciiString(), "BD20ABCD ");
139750bfa69aSSumit Kumar }
1398875b6c7bSVijay Lobo
setAsciiString(std::vector<uint8_t> & src,const std::string & value)1399875b6c7bSVijay Lobo void setAsciiString(std::vector<uint8_t>& src, const std::string& value)
1400875b6c7bSVijay Lobo {
1401875b6c7bSVijay Lobo assert(40 + value.size() <= src.size());
1402875b6c7bSVijay Lobo
1403875b6c7bSVijay Lobo for (size_t i = 0; i < value.size(); i++)
1404875b6c7bSVijay Lobo {
1405875b6c7bSVijay Lobo src[40 + i] = value[i];
1406875b6c7bSVijay Lobo }
1407875b6c7bSVijay Lobo }
1408875b6c7bSVijay Lobo
TEST_F(SRCTest,TestGetProgressCode)1409875b6c7bSVijay Lobo TEST_F(SRCTest, TestGetProgressCode)
1410875b6c7bSVijay Lobo {
1411875b6c7bSVijay Lobo {
1412875b6c7bSVijay Lobo // A real SRC with CC009184
1413875b6c7bSVijay Lobo std::vector<uint8_t> src{
1414875b6c7bSVijay Lobo 2, 8, 0, 9, 0, 0, 0, 72, 0, 0, 0, 224, 0, 0, 0,
1415875b6c7bSVijay Lobo 0, 204, 0, 145, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1416875b6c7bSVijay Lobo 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 48, 48, 57,
1417875b6c7bSVijay Lobo 49, 56, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1418875b6c7bSVijay Lobo 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
1419875b6c7bSVijay Lobo
1420875b6c7bSVijay Lobo EXPECT_EQ(SRC::getProgressCode(src), 0xCC009184);
1421875b6c7bSVijay Lobo }
1422875b6c7bSVijay Lobo
1423875b6c7bSVijay Lobo {
1424875b6c7bSVijay Lobo // A real SRC with STANDBY
1425875b6c7bSVijay Lobo std::vector<uint8_t> src{
1426875b6c7bSVijay Lobo 2, 0, 0, 1, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0,
1427875b6c7bSVijay Lobo 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1428875b6c7bSVijay Lobo 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 84, 65, 78, 68,
1429875b6c7bSVijay Lobo 66, 89, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1430875b6c7bSVijay Lobo 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
1431875b6c7bSVijay Lobo
1432875b6c7bSVijay Lobo EXPECT_EQ(SRC::getProgressCode(src), 0);
1433875b6c7bSVijay Lobo }
1434875b6c7bSVijay Lobo
1435875b6c7bSVijay Lobo {
1436875b6c7bSVijay Lobo // A real SRC with CC009184, but 1 byte too short
1437875b6c7bSVijay Lobo std::vector<uint8_t> src{
1438875b6c7bSVijay Lobo 2, 8, 0, 9, 0, 0, 0, 72, 0, 0, 0, 224, 0, 0, 0,
1439875b6c7bSVijay Lobo 0, 204, 0, 145, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1440875b6c7bSVijay Lobo 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 48, 48, 57,
1441875b6c7bSVijay Lobo 49, 56, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1442875b6c7bSVijay Lobo 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32};
1443875b6c7bSVijay Lobo src.resize(71);
1444875b6c7bSVijay Lobo EXPECT_EQ(SRC::getProgressCode(src), 0);
1445875b6c7bSVijay Lobo }
1446875b6c7bSVijay Lobo
1447875b6c7bSVijay Lobo {
1448875b6c7bSVijay Lobo // A few different ones
1449875b6c7bSVijay Lobo const std::map<std::string, uint32_t> progressCodes{
1450875b6c7bSVijay Lobo {"12345678", 0x12345678}, {"ABCDEF00", 0xABCDEF00},
1451875b6c7bSVijay Lobo {"abcdef00", 0xABCDEF00}, {"X1234567", 0},
1452875b6c7bSVijay Lobo {"1234567X", 0}, {"1 ", 0}};
1453875b6c7bSVijay Lobo
1454875b6c7bSVijay Lobo std::vector<uint8_t> src(72, 0x0);
1455875b6c7bSVijay Lobo
1456875b6c7bSVijay Lobo for (const auto& [code, expected] : progressCodes)
1457875b6c7bSVijay Lobo {
1458875b6c7bSVijay Lobo setAsciiString(src, code);
1459875b6c7bSVijay Lobo EXPECT_EQ(SRC::getProgressCode(src), expected);
1460875b6c7bSVijay Lobo }
1461875b6c7bSVijay Lobo
1462875b6c7bSVijay Lobo // empty
1463875b6c7bSVijay Lobo src.clear();
1464875b6c7bSVijay Lobo EXPECT_EQ(SRC::getProgressCode(src), 0);
1465875b6c7bSVijay Lobo }
1466875b6c7bSVijay Lobo }
1467875b6c7bSVijay Lobo
1468875b6c7bSVijay Lobo // Test progress is in right SRC hex data field
TEST_F(SRCTest,TestProgressCodeField)1469875b6c7bSVijay Lobo TEST_F(SRCTest, TestProgressCodeField)
1470875b6c7bSVijay Lobo {
1471875b6c7bSVijay Lobo message::Entry entry;
1472875b6c7bSVijay Lobo entry.src.type = 0xBD;
1473875b6c7bSVijay Lobo entry.src.reasonCode = 0xABCD;
1474875b6c7bSVijay Lobo entry.subsystem = 0x42;
1475875b6c7bSVijay Lobo
1476875b6c7bSVijay Lobo AdditionalData ad;
1477875b6c7bSVijay Lobo NiceMock<MockDataInterface> dataIface;
1478875b6c7bSVijay Lobo EXPECT_CALL(dataIface, getRawProgressSRC())
1479875b6c7bSVijay Lobo .WillOnce(Return(std::vector<uint8_t>{
1480875b6c7bSVijay Lobo 2, 8, 0, 9, 0, 0, 0, 72, 0, 0, 0, 224, 0, 0, 0,
1481875b6c7bSVijay Lobo 0, 204, 0, 145, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1482875b6c7bSVijay Lobo 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 67, 48, 48, 57,
1483875b6c7bSVijay Lobo 49, 56, 52, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
1484875b6c7bSVijay Lobo 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}));
1485875b6c7bSVijay Lobo
1486875b6c7bSVijay Lobo SRC src{entry, ad, dataIface};
1487875b6c7bSVijay Lobo EXPECT_TRUE(src.valid());
1488875b6c7bSVijay Lobo
1489875b6c7bSVijay Lobo // Verify that the hex vlue is set at the right hexword
1490875b6c7bSVijay Lobo EXPECT_EQ(src.hexwordData()[2], 0xCC009184);
1491875b6c7bSVijay Lobo }
1492