Changes in ipmi/test_ipmi_fru_device.robot

Added Following Test Case

	- Read Fru Device configuration
	- Verify Get FRU Inventory Area Info
	- Verify Get FRU Inventory Area Info For Invalid Device Data
	- Verify Get FRU Inventory Area Info For Invalid Data Request
	- Verify IPMI Write FRU Data
	- Verify IPMI Write FRU Data With BMC Reboot

Functions required are defined under lib/bmc_dbus.robot, lib/ipmi_client.robot and lib/utils.py

Request data for fru data present in data/ipmi_raw_cmd_table.py.

Read Fru Device configuration - Validates each ipmi fru device data with corresponding dbus data.

Verify Get FRU Inventory Area Info - Validates fru inventory byte size with ipmi read fru count returned.

Verify Get FRU Inventory Area Info For Invalid Device Data - Validates the response of inventory fru area info command with invalid device id.

Verify Get FRU Inventory Area Info For Invalid Data Request - Validates the response of inventory fru area info command with invalid request data by giving extra bytes.

Verify IPMI Write FRU Data - Verify write fru data with the response returned with read fru data after data is written.

Verify IPMI Write FRU Data With BMC Reboot -  Verify the response of read fru data after the bmc is rebooted once the data is written to the fru device.

Signed-off-by: ganesanb <ganesanb@ami.com>
Change-Id: I2ea51ad51512ecbcc4036e2d2593cafaa40a2d3c
diff --git a/lib/bmc_dbus.robot b/lib/bmc_dbus.robot
new file mode 100644
index 0000000..160fec1
--- /dev/null
+++ b/lib/bmc_dbus.robot
@@ -0,0 +1,83 @@
+*** Settings ***
+Documentation      Implemented keywords to execute DBUS related commands on BMC.
+
+Resource           resource.robot
+Library            OperatingSystem
+Library            Collections
+
+*** Variable ***
+
+${BUSCTL_TREE_COMMAND}                   busctl tree | less
+${BUSCTL_INTROSPECT_COMMAND}             busctl introspect
+@{dbus_uri_list}
+
+*** Keywords ***
+
+Get DBUS URI List From BMC
+    [Documentation]  Get the available DBUS URIs from device tree on BMC.
+    [Arguments]  ${service_name}  ${dbus_url}
+
+    # Return the dbus uris corresponding to the service name provided.
+    # Description of argument(s):
+    #    service_name     Any service uri of the dbus.
+    #                        Eg : xyz.openbmc_project.FruDevice
+    #    dbus_url         Any dbus url of the dbus.
+    #                        Eg : /xyz/openbmc_project/FruDevice
+
+    # Execute dbus tree command
+    ${bmc_response}=  BMC Execute Command  ${BUSCTL_TREE_COMMAND}
+    ${bmc_response}=  Convert To List  ${bmc_response}
+    ${bmc_response_output}=  Get From List  ${bmc_response}  0
+    ${bmc_response_output_list}=  Split String  ${bmc_response_output}  \n\n
+    # Identify the offset of the service name in the response.
+    ${service_name_index_value}=  get_subsequent_value_from_list  ${bmc_response_output_list}  ${service_name}
+    ${service_name_index_value}=  Get From List  ${service_name_index_value}  0
+
+    # Get the service name and its corresponding URI's.
+    ${service_name_with_uri_list}=  Get From List  ${bmc_response_output_list}  ${service_name_index_value}
+    ${service_name_with_uri_list}=  Split String  ${service_name_with_uri_list}  \n
+
+    # Find index of all the uris where the dbus URI matched.
+    ${uri_list_index}=  get_subsequent_value_from_list  ${service_name_with_uri_list}  ${dbus_url}
+    FOR  ${list_index}  IN  @{uri_list_index}
+        # For each index, get the URI and append to list
+        ${dbus_uri}=  Get From List  ${service_name_with_uri_list}  ${list_index}
+        Append To List  ${dbus_uri_list}  ${dbus_uri}
+    END
+
+    [Return]  ${dbus_uri_list[1:]}
+
+
+Fetch DBUS URI List Without Unicode
+    [Documentation]  Gets the list of DBUS URI for the service and returns only sub URIs.
+    [Arguments]  ${dbus_uri_list}
+
+    # Return the dbus uris list without the unicodes.
+    # Description of argument(s):
+    #    dbus_uri_list      List of all the uris for the corresponding service name.
+    #    Example:    Converts "  ├─/xyz/openbmc_project/FruDevice/device_0",
+    #                ...  to '/xyz/openbmc_project/FruDevice/device_0'
+
+    @{dbus_list}=  Create List
+    FOR  ${item}  IN  @{dbus_uri_list}
+        ${item}=  Set Variable  ${item.strip()}
+        ${item}=  return_decoded_string  ${item}
+        Append To List  ${dbus_list}  ${item}
+    END
+
+    [Return]  ${dbus_list}
+
+
+Execute DBUS Introspect Command
+    [Documentation]  Execute the DBUS introspect command and return response.
+    [Arguments]  ${dbus_command}
+
+    # Execute the busctl instrospect command for the service name and dbus uri.
+    # Description of argument(s):
+    #   dbus_command    Command with service name and dbus uri for the fru device.
+    #      Example :    xyz.openbmc_project.FruDevice xyz/openbmc_project/FruDevice/device_0
+
+    ${cmd}=  Catenate  ${BUSCTL_INTROSPECT_COMMAND} ${dbus_command}
+    ${resp}=  BMC Execute Command  ${cmd}
+
+    [Return]  ${resp[0]}
diff --git a/lib/ipmi_client.robot b/lib/ipmi_client.robot
index 5fdd39d..cf2a24a 100755
--- a/lib/ipmi_client.robot
+++ b/lib/ipmi_client.robot
@@ -612,4 +612,35 @@
 
     ${resp}=  Run External IPMI Raw Command  ${ipmi_cmd}  fail_on_err=0
 
