PEL: Add symbolic FRU support to FRUIdentity

A symbolic FRU is a FRU where the part is known, but the part number is
not available for it.  A trusted symbolic FRU adds the requirement that
the location code is known to be correct so it can be used for lighting
LEDs and FRU replacement.

The symbolic FRU name shares the same field as the part number.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I2fa936d9d7235c5cff245effcdb9d445aefffe23
diff --git a/test/openpower-pels/fru_identity_test.cpp b/test/openpower-pels/fru_identity_test.cpp
index e31ffad..b13bf3f 100644
--- a/test/openpower-pels/fru_identity_test.cpp
+++ b/test/openpower-pels/fru_identity_test.cpp
@@ -202,3 +202,65 @@
         EXPECT_FALSE(fru.getSN());
     }
 }
+
+// Test the constructor that takes in a symbolic FRU.
+TEST(FRUIdentityTest, CreateSymbolicFRUCalloutTest)
+{
+    // Symbolic FRU (not trusted)
+    {
+        FRUIdentity fru{"service_docs", false};
+
+        EXPECT_EQ(fru.flattenedSize(), 12);
+        EXPECT_EQ(fru.type(), 0x4944);
+        EXPECT_EQ(fru.failingComponentType(), FRUIdentity::symbolicFRU);
+        EXPECT_EQ(fru.getPN().value(), "SVCDOCS");
+        EXPECT_FALSE(fru.getMaintProc());
+        EXPECT_FALSE(fru.getCCIN());
+        EXPECT_FALSE(fru.getSN());
+
+        // Flatten and unflatten, then compare again
+        std::vector<uint8_t> data;
+        Stream stream{data};
+        fru.flatten(stream);
+
+        EXPECT_EQ(data.size(), fru.flattenedSize());
+
+        stream.offset(0);
+        FRUIdentity newFRU{stream};
+
+        EXPECT_EQ(newFRU.flattenedSize(), 12);
+        EXPECT_EQ(newFRU.type(), 0x4944);
+        EXPECT_EQ(newFRU.failingComponentType(), FRUIdentity::symbolicFRU);
+        EXPECT_EQ(newFRU.getPN().value(), "SVCDOCS");
+        EXPECT_FALSE(newFRU.getMaintProc());
+        EXPECT_FALSE(newFRU.getCCIN());
+        EXPECT_FALSE(newFRU.getSN());
+    }
+
+    // Trusted symbolic FRU
+    {
+        FRUIdentity fru{"service_docs", true};
+
+        EXPECT_EQ(fru.flattenedSize(), 12);
+        EXPECT_EQ(fru.type(), 0x4944);
+        EXPECT_EQ(fru.failingComponentType(),
+                  FRUIdentity::symbolicFRUTrustedLocCode);
+        EXPECT_EQ(fru.getPN().value(), "SVCDOCS");
+        EXPECT_FALSE(fru.getMaintProc());
+        EXPECT_FALSE(fru.getCCIN());
+        EXPECT_FALSE(fru.getSN());
+    }
+
+    // Invalid symbolic FRU
+    {
+        FRUIdentity fru{"garbage", false};
+
+        EXPECT_EQ(fru.flattenedSize(), 12);
+        EXPECT_EQ(fru.type(), 0x4944);
+        EXPECT_EQ(fru.failingComponentType(), FRUIdentity::symbolicFRU);
+        EXPECT_EQ(fru.getPN().value(), "INVALID");
+        EXPECT_FALSE(fru.getMaintProc());
+        EXPECT_FALSE(fru.getCCIN());
+        EXPECT_FALSE(fru.getSN());
+    }
+}