Add new SEL test cases

Changes:
    - Added validation for Reserver ID, Most Recent Timestamps,
      Clear SEL and modifications in Add SEL Entry and Reserver ID

Testcases Modified:
          - Verify Reserve SEL
New Testcases:
          - Verify Add SEL Entry For Any Random Sensor
          - Verify IPMI SEL Most Recent Addition Timestamp
          - Verify IPMI SEL Most Recent Erase Timestamp
          - Verify Clear SEL With Invalid Reservation ID
          - Verify Reservation ID Erasure Status
          - Verify Clear SEL After Cold Reset

Verify Add SEL Entry For Any Random Sensor
    - Modified with create SEL by sensor number and type taken i
      from sensor list and sdr get. Verified the result with sel elist last 1

Verify Reserve SEL
    - Added condition to check if the sel entry is empty.

Verify IPMI SEL Most Recent Addition Timestamp
     - Gets Most Recent Addition Timestamp from IPMI Sel Info raw command
       and validate against sel entry date. If no sel entry present, newi
       sel entry will be created and validates the SEL date againt IPMI
       Sel Most Recent Addition Timestamp.

Verify IPMI SEL Most Recent Erase Timestamp
     - Clears the SEL and  validates Most Recent Erase Timestamp from SEL
       Info against bmc current time. Also verifies if Most Recent Addition
       Timestamp is not available.

Verify Clear SEL With Invalid Reservation ID
     - Creates two reservation id, stores first reservation id created and
       tries to clear sel with stored reservation id. Once a new reservationi
       id is created, previous reservation id generated will no longer be valid.

Verify Reservation ID Erasure Status
     - Creates a reservation id, clears the sel using the reservation id created,
       generate a new reservation id, check the erasure status using new reservation id

Verify Clear SEL After Cold Reset
     - Creates a new reservation id, runs cold reset from lanplus, once bmc is booted,
       checks whether the generated reservation id is accessible.

Tested: Run robot ipmi/test_ipmi_sel.robot

Signed-off-by: chithrag <chithrag@ami.com>
Signed-off-by: George Keishing <gkeishin@in.ibm.com>
Change-Id: I3cd71447debaa6ddca05a9d7613e369bea6514b6
Signed-off-by: George Keishing <gkeishin@in.ibm.com>
diff --git a/data/ipmi_raw_cmd_table.py b/data/ipmi_raw_cmd_table.py
index d6e2d33..4433186 100644
--- a/data/ipmi_raw_cmd_table.py
+++ b/data/ipmi_raw_cmd_table.py
@@ -88,13 +88,28 @@
         ],
         'Set_SEL_Time':
         [
-            # raw command, expected output(s), comment
+            # raw command, expected output(s)
             '0x0a 0x49',
             'rsp=0xd5',
             'not supported in present state',
             'rsp=0xc7',
             'Request data length invalid',
-
+        ],
+        'Clear_SEL':
+        [
+            # raw command, expected output(s)
+            "0x0a 0x47",
+            "0x43 0x4c 0x52 0xaa",
+            "sel clear",
+            "Clearing SEL",
+            "rsp=0xc5",
+            "Reservation cancelled or invalid",
+            "0x43 0x4c 0x52 0x00",
+        ],
+        'SEL_info':
+        [
+            # raw command
+            "0x0a 0x40"
         ],
         'Create_SEL':
         [
@@ -102,6 +117,12 @@
             "0x0a 0x44 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x04",
             "0x00 0xa0 0x04 0x07",
         ],
