IPZ VPD Parser support

This commit enables the app ibm-read-vpd to read the
IPZ format vpd. To build this app, the application
build must be configured with the "--enable-ibm-parser"
option.

The application populates the Inventory with the parsed
VPD data. The parser relies on a JSON config file
that maps the input VPD file path to the Inventory D-Bus
object that hosts the VPD data as properties.

The JSON file also supplies any additional interfaces
and properties that the D-Bus object should implement.

Argument required to run this application-
ibm-read-vpd --file vpd_file

Tested:

Also tested this on Rainier simulation model and verified that VPD
for FRUs is properly published as properties of D-Bus objects in the
Inventory.

Change-Id: Ic9305f25625adced7f64123589dd083e2679afbb
Signed-off-by: Alpana Kumari <alpankum@in.ibm.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index 4f35b94..05785da 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -3,8 +3,32 @@
 TESTS = $(check_PROGRAMS)
 
 check_PROGRAMS = store_test
+
 store_test_SOURCES = store/store.cpp
 
+check_PROGRAMS += ipz_parser_test
+
+ipz_parser_test_SOURCES = ipz_parser/parser.cpp \
+                          ../impl.cpp
+test_cppflags = \
+	-Igtest \
+	$(GTEST_CPPFLAGS) \
+	$(AM_CPPFLAGS)  \
+	-pthread  \
+	$(PTHREAD_CFLAGS) \
+	$(SDBUSPLUS_CFLAGS)
+
+test_ldflags = \
+	-lgtest_main \
+	-lgtest \
+	-pthread  \
+	$(PTHREAD_LIBS) \
+	$(SDBUSPLUS_LIBS)
+
+ipz_parser_test_CPPFLAGS = $(test_cppflags) -DIPZ_PARSER
+ipz_parser_test_LDFLAGS = $(test_ldflags)
+
+if !IBM_PARSER
 noinst_PROGRAMS = parser_test
 parser_test_SOURCES = \
 	parser/parser.cpp \
@@ -14,3 +38,4 @@
 	../utils.cpp
 parser_test_LDFLAGS = $(SDBUSPLUS_LIBS) $(PHOSPHOR_LOGGING_LIBS)
 parser_test_CXXFLAGS = $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_LOGGING_CFLAGS)
