regulators: Support a string or vector for VPD

Add a 'byte_values' alternative to the 'value' entry in the compare VPD
action.  This is to support VPD values that are not strings, such as
'HW', a new IBM keyword that describes the version of a piece of
hardware.

To support this, the VPD class now treats all VPD keyword values as
vectors of uint8_ts, including in its data cache.  If a compare VPD
action in the JSON contains a string value, it will be converted to the
vector before the CompareVPDAction class is created.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I3fcabf896f4885feae1b07ee2c3da5929cf8bfa4
diff --git a/phosphor-regulators/test/config_file_parser_tests.cpp b/phosphor-regulators/test/config_file_parser_tests.cpp
index c2cf08e..3249465 100644
--- a/phosphor-regulators/test/config_file_parser_tests.cpp
+++ b/phosphor-regulators/test/config_file_parser_tests.cpp
@@ -1085,7 +1085,7 @@
 
 TEST(ConfigFileParserTests, ParseCompareVPD)
 {
-    // Test where works
+    // Test where works, using "value"
     {
         const json element = R"(
             {
@@ -1099,7 +1099,25 @@
             action->getFRU(),
             "/xyz/openbmc_project/inventory/system/chassis/disk_backplane");
         EXPECT_EQ(action->getKeyword(), "CCIN");
-        EXPECT_EQ(action->getValue(), "2D35");
+        EXPECT_EQ(action->getValue(),
+                  (std::vector<uint8_t>{0x32, 0x44, 0x33, 0x35}));
+    }
+
+    // Test where works, using "byte_values"
+    {
+        const json element = R"(
+            {
+              "fru": "system/chassis/disk_backplane",
+              "keyword": "CCIN",
+              "byte_values": ["0x11", "0x22", "0x33"]
+            }
+        )"_json;
+        std::unique_ptr<CompareVPDAction> action = parseCompareVPD(element);
+        EXPECT_EQ(
+            action->getFRU(),
+            "/xyz/openbmc_project/inventory/system/chassis/disk_backplane");
+        EXPECT_EQ(action->getKeyword(), "CCIN");
+        EXPECT_EQ(action->getValue(), (std::vector<uint8_t>{0x11, 0x22, 0x33}));
     }
 
     // Test where fails: Element is not an object
@@ -1181,7 +1199,28 @@
     }
     catch (const std::invalid_argument& e)
     {
-        EXPECT_STREQ(e.what(), "Required property missing: value");
+        EXPECT_STREQ(e.what(), "Invalid property: Must contain "
+                               "either value or byte_values");
+    }
+
+    // Test where fails: both value and byte_value specified
+    try
+    {
+        const json element = R"(
+            {
+              "fru": "system/chassis/disk_backplane",
+              "keyword": "CCIN",
+              "value": "2D35",
+              "byte_values": [ "0x01", "0x02" ]
+            }
+        )"_json;
+        parseCompareVPD(element);
+        ADD_FAILURE() << "Should not have reached this line.";
+    }
+    catch (const std::invalid_argument& e)
+    {
+        EXPECT_STREQ(e.what(), "Invalid property: Must contain "
+                               "either value or byte_values");
     }
 
     // Test where fails: fru value is invalid
@@ -1237,6 +1276,24 @@
     {
         EXPECT_STREQ(e.what(), "Element is not a string");
     }
+
+    // Test where fails: byte_values is wrong format
+    try
+    {
+        const json element = R"(
+            {
+              "fru": "system/chassis/disk_backplane",
+              "keyword": "CCIN",
+              "byte_values": [1, 2, 3]
+            }
+        )"_json;
+        parseCompareVPD(element);
+        ADD_FAILURE() << "Should not have reached this line.";
+    }
+    catch (const std::invalid_argument& e)
+    {
+        EXPECT_STREQ(e.what(), "Element is not a string");
+    }
 }
 
 TEST(ConfigFileParserTests, ParseConfiguration)