+        'Get_SEL_Entry':
+        [
+            # raw command
+            "0x0a 0x43 0x00 0x00",
+            "0x00 0xff",
+        ],
     },
     'Self_Test_Results':
     {
diff --git a/ipmi/test_ipmi_sel.robot b/ipmi/test_ipmi_sel.robot
index a9262a3..e2269ba 100644
--- a/ipmi/test_ipmi_sel.robot
+++ b/ipmi/test_ipmi_sel.robot
@@ -3,8 +3,10 @@
 Documentation    Module to test IPMI SEL functionality.
 Resource         ../lib/ipmi_client.robot
 Resource         ../lib/openbmc_ffdc.robot
+Library          ../lib/ipmi_utils.py
 Variables        ../data/ipmi_raw_cmd_table.py
 
+Test Setup       Test Setup Execution
 Test Teardown    FFDC On Test Case Fail
 
 *** Variables ***
@@ -50,12 +52,9 @@
     [Tags]  Verify_Add_SEL_Entry
     [Teardown]  Run Keywords  FFDC On Test Case Fail  AND  Run IPMI Standard Command  sel clear
 
-    Run IPMI Standard Command  sel clear
-    Sleep  5s
-
     # The IPMI raw command to generate Temp sensor  error is no longer working.
     # Our aim is to check if the SEL command is listed in IPMI or not.
-    # Original keyword "Create SEL" for reference
+    # Original keyword "Create User Defined SEL" for reference
     Create Test PEL Log
 
     # Get last SEL entry.
@@ -66,6 +65,52 @@
     ...  Should Contain  ${resp}  Asserted  msg=Add SEL Entry failed.
 
 
+Verify Add SEL Entry For Any Random Sensor
+    [Documentation]  Create SEL entry and verify for any given random sensor.
+    [Tags]  Verify_Add_SEL_Entry_For_Any_Random_Sensor
+    [Teardown]  Run Keywords  FFDC On Test Case Fail  AND  Run IPMI Standard Command  sel clear
+
+    # Get any sensor available from sensor list.
+    ${sensor_name}=  Fetch Any Sensor From Sensor List
+
+    # Get Sensor ID from SDR get "sensor".
+    ${sensor_data1}=  Fetch Sensor Details From SDR  ${sensor_name}  Sensor ID
+    ${name_sensor}  ${sensor_number}=  Get Data And Byte From SDR Sensor  ${sensor_data1}
+
+    # Get Sensor Type from SDR get "sensor".
+    ${sensor_data2}=  Fetch Sensor Details From SDR  ${sensor_name}  Sensor Type (Threshold)
+    ${sensor_type}  ${sensor_type_id}=  Get Data And Byte From SDR Sensor  ${sensor_data2}
+
+    # Add SEL Entry.
+    # ${sel_entry_id} is the Record ID for added record (LSB First).
+    ${sel_create_resp}=  Create SEL  ${sensor_type_id}  ${sensor_number}
+    ${sel_entry_id}=  Split String  ${sel_create_resp}
+
+    # Get last SEL entry.
+    ${resp}=  Run IPMI Standard Command  sel elist last 1
+
+    # Output of the Sel elist last 1.
+    # Below example is a continuous line statement.
+    #    N | MM/DD/YYYY | HH:MM:SS | Sensor_Type Sensor_Name |
+    #    Lower Non-critical going low  | Asserted | Reading 0.
+
+    Run Keywords  Should Contain  ${resp}  ${sensor_type} ${sensor_name}  AND
+    ...  Should Contain  ${resp}  Asserted  msg=Add SEL Entry failed.
+
+    # Get SEL Entry IPMI Raw Command.
+    ${entry}=  Get SEL Entry Via IPMI  ${sel_entry_id[0]}  ${sel_entry_id[1]}
+
+    # Compare SEL Record ID.
+    ${sel_record_id}=  Set Variable  ${entry[2:4]}
+    Should Be Equal  ${sel_record_id}  ${sel_entry_id}
+
+    # Sensor type compare.
+    Should Be Equal  ${sensor_type_id}  ${entry[12]}
+
+    # Sensor number compare.
+    Should Be Equal  ${sensor_number}  ${entry[13]}
+
+
 Verify Reserve SEL
     [Documentation]  Verify reserve SEL.
     [Tags]  Verify_Reserve_SEL
@@ -79,14 +124,244 @@
     Run IPMI Standard Command
     ...  raw 0x0a 0x47 0x${reserve_id[0]} 0x${reserve_id[1]} 0x43 0x4c 0x52 0xaa
 
+    # Check SEL list.
+    ${resp}=  Run IPMI Standard Command  sel list
+    Should Contain  ${resp}  SEL has no entries  case_insensitive=True
+
+
+Verify IPMI SEL Most Recent Addition Timestamp
+    [Documentation]  Verify most recent addition timestamp in SEL info.
+    [Tags]  Verify_IPMI_SEL_Most_Recent_Addition_Timestamp
+
+    # Get Most Recent Addition Timestamp from SEL Info.
+    ${addition_timestamp}=  Get Most Recent Addition Timestamp From SEL Info
+
+    IF  '${addition_timestamp}' != 'ffffffff'
+        # Convert to epoch timestamp.
+        ${epoch_addition}=  Convert To Integer  ${addition_timestamp}  16
+
+        # Get SEL List last 1 entry date and time and convert to epoch timestamp.
+        ${sel_epoch_time}=  Get SEL Elist Last Entry Date In Epoch
+
+        # Compare epoch of sel entry timestamp and last addition timestamp.
+        ${diff}=  Evaluate  int(${sel_epoch_time}) - int(${epoch_addition})
+        Should Be True  ${diff}<=600
+
+    ELSE
+        # Get any Sensor available from Sensor list
+        ${sensor_name}=  Fetch Any Sensor From Sensor List
+
+        # Get Sensor ID from SDR Get "sensor" and Identify Sensor ID.
+        ${sensor_data1}=  Fetch Sensor Details From SDR  ${sensor_name}  Sensor ID
+        ${name_sensor}  ${sensor_number}=  Get Data And Byte From SDR Sensor  ${sensor_data1}
+
+        # Get Sensor Type from SDR Get "sensor" and Identify Sensor Type.
+        ${sensor_data2}=  Fetch Sensor Details From SDR  ${sensor_name}  Sensor Type (Threshold)
+        ${sensor_type}  ${sensor_type_id}=  Get Data And Byte From SDR Sensor  ${sensor_data2}
+
+        # Add SEL Entry.
+        ${sel_create_resp}=  Create SEL  ${sensor_type_id}  ${sensor_number}
+
+        # Get SEL List last 1 entry date and time and convert to epoch timestamp.
+        ${sel_epoch_time}=  Get SEL Elist Last Entry Date In Epoch
+
+        # Get Most Recent Addition Timestamp from SEL Info.
+        ${addition}=  Get Most Recent Addition Timestamp From SEL Info
+        ${epoch_addition}=  Convert To Integer  ${addition}  16
+
+        # Compare epoch of sel entry timestamp and last addition timestamp.
+        ${diff}=  Evaluate  int(${epoch_addition}) - int(${sel_epoch_time})
+        Should Be True  ${diff}<=5
+    END
+
+
+Verify IPMI SEL Most Recent Erase Timestamp
+    [Documentation]  Verify Most Recent Erase Timestamp In SEL Info with current
+    ...              BMC epoch timestamp.
+    [Tags]  Verify_IPMI_SEL_Most_Recent_Erase_Timestamp
+
+    # Get BMC Current Time.
+    ${bmc_epoch_time}=  Get BMC Time In Epoch
+
+    # Get Most Recent Addition Timestamp from SEL Info.
+    ${addition_timestamp}=  Get Most Recent Addition Timestamp From SEL Info
+    Should Be Equal  ${addition_timestamp}  ffffffff
+
+    # Get Most Recent Erase Timestamp from SEL Info.
+    ${erase_timestamp}=  Get Most Recent Erase Timestamp From SEL Info
+    ${epoch_erase}=  Convert To Integer  ${erase_timestamp}  16
+
+    # Compare epoch of erase timestamp and current bmc timestamp.
+    ${diff}=  Evaluate  int(${epoch_erase}) - int(${bmc_epoch_time})
+    Should Be True  ${diff}<=5
+
+
+Verify Clear SEL With Invalid Reservation ID
+    [Documentation]  Verify clear SEL After generating another reserve ID.
+    [Tags]  Verify_Clear_SEL_With_Invalid_Reservation_ID
+
+    # Reserve Sel command - 1.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['SEL_entry']['Reserve'][0]}
+    ${reserve_id}=  Split String  ${resp}
+
+    # Reserve Sel command - 2.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['SEL_entry']['Reserve'][0]}
+
+    ${cmd}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][0]} 0x${reserve_id[0]}
+    ...  0x${reserve_id[1]} ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][1]}
+
+    # Clear SEL command.
+    ${clear_resp}=  Run Keyword and Expect Error  *${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][4]}*
+    ...  Run IPMI Standard Command  raw ${cmd}
+    Should Contain  ${clear_resp}  ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][5]}
+
+
+Verify Reservation ID Erasure Status
+    [Documentation]  Verify Erasure status by clearing SEL with Reserve ID and verify the response byte,
+    ...  whether erasure status is updated in clear sel command response data using new Reserve ID.
+    [Tags]  Verify_Reservation_ID_Erasure_Status
+
+    # Generate Reserve ID 1.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['SEL_entry']['Reserve'][0]}
+    ${reserve_id}=  Split String  ${resp}
+
+    ${cmd1}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][0]} 0x${reserve_id[0]}
+    ...  0x${reserve_id[1]} ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][1]}
+
+    # Execute clear SEL raw command with Reservation ID.
+    # Command will not execute unless the correct Reservation ID value is provided.
+    Run IPMI Standard Command  raw ${cmd1}
+
+    # Generate Reserver ID 2.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['SEL_entry']['Reserve'][0]}
+    ${reserve_id}=  Split String  ${resp}
+
+    ${cmd2}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][0]} 0x${reserve_id[0]}
+    ...  0x${reserve_id[1]} ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][6]}
+
+    # Check the Erasure status of Clear SEL.
+    ${data}=  Run IPMI Standard Command  raw ${cmd2}
+
+    # 00 - Erasure in Progress , 01 - Erasure Complete.
+    Should Contain Any  ${data}  00  01
+
+
+Verify Clear SEL After Cold Reset
+    [Documentation]  Verify Clear SEL for a reserve SEL ID after Cold Reset.
+    [Tags]  Verify_Clear_SEL_After_Cold_Reset
+
+    # Reserve Sel command.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['SEL_entry']['Reserve'][0]}
+    ${reserve_id}=  Split String  ${resp}
+
+    # Run Cold Reset.
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['Cold Reset']['reset'][0]}
+    Wait Until Keyword Succeeds  3 min  10 sec  Is BMC Unpingable
+    Wait Until Keyword Succeeds  3 min  10 sec  Is BMC Operational
+
+    ${cmd}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][0]} 0x${reserve_id[0]}
+    ...  0x${reserve_id[1]} ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][1]}
+
+    # Clear SEL command.
+    ${clear_resp}=  Run Keyword and Expect Error  *${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][5]}*
+    ...  Run IPMI Standard Command  raw ${cmd}
+
+    Should Contain  ${clear_resp}  ${IPMI_RAW_CMD['SEL_entry']['Clear_SEL'][4]}
+
 
 *** Keywords ***
 