+endif
diff --git a/test/ipz_parser/parser.cpp b/test/ipz_parser/parser.cpp
new file mode 100644
index 0000000..40c60e9
--- /dev/null
+++ b/test/ipz_parser/parser.cpp
@@ -0,0 +1,144 @@
+#include <cassert>
+#include <defines.hpp>
+#include <fstream>
+#include <impl.hpp>
+#include <iterator>
+#include <parser.hpp>
+#include <store.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace openpower::vpd;
+
+TEST(IpzVpdParserApp, vpdGoodPath)
+{
+    // Create a vpd
+    Binary vpd = {
+        0x00, 0x0f, 0x17, 0xba, 0x42, 0xca, 0x82, 0xd7, 0x7b, 0x77, 0x1e, 0x84,
+        0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02,
+        0x30, 0x31, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0xd5, 0x00, 0x37,
+        0x00, 0x4c, 0x00, 0x97, 0x05, 0x13, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x84, 0x48, 0x00, 0x52, 0x54,
+        0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x0e, 0x56, 0x49, 0x4e, 0x49,
+        0xd5, 0x00, 0x52, 0x00, 0x90, 0x00, 0x73, 0x05, 0x24, 0x00, 0x84, 0x8c,
+        0x00, 0x52, 0x54, 0x04, 0x56, 0x49, 0x4e, 0x49, 0x44, 0x52, 0x10, 0x41,
+        0x50, 0x53, 0x53, 0x20, 0x26, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x20, 0x43,
+        0x41, 0x52, 0x44, 0x43, 0x45, 0x01, 0x31, 0x56, 0x5a, 0x02, 0x30, 0x31,
+        0x46, 0x4e, 0x07, 0x30, 0x31, 0x44, 0x48, 0x32, 0x30, 0x30, 0x50, 0x4e,
+        0x07, 0x30, 0x31, 0x44, 0x48, 0x32, 0x30, 0x31, 0x53, 0x4e, 0x0c, 0x59,
+        0x4c, 0x33, 0x30, 0x42, 0x47, 0x37, 0x43, 0x46, 0x30, 0x33, 0x50, 0x43,
+        0x43, 0x04, 0x36, 0x42, 0x36, 0x36, 0x50, 0x52, 0x08, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x45, 0x04, 0x30, 0x30, 0x30, 0x31,
+        0x43, 0x54, 0x04, 0x40, 0xb8, 0x02, 0x03, 0x48, 0x57, 0x02, 0x00, 0x01,
+        0x42, 0x33, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x34, 0x01,
+        0x00, 0x42, 0x37, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x02, 0x00, 0x00, 0x78, 0x84, 0xdc,
+        0x00, 0x52, 0x54, 0x04};
+
+    // call app for this vpd
+    parser::Impl p(std::move(vpd));
+    Store vpdStore = p.run();
+
+    static const std::string record = "VINI";
+    static const std::string keyword = "DR";
+
+    // TODO 2: Move this as an utility to store.hpp
+    std::string dataFound;
+    Parsed st_bin = vpdStore.getVpdMap();
+
+    auto kw = st_bin.find(record);
+    if (st_bin.end() != kw)
+    {
+        auto value = (kw->second).find(keyword);
+        if ((kw->second).end() != value)
+        {
+            dataFound = value->second;
+        }
+    }
+
+    ASSERT_EQ(dataFound, "APSS & TPM  CARD");
+}
+
+TEST(IpzVpdParserApp, vpdBadPathEmptyVPD)
+{
+    Binary vpd = {};
+
+    // VPD is empty
+    parser::Impl p(std::move(vpd));
+
+    // Expecting a throw here
+    EXPECT_THROW(p.run(), std::runtime_error);
+}
+
+TEST(IpzVpdParserApp, vpdBadPathMissingHeader)
+{
+    Binary vpd = {
+        0x00, 0x0f, 0x17, 0xba, 0x42, 0xca, 0x82, 0xd7, 0x7b, 0x77, 0x1e, 0x84,
+        0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02,
+        0x30, 0x31, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0xd5, 0x00, 0x37,
+        0x00, 0x4c, 0x00, 0x97, 0x05, 0x13, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x84, 0x48, 0x00, 0x52, 0x54,
+        0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x0e, 0x56, 0x49, 0x4e, 0x49,
+        0xd5, 0x00, 0x52, 0x00, 0x90, 0x00, 0x73, 0x05, 0x24, 0x00, 0x84, 0x8c,
+        0x00, 0x52, 0x54, 0x04, 0x56, 0x49, 0x4e, 0x49, 0x44, 0x52, 0x10, 0x41,
+        0x50, 0x53, 0x53, 0x20, 0x26, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x20, 0x43,
+        0x41, 0x52, 0x44, 0x43, 0x45, 0x01, 0x31, 0x56, 0x5a, 0x02, 0x30, 0x31,
+        0x46, 0x4e, 0x07, 0x30, 0x31, 0x44, 0x48, 0x32, 0x30, 0x30, 0x50, 0x4e,
+        0x07, 0x30, 0x31, 0x44, 0x48, 0x32, 0x30, 0x31, 0x53, 0x4e, 0x0c, 0x59,
+        0x4c, 0x33, 0x30, 0x42, 0x47, 0x37, 0x43, 0x46, 0x30, 0x33, 0x50, 0x43,
+        0x43, 0x04, 0x36, 0x42, 0x36, 0x36, 0x50, 0x52, 0x08, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x45, 0x04, 0x30, 0x30, 0x30, 0x31,
+        0x43, 0x54, 0x04, 0x40, 0xb8, 0x02, 0x03, 0x48, 0x57, 0x02, 0x00, 0x01,
+        0x42, 0x33, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x34, 0x01,
+        0x00, 0x42, 0x37, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x02, 0x00, 0x00, 0x78, 0x84, 0xdc,
+        0x00, 0x52, 0x54, 0x04};
+
+    // corrupt the VHDR
+    vpd[17] = 0x00;
+
+    parser::Impl p(std::move(vpd));
+
+    // Expecting a throw here
+    EXPECT_THROW(p.run(), std::runtime_error);
+}
+
+TEST(IpzVpdParserApp, vpdBadPathMissingVTOC)
+{
+    Binary vpd = {
+        0x00, 0x0f, 0x17, 0xba, 0x42, 0xca, 0x82, 0xd7, 0x7b, 0x77, 0x1e, 0x84,
+        0x28, 0x00, 0x52, 0x54, 0x04, 0x56, 0x48, 0x44, 0x52, 0x56, 0x44, 0x02,
+        0x30, 0x31, 0x50, 0x54, 0x0e, 0x56, 0x54, 0x4f, 0x43, 0xd5, 0x00, 0x37,
+        0x00, 0x4c, 0x00, 0x97, 0x05, 0x13, 0x00, 0x50, 0x46, 0x08, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x84, 0x48, 0x00, 0x52, 0x54,
+        0x04, 0x56, 0x54, 0x4f, 0x43, 0x50, 0x54, 0x0e, 0x56, 0x49, 0x4e, 0x49,
+        0xd5, 0x00, 0x52, 0x00, 0x90, 0x00, 0x73, 0x05, 0x24, 0x00, 0x84, 0x8c,
+        0x00, 0x52, 0x54, 0x04, 0x56, 0x49, 0x4e, 0x49, 0x44, 0x52, 0x10, 0x41,
+        0x50, 0x53, 0x53, 0x20, 0x26, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x20, 0x43,
+        0x41, 0x52, 0x44, 0x43, 0x45, 0x01, 0x31, 0x56, 0x5a, 0x02, 0x30, 0x31,
+        0x46, 0x4e, 0x07, 0x30, 0x31, 0x44, 0x48, 0x32, 0x30, 0x30, 0x50, 0x4e,
+        0x07, 0x30, 0x31, 0x44, 0x48, 0x32, 0x30, 0x31, 0x53, 0x4e, 0x0c, 0x59,
+        0x4c, 0x33, 0x30, 0x42, 0x47, 0x37, 0x43, 0x46, 0x30, 0x33, 0x50, 0x43,
+        0x43, 0x04, 0x36, 0x42, 0x36, 0x36, 0x50, 0x52, 0x08, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x45, 0x04, 0x30, 0x30, 0x30, 0x31,
+        0x43, 0x54, 0x04, 0x40, 0xb8, 0x02, 0x03, 0x48, 0x57, 0x02, 0x00, 0x01,
+        0x42, 0x33, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x34, 0x01,
+        0x00, 0x42, 0x37, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x50, 0x46, 0x02, 0x00, 0x00, 0x78, 0x84, 0xdc,
+        0x00, 0x52, 0x54, 0x04};
+
+    // corrupt the VTOC
+    vpd[61] = 0x00;
+
+    parser::Impl p(std::move(vpd));
+
+    // Expecting a throw here
+    EXPECT_THROW(p.run(), std::runtime_error);
+}
+
+int main(int argc, char** argv)
+{
+    ::testing::InitGoogleTest(&argc, argv);
+
+    return RUN_ALL_TESTS();
+}