-    Should Contain  ${resp}  rsp=${error_code}
\ No newline at end of file
+    Should Contain  ${resp}  rsp=${error_code}
+
+
+Identify Request Data
+    [Documentation]  Convert text from variable declared to request data.
+    [Arguments]  ${string}
+
+    # Convert string to hexadecimal data for each character.
+    # Return the hex data with prefix of 0x as string and list of hex data.
+    # Description of argument(s):
+    #    string             Any string to be converted to hex.
+
+    # Given a string, convert to hexadecimal and prefix with 0x
+    ${hex1}=  Create List
+    ${hex2}=  Create List
+    ${resp_data}=  Split String With Index  ${string}  1
+    FOR  ${data}  IN  @{resp_data}
+        # prefixes 0x by default
+        ${hex_value}=  Evaluate  hex(ord("${data}"))
+        # prefixes string with bytes prefixed 0x by default
+        Append To List  ${hex1}  ${hex_value}
+        # provides only hexadecimal bytes
+        ${hex}=  Evaluate  hex(ord("${data}"))[2:]
+        # provides string with only hexadecimal bytes
+        Append To List  ${hex2}  ${hex}
+    END
+    ${hex1}=  Evaluate  " ".join(${hex1})
+
+    # ${hex1} will contains the data to write for fru in list.
+    # ${hex2} will contains the data to verify fru after write operation completed.
+
+    [Return]  ${hex1}  ${hex2}
\ No newline at end of file
diff --git a/lib/utils.py b/lib/utils.py
index 40bcf83..901c6e0 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -452,3 +452,22 @@
     """
 
     return data.zfill(int(num))
+
+
+def get_subsequent_value_from_list(list, value):
+    r"""
+    returns first index of the element occurrence.
+    """
+
+    index = [list.index(i) for i in list if value in i]
+    return index
+
+
+def return_decoded_string(input):
+    r"""
+    returns decoded string of encoded byte.
+    """
+
+    encoded_string = input.encode('ascii', 'ignore')
+    decoded_string = encoded_string.decode()
+    return decoded_string