FRU fields validation

Verifying the FRU's properties defined in YAML file for inventory.

Logic:
    1. Find the list of qualified FRU's from inventory.
    2. Iterate the FRU url and extract the fields.
    3. Compare the FRU properties set from system vs the derived
       FRU properties from YAML file (e.g. "data/inventory.py").
    4. Any mismatch would be a failure.

Resolves openbmc/openbmc-test-automation#417

Change-Id: I526c28e957fc8ff9cd46bacfd3ff108728f8550e
Signed-off-by: George Keishing <gkeishin@in.ibm.com>
diff --git a/tests/test_inventory.robot b/tests/test_inventory.robot
index 3c4ac8b..34694c4 100644
--- a/tests/test_inventory.robot
+++ b/tests/test_inventory.robot
@@ -5,6 +5,7 @@
 Resource          ../lib/utils.robot
 Resource          ../lib/state_manager.robot
 Resource          ../lib/openbmc_ffdc.robot
+Library           ../lib/utilities.py
 
 Variables         ../data/variables.py
 Variables         ../data/inventory.py
@@ -105,6 +106,42 @@
     \  Should Be True  ${present}
 
 
+Verify FRU Properties
+    [Documentation]  Verify the FRU properties fields.
+    [Tags]  Verify_FRU_Properties
+    # Example:
+    # A FRU would have "FieldReplaceable" set to boolean 1 and should have
+    # the following entries
+    #  "fru": [
+    #    "FieldReplaceable"
+    #    "BuildDate",
+    #    "Cached"
+    #    "SerialNumber",
+    #    "Version",
+    #    "Model",
+    #    "PrettyName",
+    #    "PartNumber",
+    #    "Present",
+    #    "Manufacturer",
+    # ]
+    # and FRU which doesn't have one of this fields is an error.
+    #   "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm0": {
+    #    "FieldReplaceable": 1,
+    #    "BuildDate": "",
+    #    "Cached": 0,
+    #    "SerialNumber": "0x0300cf4f",
+    #    "Version": "0x00",
+    #    "Model": "M393A1G40EB1-CRC    ",
+    #    "PrettyName": "0x0c",
+    #    "PartNumber": "",
+    #    "Present": 1,
+    #    "Manufacturer": "0xce80"
+    # },
+
+    ${system_list}=  Get Endpoint Paths  ${HOST_INVENTORY_URI}system  *
+    ${fru_list}=  Qualified FRU List  @{system_list}
+    Validate FRU Properties Fields  @{fru_list}
+
 *** Keywords ***
 
 Test Suite Setup
@@ -128,3 +165,56 @@
     Should Be Equal As Strings  ${resp.status_code}  ${HTTP_OK}
     ${jsondata}=  To JSON  ${resp.content}
     [Return]  ${jsondata}
+
+
+Qualified FRU List
+    [Documentation]  Build the list of valid FRUs.
+    [Arguments]  @{system_list}
+    # Description of arguments:
+    # system_list  List of system inventory URLs.
+    # Example:
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm0
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm1
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm2
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm3
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm4
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm5
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm6
+    # /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm7
+
+    ${fru_list}=  Create List
+    :FOR  ${fru_uri}  IN  @{system_list}
+    \  ${is_fru}=  OpenBMC Get Request  ${fru_uri}/attr/FieldReplaceable
+    \  ${status}=  Run Keyword And Return Status  Should Be True  ${is_fru}
+    \  Run Keyword If  '${status}' == '${True}'
+    ...  Append To List  ${fru_list}  ${fru_uri}
+
+    [Return]  ${fru_list}
+
+
+Validate FRU Properties Fields
+    [Documentation]  Compare valid FRUs from system vs expected FRU set.
+    [Arguments]  @{fru_list}
+    # Description of arguments:
+    # fru_list  List of qualified FRU URLs.
+
+    # Build the pre-defined set list from data/inventory.py derived from
+    # a group of YAML files.
+    # Example:
+    # set(['Version', 'PartNumber', 'SerialNumber', 'FieldReplaceable',
+    # 'BuildDate', 'Present', 'Manufacturer', 'PrettyName', 'Cached', 'Model'])
+    ${fru_set}=  List To Set  ${inventory_dict['fru']}
+
+    # Iterate through the FRU's url and compare the set dictionary keys
+    # with the pre-define inventory data.
+    :FOR  ${fru_url_path}  IN  @{fru_list}
+    \  ${fru_field}=  Read Properties  ${fru_url_path}
+    # ------------------------------------------------------------
+    #  ${fru_field.viewkeys()} extracts the list of keys from the
+    #  JSON dictionary as a set.
+    # ------------------------------------------------------------
+    \  Should Be Equal  ${fru_field.viewkeys()}  ${fru_set}
+