openpower-pels: only fail on hw callouts

After further discussion with the IBM service and manufacturing team, it
was determined that firmware should only be automatically going to
Quiesce and preventing the system boot in QuiesceOnError mode when the
PEL has a hardware callout present (vs. any type of callout).

Tested:
- New unit test case
- Verified that an unrecoverable PEL with only a symbolic FRU and a
  maintenance procedure callout did not trigger the Quiesce logic
- Verified that a BMC log with a HW callout still triggers the Quiesce
  logic
- Verified a boot in simulation with Quiesce enabled

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I8912d59fd69b699c7da5a44da887cce4e987f6d2
diff --git a/test/openpower-pels/pel_test.cpp b/test/openpower-pels/pel_test.cpp
index 322d0ca..352e0ed 100644
--- a/test/openpower-pels/pel_test.cpp
+++ b/test/openpower-pels/pel_test.cpp
@@ -209,7 +209,7 @@
     EXPECT_EQ(mtmsCount, 1);
     EXPECT_EQ(euhCount, 1);
     EXPECT_EQ(udCount, 2); // AD section and sysInfo section
-    ASSERT_FALSE(pel.isCalloutPresent());
+    ASSERT_FALSE(pel.isHwCalloutPresent());
 
     {
         // The same thing, but without the action flags specified
@@ -894,7 +894,7 @@
         ASSERT_TRUE(pel.primarySRC().value()->callouts());
         auto& callouts = pel.primarySRC().value()->callouts()->callouts();
         ASSERT_EQ(callouts.size(), 1);
-        ASSERT_TRUE(pel.isCalloutPresent());
+        ASSERT_TRUE(pel.isHwCalloutPresent());
 
         EXPECT_EQ(callouts[0]->priority(), 'H');
         EXPECT_EQ(callouts[0]->locationCode(), "UXXX-P1");
@@ -1031,6 +1031,7 @@
     ASSERT_TRUE(pel.primarySRC().value()->callouts());
     const auto& callouts = pel.primarySRC().value()->callouts()->callouts();
     ASSERT_EQ(callouts.size(), 2);
+    ASSERT_TRUE(pel.isHwCalloutPresent());
 
     {
         EXPECT_EQ(callouts[0]->priority(), 'H');
@@ -1053,3 +1054,62 @@
     }
     fs::remove_all(dir);
 }
+
+// Test PELs with symblic FRU callout.
+TEST_F(PELTest, CreateWithJSONSymblicCalloutTest)
+{
+    PelFFDCfile ffdcFile;
+    ffdcFile.format = UserDataFormat::json;
+    ffdcFile.subType = 0xCA; // Callout JSON
+    ffdcFile.version = 1;
+
+    // Write these callouts to a JSON file and pass it into
+    // the PEL as an FFDC file.
+    auto inputJSON = R"([
+        {
+            "Priority": "M",
+            "Procedure": "SVCDOCS"
+        }
+    ])"_json;
+
+    auto s = inputJSON.dump();
+    std::vector<uint8_t> data{s.begin(), s.end()};
+    auto dir = makeTempDir();
+    ffdcFile.fd = writeFileAndGetFD(dir, data);
+
+    PelFFDC ffdc;
+    ffdc.push_back(std::move(ffdcFile));
+
+    AdditionalData ad;
+    NiceMock<MockDataInterface> dataIface;
+
+    std::vector<std::string> dumpType{"bmc/entry", "resource/entry",
+                                      "system/entry"};
+    EXPECT_CALL(dataIface, checkDumpStatus(dumpType))
+        .WillRepeatedly(Return(std::vector<bool>{false, false, false}));
+
+    message::Entry regEntry;
+    regEntry.name = "test";
+    regEntry.subsystem = 5;
+    regEntry.actionFlags = 0xC000;
+    regEntry.src.type = 0xBD;
+    regEntry.src.reasonCode = 0x1234;
+
+    PEL pel{regEntry, 42,   5,        phosphor::logging::Entry::Level::Error,
+            ad,       ffdc, dataIface};
+
+    ASSERT_TRUE(pel.valid());
+    ASSERT_TRUE(pel.primarySRC().value()->callouts());
+    const auto& callouts = pel.primarySRC().value()->callouts()->callouts();
+    ASSERT_EQ(callouts.size(), 1);
+    ASSERT_FALSE(pel.isHwCalloutPresent());
+
+    {
+        EXPECT_EQ(callouts[0]->priority(), 'M');
+        EXPECT_EQ(callouts[0]->locationCode(), "");
+
+        auto& fru = callouts[0]->fruIdentity();
+        EXPECT_EQ(fru->getMaintProc().value(), "SVCDOCS");
+    }
+    fs::remove_all(dir);
+}