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/validate-regulators-config_tests.cpp b/phosphor-regulators/test/validate-regulators-config_tests.cpp
index e6b84ec..92aff99 100644
--- a/phosphor-regulators/test/validate-regulators-config_tests.cpp
+++ b/phosphor-regulators/test/validate-regulators-config_tests.cpp
@@ -652,6 +652,14 @@
         json configFile = compareVpdFile;
         EXPECT_JSON_VALID(configFile);
     }
+    // Valid, using byte_values.
+    {
+        json configFile = compareVpdFile;
+        configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
+        configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
+            "0x01", "0x02"};
+        EXPECT_JSON_VALID(configFile);
+    }
 
     // Invalid: no FRU property.
     {
@@ -694,14 +702,14 @@
     }
 
     // Invalid: property keyword is not "CCIN", "Manufacturer", "Model",
-    // "PartNumber"
+    // "PartNumber", "HW"
     {
         json configFile = compareVpdFile;
         configFile["rules"][0]["actions"][1]["compare_vpd"]["keyword"] =
             "Number";
         EXPECT_JSON_INVALID(configFile, "Validation failed.",
                             "'Number' is not one of ['CCIN', "
-                            "'Manufacturer', 'Model', 'PartNumber']");
+                            "'Manufacturer', 'Model', 'PartNumber', 'HW']");
     }
 
     // Invalid: property value wrong type.
@@ -711,6 +719,39 @@
         EXPECT_JSON_INVALID(configFile, "Validation failed.",
                             "1 is not of type 'string'");
     }
+
+    // Invalid: property byte_values has wrong type
+    {
+        json configFile = compareVpdFile;
+        configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
+        configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
+            "0x50";
+        EXPECT_JSON_INVALID(configFile, "Validation failed.",
+                            "'0x50' is not of type 'array'");
+    }
+
+    // Invalid: property byte_values is empty
+    {
+        json configFile = compareVpdFile;
+        configFile["rules"][0]["actions"][1]["compare_vpd"].erase("value");
+        configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] =
+            json::array();
+        EXPECT_JSON_INVALID(configFile, "Validation failed.",
+                            "[] is too short");
+    }
+
+    // Invalid: properties byte_values and value both exist
+    {
+        json configFile = compareVpdFile;
+        configFile["rules"][0]["actions"][1]["compare_vpd"]["byte_values"] = {
+            "0x01", "0x02"};
+        EXPECT_JSON_INVALID(
+            configFile, "Validation failed.",
+            "{'byte_values': ['0x01', '0x02'], 'fru': "
+            "'system/chassis/motherboard/regulator2', 'keyword': 'CCIN', "
+            "'value': '2D35'} is valid under each of {'required': "
+            "['byte_values']}, {'required': ['value']}");
+    }
 }
 TEST(ValidateRegulatorsConfigTest, ConfigFile)
 {