PEL: Add getLocationCode call to inv callout

Instead of getting the location code, PN, SN, and CCIN all in one
function call, split getting the location code into its own function.
This way, if there is a location code but not the VPD fields, we can
still have the location code in the callout.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I02f1b18319c34fffce79ad31da74e2114ceb5c95
diff --git a/test/openpower-pels/mocks.hpp b/test/openpower-pels/mocks.hpp
index c003dd8..1fd679f 100644
--- a/test/openpower-pels/mocks.hpp
+++ b/test/openpower-pels/mocks.hpp
@@ -30,10 +30,11 @@
     MOCK_METHOD(std::string, getHostState, (), (const override));
     MOCK_METHOD(std::string, getMotherboardCCIN, (), (const override));
     MOCK_METHOD(void, getHWCalloutFields,
-                (const std::string&, std::string&, std::string&, std::string&,
-                 std::string&),
+                (const std::string&, std::string&, std::string&, std::string&),
                 (const override));
     MOCK_METHOD(std::string, getSystemType, (), (const override));
+    MOCK_METHOD(std::string, getLocationCode, (const std::string&),
+                (const override));
 
     void changeHostState(bool newState)
     {
diff --git a/test/openpower-pels/src_test.cpp b/test/openpower-pels/src_test.cpp
index 9342050..e9abb8e 100644
--- a/test/openpower-pels/src_test.cpp
+++ b/test/openpower-pels/src_test.cpp
@@ -329,11 +329,13 @@
     AdditionalData ad{adData};
     NiceMock<MockDataInterface> dataIface;
 
-    EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _, _))
+    EXPECT_CALL(dataIface, getLocationCode("motherboard"))
+        .WillOnce(Return("UTMS-P1"));
+
+    EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
         .Times(1)
-        .WillOnce(DoAll(SetArgReferee<1>("UTMS-P1"),
-                        SetArgReferee<2>("1234567"), SetArgReferee<3>("CCCC"),
-                        SetArgReferee<4>("123456789ABC")));
+        .WillOnce(DoAll(SetArgReferee<1>("1234567"), SetArgReferee<2>("CCCC"),
+                        SetArgReferee<3>("123456789ABC")));
 
     SRC src{entry, ad, dataIface};
     EXPECT_TRUE(src.valid());
@@ -364,8 +366,62 @@
     EXPECT_EQ(src.callouts()->callouts().size(), 1);
 }
 
-// Test that when the FRU fields can't be obtained that
+// Test that when the location code can't be obtained that
 // a procedure callout is used.
+TEST_F(SRCTest, InventoryCalloutNoLocCodeTest)
+{
+    message::Entry entry;
+    entry.src.type = 0xBD;
+    entry.src.reasonCode = 0xABCD;
+    entry.subsystem = 0x42;
+    entry.src.powerFault = false;
+
+    std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard"};
+    AdditionalData ad{adData};
+    NiceMock<MockDataInterface> dataIface;
+
+    auto func = []() {
+        throw sdbusplus::exception::SdBusError(5, "Error");
+        return std::string{};
+    };
+
+    EXPECT_CALL(dataIface, getLocationCode("motherboard"))
+        .Times(1)
+        .WillOnce(InvokeWithoutArgs(func));
+
+    EXPECT_CALL(dataIface, getHWCalloutFields(_, _, _, _)).Times(0);
+
+    SRC src{entry, ad, dataIface};
+    EXPECT_TRUE(src.valid());
+
+    ASSERT_TRUE(src.callouts());
+
+    EXPECT_EQ(src.callouts()->callouts().size(), 1);
+
+    auto& callout = src.callouts()->callouts().front();
+    EXPECT_EQ(callout->locationCodeSize(), 0);
+
+    auto& fru = callout->fruIdentity();
+
+    EXPECT_EQ(fru->getMaintProc().value(), "BMCSP01");
+    EXPECT_FALSE(fru->getPN());
+    EXPECT_FALSE(fru->getSN());
+    EXPECT_FALSE(fru->getCCIN());
+
+    // flatten and unflatten
+    std::vector<uint8_t> data;
+    Stream stream{data};
+    src.flatten(stream);
+
+    stream.offset(0);
+    SRC newSRC{stream};
+    EXPECT_TRUE(newSRC.valid());
+    ASSERT_TRUE(src.callouts());
+    EXPECT_EQ(src.callouts()->callouts().size(), 1);
+}
+
+// Test that when the VPD can't be obtained that
+// a callout is still created.
 TEST_F(SRCTest, InventoryCalloutNoVPDTest)
 {
     message::Entry entry;
@@ -378,28 +434,31 @@
     AdditionalData ad{adData};
     NiceMock<MockDataInterface> dataIface;
 
+    EXPECT_CALL(dataIface, getLocationCode("motherboard"))
+        .Times(1)
+        .WillOnce(Return("UTMS-P10"));
+
     auto func = []() { throw sdbusplus::exception::SdBusError(5, "Error"); };
 
-    EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _, _))
+    EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
         .Times(1)
         .WillOnce(InvokeWithoutArgs(func));
 
     SRC src{entry, ad, dataIface};
     EXPECT_TRUE(src.valid());
-
     ASSERT_TRUE(src.callouts());
-
     EXPECT_EQ(src.callouts()->callouts().size(), 1);
 
     auto& callout = src.callouts()->callouts().front();
+    EXPECT_EQ(callout->locationCode(), "UTMS-P10");
 
     auto& fru = callout->fruIdentity();
 
-    EXPECT_EQ(fru->getMaintProc().value(), "BMCSP01");
-    EXPECT_FALSE(fru->getPN());
-    EXPECT_FALSE(fru->getSN());
-    EXPECT_FALSE(fru->getCCIN());
-    //
+    EXPECT_EQ(fru->getPN(), "");
+    EXPECT_EQ(fru->getCCIN(), "");
+    EXPECT_EQ(fru->getSN(), "");
+    EXPECT_FALSE(fru->getMaintProc());
+
     // flatten and unflatten
     std::vector<uint8_t> data;
     Stream stream{data};