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