-Create SEL
-    [Documentation]  Create a SEL.
+Create User Defined SEL
+    [Documentation]  Create a user defined tempearature sensor SEL.
 
     # Create a SEL.
     # Example:
     # a | 02/14/2020 | 01:16:58 | Temperature #0x17 |  | Asserted
     Run IPMI Command
     ...  0x0a 0x44 0x00 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x01 ${sensor_number} 0x00 0xa0 0x04 0x07
+
+
+Get SEL Entry Via IPMI
+    [Documentation]  Get SEL Entry Via IPMI raw command.
+    [Arguments]  ${record1}  ${record2}
+
+    # Description of Argument(s):
+    # ${record1}    Record ID for added record, LS Byte
+    # ${record2}    Record ID for added record, MS Byte
+
+    # For example, when a first sel entry is added with IPMI raw command, the response will be "01 00".
+    # Here, ${record1} is 01, and ${record2} is 00.
+
+    ${cmd}=  Catenate  ${IPMI_RAW_CMD['SEL_entry']['Get_SEL_Entry'][0]} 0x${record1}
+    ...  0x${record2} ${IPMI_RAW_CMD['SEL_entry']['Get_SEL_Entry'][1]}
+
+    # Get SEL Entry Raw command.
+    ${resp}=  Run IPMI Standard Command  raw ${cmd}
+    ${resp}=  Split String  ${resp}
+
+    [Return]  ${resp}
+
+
+Get Most Recent Addition Timestamp From SEL Info
+    [Documentation]  Get Most recent addition timestamp From SEL Info.
+
+    # Get SEL Info raw command.
+    ${sel_info}=  Get SEL Info Via IPMI
+
+    # Get Most Recent Addition timestamp in hex.
+    ${addition_timestamp}=  Set Variable  ${sel_info[5:9]}
+    Reverse List  ${addition_timestamp}
+    ${addition_timestamp}=  Evaluate  "".join(${addition_timestamp})
+
+    [Return]  ${addition_timestamp}
+
+
+Get Most Recent Erase Timestamp From SEL Info
+    [Documentation]  Get Most recent erase timestamp From SEL Info.
+
+    # Get SEL Info Raw command.
+    ${sel_info}=  Get SEL Info Via IPMI
+
+    # Get Most Recent Erase timestamp in hex.
+    ${erase_timestamp}=  Set Variable  ${sel_info[9:13]}
+    Reverse List  ${erase_timestamp}
+    ${erase_timestamp}=  Evaluate  "".join(${erase_timestamp})
+
+    [Return]  ${erase_timestamp}
+
+
+Get SEL Elist Last Entry Date In Epoch
+    [Documentation]  Get the time from SEL elist last entry and returns epoch time.
+
+    # Get SEL list last entry.
+    ${resp}=  Run IPMI Standard Command  sel elist last 1
+
+    # Get date from the sel entry and convert to epoch timestamp.
+    ${sel_entry_date}=  Fetch Added SEL Date  ${resp}
+    ${epoch_date}=  Convert Date  ${sel_entry_date}  epoch  exclude_millis=yes  date_format=%m/%d/%Y %H:%M:%S
+
+    [Return]  ${epoch_date}
+
+
+Get BMC Time In Epoch
+    [Documentation]  Get the current time from BMC and returns epoch time.
+
+    # Get the bmc native bmc date command response.
+    ${date}=  Get Current Date from BMC
+
+    ${epoch_date}=  Convert Date  ${date}  epoch  exclude_millis=yes  date_format=%m/%d/%Y %H:%M:%S
+
+    [Return]   ${epoch_date}
+
+
+Test Setup Execution
+    [Documentation]  Do test setup tasks.
+
+    Run IPMI Standard Command  sel clear
+    Sleep  5s
diff --git a/lib/ipmi_client.robot b/lib/ipmi_client.robot
index bfed034..d6b944c 100755
--- a/lib/ipmi_client.robot
+++ b/lib/ipmi_client.robot
@@ -457,6 +457,8 @@
     ${resp}=  Run IPMI Command
     ...  ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][0]} 0x${sensor_type} 0x${sensor_number} ${IPMI_RAW_CMD['SEL_entry']['Create_SEL'][1]}
 
+    Should Not Contain  ${resp}  00 00  msg=SEL not created.
+
     [Return]  ${resp}
 
 
@@ -536,3 +538,24 @@
     ${date}=  Convert Date  ${date}  date_format=%b %d %H:%M:%S %Y  result_format=%m/%d/%Y %H:%M:%S  exclude_millis=True
 
     [Return]   ${date}
+
+
+Get SEL Info Via IPMI
+    [Documentation]  Get the SEL Info via IPMI raw command
+
+    # Get SEL Info response consist of 14 bytes of hexadecimal data.
+
+    # Byte 1 - SEL Version,
+    # Byte 2 & 3 - Entry bytes - LSB MSB,
+    # Byte 4 & 5 - Free Space in bytes, LS Byte first.
+    # Byte 6 - 9 - Most recent addition timestamp,
+    # Byte 10-13 - Most recent erase timestamp,
+    # Byte 14 - Operation Support
+
+    # Example: ${resp} will be "51 XX XX XX XX ff ff ff ff ff ff ff ff XX"
+
+    ${resp}=  Run IPMI Standard Command
+    ...  raw ${IPMI_RAW_CMD['SEL_entry']['SEL_info'][0]}
+    ${resp}=  Split String  ${resp}
+
+    [Return]  ${resp}