blob: 81e0ca216dc5469d074054b6fdd08d09c1d1cbd8 [file] [log] [blame]
George Keishingcae6e902017-09-07 13:35:59 -05001*** Settings ***
2Documentation Open power domain keywords.
3
George Keishing7e825d82019-12-13 00:38:15 -06004Variables ../data/variables.py
George Keishingcae6e902017-09-07 13:35:59 -05005Resource ../lib/utils.robot
Michael Sheposd66cd552020-08-20 16:24:21 -05006Resource ../lib/connection_client.robot
George Keishing8ef9e722023-01-18 10:21:31 +05307Library utilities.py
George Keishingcae6e902017-09-07 13:35:59 -05008
George Keishingedd01e12021-08-31 14:01:12 -05009*** Variables ***
10${functional_cpu_count} ${0}
11${active_occ_count} ${0}
George Keishing9c223092024-01-29 21:18:25 +053012${OCC_WAIT_TIMEOUT} 8 min
George Keishingc23f3872023-03-16 22:43:33 +053013${fan_json_msg} Unable to create dump on non-JSON config based system
George Keishingedd01e12021-08-31 14:01:12 -050014
George Keishingcae6e902017-09-07 13:35:59 -050015*** Keywords ***
16
17Get OCC Objects
18 [Documentation] Get the OCC objects and return as a list.
19
20 # Example:
21 # {
22 # "/org/open_power/control/occ0": {
23 # "OccActive": 0
24 # },
25 # "/org/open_power/control/occ1": {
26 # "OccActive": 1
27 # }
28
George Keishing50cd0012017-09-14 12:23:41 -050029 ${occ_list}= Get Endpoint Paths ${OPENPOWER_CONTROL} occ*
George Keishingcae6e902017-09-07 13:35:59 -050030
George Keishing409df052024-01-17 22:36:14 +053031 RETURN ${occ_list}
George Keishingcae6e902017-09-07 13:35:59 -050032
33
34Get OCC Active State
35 [Documentation] Get the OCC "OccActive" and return the attribute value.
George Keishing9f487012021-08-19 12:18:10 -050036 [Arguments] ${value}
George Keishingcae6e902017-09-07 13:35:59 -050037
38 # Description of argument(s):
George Keishing9f487012021-08-19 12:18:10 -050039 # value CPU position (e.g. "0, 1, 2").
George Keishingcae6e902017-09-07 13:35:59 -050040
George Keishing9f487012021-08-19 12:18:10 -050041 ${cmd}= Catenate busctl get-property org.open_power.OCC.Control
42 ... /org/open_power/control/occ${value} org.open_power.OCC.Status OccActive
43
44 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd}
45 ... print_out=1 print_err=1 ignore_err=1
46
47 # The command returns format 'b true'
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -050048 IF '${cmd_output.split(' ')[-1]}' == 'true'
49 RETURN ${1}
50 END
George Keishing9f487012021-08-19 12:18:10 -050051
George Keishing409df052024-01-17 22:36:14 +053052 RETURN ${0}
George Keishing50cd0012017-09-14 12:23:41 -050053
54
55Count Object Entries
Gunnar Mills28e403b2017-10-25 16:16:38 -050056 [Documentation] Count the occurrence number of a given object.
George Keishing50cd0012017-09-14 12:23:41 -050057 [Arguments] ${object_base_uri_path} ${object_name}
58
59 # Description of argument(s):
60 # object_base_uri_path Object base path
61 # (e.g. "/org/open_power/control/").
62 # object_name Object name (e.g. "occ", "cpu" etc).
63
64 ${object_list}= Get Endpoint Paths
65 ... ${object_base_uri_path} ${object_name}
66 ${list_count}= Get Length ${object_list}
George Keishing409df052024-01-17 22:36:14 +053067 RETURN ${list_count}
George Keishing50cd0012017-09-14 12:23:41 -050068
69
70Read Object Attribute
71 [Documentation] Return object attribute data.
72 [Arguments] ${object_base_uri_path} ${attribute_name}
73
74 # Description of argument(s):
75 # object_base_uri_path Object path.
76 # (e.g. "/org/open_power/control/occ0").
77 # attribute_name Object attribute name.
78
79 ${resp}= OpenBMC Get Request
80 ... ${object_base_uri_path}/attr/${attribute_name} quiet=${1}
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -050081
82 IF ${resp.status_code} != ${HTTP_OK}
83 RETURN
84 END
85
George Keishing409df052024-01-17 22:36:14 +053086 RETURN ${resp.json()["data"]}
George Keishing50cd0012017-09-14 12:23:41 -050087
George Keishing5c96d1a2018-02-02 10:59:58 -060088
George Keishingedd01e12021-08-31 14:01:12 -050089Get Functional Processor Count
90 [Documentation] Get functional processor count.
91
Yi Huc32434a2024-01-11 17:33:10 -080092 ${cpu_list}= Redfish.Get Members List /redfish/v1/Systems/${SYSTEM_ID}/Processors/ *cpu*
George Keishingedd01e12021-08-31 14:01:12 -050093
94 FOR ${endpoint_path} IN @{cpu_list}
95 # {'Health': 'OK', 'State': 'Enabled'} get only matching status good.
96 ${cpu_status}= Redfish.Get Attribute ${endpoint_path} Status
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -050097
98 IF '${cpu_status['Health']}' != 'OK' or '${cpu_status['State']}' != 'Enabled'
99 CONTINUE
100 END
George Keishingedd01e12021-08-31 14:01:12 -0500101 ${functional_cpu_count} = Evaluate ${functional_cpu_count} + 1
102 END
103
George Keishing409df052024-01-17 22:36:14 +0530104 RETURN ${functional_cpu_count}
George Keishingedd01e12021-08-31 14:01:12 -0500105
106
107Get Active OCC State Count
108 [Documentation] Get active OCC state count.
109
Yi Huc32434a2024-01-11 17:33:10 -0800110 ${cpu_list}= Redfish.Get Members List /redfish/v1/Systems/${SYSTEM_ID}/Processors/ *cpu*
George Keishingedd01e12021-08-31 14:01:12 -0500111
112 FOR ${endpoint_path} IN @{cpu_list}
113 ${num}= Set Variable ${endpoint_path[-1]}
114 ${cmd}= Catenate busctl get-property org.open_power.OCC.Control
115 ... /org/open_power/control/occ${num} org.open_power.OCC.Status OccActive
116
117 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd}
118 ... print_out=1 print_err=1 ignore_err=1
119
120 # The command returns format 'b true'
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500121 IF '${cmd_output.split(' ')[-1]}' != 'true' CONTINUE
George Keishingedd01e12021-08-31 14:01:12 -0500122 ${active_occ_count} = Evaluate ${active_occ_count} + 1
123 END
124
George Keishing409df052024-01-17 22:36:14 +0530125 RETURN ${active_occ_count}
George Keishingedd01e12021-08-31 14:01:12 -0500126
127
128Match OCC And CPU State Count
George Keishing8b38c1a2021-12-06 22:47:18 -0600129 [Documentation] Get CPU functional count and verify OCC count active matches.
130
George Keishingedd01e12021-08-31 14:01:12 -0500131 ${cpu_count}= Get Functional Processor Count
George Keishing8b38c1a2021-12-06 22:47:18 -0600132 Log To Console Functional Processor count: ${cpu_count}
133
134 FOR ${num} IN RANGE ${0} ${cpu_count}
135 ${cmd}= Catenate busctl get-property org.open_power.OCC.Control
136 ... /org/open_power/control/occ${num} org.open_power.OCC.Status OccActive
137
138 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd}
139 ... print_out=1 print_err=1 ignore_err=1
140
141 # The command returns format 'b true'
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500142 IF '${cmd_output.split(' ')[-1]}' != 'true' CONTINUE
George Keishing8b38c1a2021-12-06 22:47:18 -0600143 ${active_occ_count} = Evaluate ${active_occ_count} + 1
144 END
145
146 Log To Console OCC Active count: ${active_occ_count}
147
148 Should Be Equal ${active_occ_count} ${cpu_count}
149 ... msg=OCC count ${active_occ_count} and CPU Count ${cpu_count} mismatched.
George Keishingedd01e12021-08-31 14:01:12 -0500150
151
George Keishing5c96d1a2018-02-02 10:59:58 -0600152Verify OCC State
153 [Documentation] Check OCC active state.
154 [Arguments] ${expected_occ_active}=${1}
155 # Description of Argument(s):
156 # expected_occ_active The expected occ_active value (i.e. 1/0).
157
158 # Example cpu_list data output:
George Keishing0ad13a12021-06-18 14:15:14 -0500159 # /redfish/v1/Systems/system/Processors/cpu0
160 # /redfish/v1/Systems/system/Processors/cpu1
161
Yi Huc32434a2024-01-11 17:33:10 -0800162 ${cpu_list}= Redfish.Get Members List /redfish/v1/Systems/${SYSTEM_ID}/Processors/ cpu*
George Keishing5c96d1a2018-02-02 10:59:58 -0600163
Marissa Garza522a0c22020-02-05 12:49:29 -0600164 FOR ${endpoint_path} IN @{cpu_list}
George Keishing0ad13a12021-06-18 14:15:14 -0500165 # {'Health': 'OK', 'State': 'Enabled'} get only matching status good.
166 ${cpu_status}= Redfish.Get Attribute ${endpoint_path} Status
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500167 IF '${cpu_status['Health']}' != 'OK' or '${cpu_status['State']}' != 'Enabled' CONTINUE
George Keishing0ad13a12021-06-18 14:15:14 -0500168 Log To Console ${cpu_status}
Marissa Garza522a0c22020-02-05 12:49:29 -0600169 ${num}= Set Variable ${endpoint_path[-1]}
George Keishing9f487012021-08-19 12:18:10 -0500170 ${occ_active}= Get OCC Active State ${num}
Marissa Garza522a0c22020-02-05 12:49:29 -0600171 Should Be Equal ${occ_active} ${expected_occ_active}
172 ... msg=OCC not in right state
173 END
George Keishingac512252018-02-05 02:04:30 -0600174
175
176Get Sensors Aggregation Data
177 [Documentation] Return open power sensors aggregation value list.
178 [Arguments] ${object_base_uri_path}
179
180 # Description of argument(s):
181 # object_base_uri_path An object path such as one of the elements
182 # returned by 'Get Sensors Aggregation URL List'
183 # (e.g. "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/average").
184
185 # Example of aggregation [epoch,time] data:
186 # "Values": [
187 # [
188 # 1517815708479, <-- EPOCH
189 # 282 <-- Power value in watts
190 # ],
191 # [
192 # 1517815678238,
193 # 282
194 # ],
195 # [
196 # 1517815648102,
197 # 282
198 # ],
199 # ],
200
201 ${resp}= Read Attribute ${object_base_uri_path} Values quiet=${1}
202 ${power_sensors_value_list}= Create List
Marissa Garza522a0c22020-02-05 12:49:29 -0600203 FOR ${entry} IN @{resp}
204 Append To List ${power_sensors_value_list} ${entry[1]}
205 END
George Keishing409df052024-01-17 22:36:14 +0530206 RETURN ${power_sensors_value_list}
George Keishingac512252018-02-05 02:04:30 -0600207
208
209Get Sensors Aggregation URL List
210 [Documentation] Return the open power aggregation maximum list and the
211 ... average list URIs.
212 [Arguments] ${object_base_uri_path}
213
214 # Example of the 2 lists returned by this keyword:
215 # avgs:
216 # avgs[0]: /org/open_power/sensors/aggregation/per_30s/ps0_input_power/average
217 # avgs[1]: /org/open_power/sensors/aggregation/per_30s/ps1_input_power/average
218 # maxs:
219 # maxs[0]: /org/open_power/sensors/aggregation/per_30s/ps1_input_power/maximum
220 # maxs[1]: /org/open_power/sensors/aggregation/per_30s/ps0_input_power/maximum
221
222 # Description of argument(s):
223 # object_base_uri_path Object path.
224 # base path "/org/open_power/sensors/"
225 # (e.g. "base path + aggregation/per_30s/ps0_input_power/average")
226
227 # Example of open power sensor aggregation data as returned by the get
228 # request:
229 # /org/open_power/sensors/list
230 # [
231 # "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/average",
232 # "/org/open_power/sensors/aggregation/per_30s/ps1_input_power/maximum",
233 # "/org/open_power/sensors/aggregation/per_30s/ps0_input_power/maximum",
234 # "/org/open_power/sensors/aggregation/per_30s/ps1_input_power/average"
235 # ]
236
237 ${resp}= OpenBMC Get Request ${object_base_uri_path}list quiet=${1}
George Keishingac512252018-02-05 02:04:30 -0600238
239 ${power_supply_avg_list}= Create List
240 ${power_supply_max_list}= Create List
241
George Keishingfbd67002022-08-01 11:24:03 -0500242 FOR ${entry} IN @{resp.json()["data"]}
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500243 IF 'average' in '${entry}' Append To List ${power_supply_avg_list} ${entry}
244 IF 'maximum' in '${entry}' Append To List ${power_supply_max_list} ${entry}
Marissa Garza522a0c22020-02-05 12:49:29 -0600245 END
George Keishingac512252018-02-05 02:04:30 -0600246
George Keishing409df052024-01-17 22:36:14 +0530247 RETURN ${power_supply_avg_list} ${power_supply_max_list}
Sweta Potthuri39255032018-03-28 10:12:14 -0500248
249
250REST Verify No Gard Records
251 [Documentation] Verify no gard records are present.
252
253 ${resp}= Read Properties ${OPENPOWER_CONTROL}gard/enumerate
254 Log Dictionary ${resp}
255 Should Be Empty ${resp} msg=Found gard records.
Michael Sheposd66cd552020-08-20 16:24:21 -0500256
257
258Inject OPAL TI
259 [Documentation] OPAL terminate immediate procedure.
260 [Arguments] ${stable_branch}=master
Michael Shepos8381f7352021-04-20 12:03:08 -0500261 ... ${repo_dir_path}=/tmp/repository
Michael Sheposd66cd552020-08-20 16:24:21 -0500262 ... ${repo_github_url}=https://github.com/open-power/op-test
263
264 # Description of arguments:
265 # stable_branch Git branch to clone. (default: master)
266 # repo_dir_path Directory path for repo tool (e.g. "op-test").
267 # repo_github_url Github URL link (e.g. "https://github.com/open-power/op-test").
268
269 ${value}= Generate Random String 4 [NUMBERS]
270
271 ${cmd_buf}= Catenate git clone --branch ${stable_branch} ${repo_github_url} ${repo_dir_path}/${value}
272 Shell Cmd ${cmd_buf}
273
274 Open Connection for SCP
275 scp.Put File ${repo_dir_path}/${value}/test_binaries/deadbeef /tmp
276 Pdbg -a putmem 0x300000f8 < /tmp/deadbeef
277
278 # Clean up the repo once done.
279 ${cmd_buf}= Catenate rm -rf ${repo_dir_path}${/}${value}
280 Shell Cmd ${cmd_buf}
George Keishing2d4a8102022-02-22 12:23:21 -0600281
282
283Trigger OCC Reset
284 [Documentation] Trigger OCC reset request on an active OCC.
285 [Arguments] ${occ_target}=${0}
286
287 # Description of Argument(s):
288 # occ_target Target a valid given OCC number 0,1, etc.
289
290 Log To Console OCC Reset Triggered on OCC ${occ_target}
291
292 ${cmd}= Catenate busctl call org.open_power.OCC.Control
293 ... /org/open_power/control/occ${occ_target} org.open_power.OCC.PassThrough
294 ... Send ai 8 64 0 5 20 82 83 84 0
295
296 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd} print_out=1 print_err=1
297
George Keishing5dd532a2022-03-07 11:14:42 -0600298 Log To Console OCC wait check for disabled state.
299 Wait Until Keyword Succeeds 30 sec 5 sec Verify OCC Target State ${occ_target}
300
301
302Verify OCC Target State
303 [Documentation] Verify that the user given state matches th current OCC state.
304 [Arguments] ${occ_target}=${0} ${expected_state}=${0}
305
306 # Description of Argument(s):
307 # occ_target Target a valid given OCC number 0,1, etc.
308 # expected_state For OCC either 0 or 1. Default is 0.
George Keishing2d4a8102022-02-22 12:23:21 -0600309
310 ${occ_active}= Get OCC Active State ${occ_target}
George Keishing5dd532a2022-03-07 11:14:42 -0600311 Should Be Equal ${occ_active} ${expected_state}
George Keishing2d4a8102022-02-22 12:23:21 -0600312 Log To Console Target OCC ${occ_target} state is ${occ_active}.
313
314
315Trigger OCC Reset And Wait For OCC Active State
316 [Documentation] Trigger OCC reset request and wait for OCC to reset back to active state.
317
318 Trigger OCC Reset
319
320 Log To Console OCC wait check for active state.
321 Wait Until Keyword Succeeds ${OCC_WAIT_TIMEOUT} 20 sec Match OCC And CPU State Count
George Keishingd1baad62022-11-23 08:25:36 -0600322
323
324Get Sensors Dbus Tree List
325 [Documentation] Get the list dbus path of the given sensor object and
326 ... return the populatedlist.
327
328 ${dbus_obj_var}= Set Variable
329 ... xyz.openbmc_project.HwmonTempSensor
330 ... xyz.openbmc_project.ADCSensor
331 ... xyz.openbmc_project.VirtualSensor
332
333 # Filter only the dbus paths service by the sensor obj.
334 ${sensors_dbus_tree_dict}= Create Dictionary
335 FOR ${dbus_obj} IN @{dbus_obj_var}
336 ${cmd}= Catenate busctl tree ${dbus_obj} --list | grep /sensors/
337 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd}
338 ... print_out=0 print_err=0 ignore_err=1
339 Set To Dictionary ${sensors_dbus_tree_dict} ${dbus_obj} ${cmd_output.splitlines()}
340 END
341
342 Rprint Vars sensors_dbus_tree_dict
343 # Key Pair: 'sensor obj":[list of obj URI]
344 # Example:
345 # sensors_dbus_tree_dict:
346 # [xyz.openbmc_project.HwmonTempSensor]:
347 # [0]: /xyz/openbmc_project/sensors/temperature/Ambient_0_Temp
348 # [1]: /xyz/openbmc_project/sensors/temperature/PCIE_0_Temp
349 # [xyz.openbmc_project.ADCSensor]:
350 # [0]: /xyz/openbmc_project/sensors/voltage/Battery_Voltage
351 # [xyz.openbmc_project.VirtualSensor]:
352 # [0]: /xyz/openbmc_project/sensors/temperature/Ambient_Virtual_Temp
353
George Keishing409df052024-01-17 22:36:14 +0530354 RETURN ${sensors_dbus_tree_dict}
George Keishingd1baad62022-11-23 08:25:36 -0600355
356
357Get Populated Sensors Dbus List
358 [Documentation] Perform GET operation on the attribute list and confirm it is
359 ... populated and does not error out during GET request..
360
361 ${sensor_dict}= Get Sensors Dbus Tree List
362
363 # Loop through the dictionary and iterate item entries.
364 ${valid_dbus_list}= Create List
365 FOR ${key} IN @{sensor_dict.keys()}
366 FOR ${val} IN @{sensor_dict["${key}"]}
367 ${cmd}= Catenate
368 ... busctl get-property ${key} ${val} xyz.openbmc_project.Sensor.Value Value
369 ${cmd_output} ${stderr} ${rc} = BMC Execute Command ${cmd}
370 ... print_out=0 print_err=0 ignore_err=1
371 # Skip failed to get property command on Dbus object.
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500372 IF ${rc} == 0 Append To List ${valid_dbus_list} ${val}
George Keishingd1baad62022-11-23 08:25:36 -0600373 END
374 END
375
George Keishing409df052024-01-17 22:36:14 +0530376 RETURN ${valid_dbus_list}
George Keishingd1baad62022-11-23 08:25:36 -0600377
378
379Verify Runtime Sensors Dbus List
380 [Documentation] Load pre-defined sensor JSON Dbus data and validate against
381 ... runtime sensor list generated.
382
383 # Default path data/sensor_dbus.json else takes
384 # user CLI input -v SENSOR_DBUS_JSON_FILE_PATH:<path>
385 ${SENSOR_DBUS_JSON_FILE_PATH}=
386 ... Get Variable Value ${SENSOR_DBUS_JSON_FILE_PATH} data/sensor_dbus.json
387
388 ${json_data}= OperatingSystem.Get File ${SENSOR_DBUS_JSON_FILE_PATH}
389 ${json_sensor_data}= Evaluate json.loads('''${json_data}''') json
390
391 ${runtime_sensor_list}= Get Populated Sensors Dbus List
392
393 ${system_model}= Get BMC System Model
394 Rprint Vars system_model
395 Rprint Vars runtime_sensor_list
396
397 ${status}= Run Keyword And Return Status
398 ... Dictionary Should Contain Value ${json_sensor_data} ${runtime_sensor_list}
399
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500400 IF ${status} == ${False} Log And Fail ${json_sensor_data}
George Keishingd1baad62022-11-23 08:25:36 -0600401
402 Log To Console Runtime Dbus sensor list matches.
403
404
405Log And Fail
406 [Documentation] Log detailed failure log on the console.
407 [Arguments] ${json_sensor_data}
408
409 # Description of Argument(s):
410 # json_sensor_data Sensor JSON data from data/sensor_dbus.json.
411
412 Rprint Vars json_sensor_data
413 Fail Runtime generated Dbus sensors does not match
414
George Keishing8ef9e722023-01-18 10:21:31 +0530415
416Dump Fan Control JSON
417 [Documentation] Execute fan control on BMC to dump config with 'fanctl dump',
418 ... which makes it write a /tmp/fan_control_dump.json file.
419
420 ${output} ${stderr} ${rc} = BMC Execute Command test -f /usr/bin/fanctl
421 ... print_err=1 ignore_err=1
Sridevi Rameshfd8e5de2025-10-22 07:27:26 -0500422
423 IF ${rc} == 1 RETURN fanctl application doesn't exist.
George Keishing8ef9e722023-01-18 10:21:31 +0530424
425 # This command will force a fan_control_dump.json file in temp path and
426 # takes few seconds to complete..
427 BMC Execute Command fanctl dump
428 Sleep 10s
429
George Keishingc23f3872023-03-16 22:43:33 +0530430
431Get Fan JSON Data
432 [Documentation] Read the JSON string file from BMC and return.
433
George Keishing8ef9e722023-01-18 10:21:31 +0530434 # Check for the generated file and return the file data as JSON and fails if
435 # it doesn't find file generated.
436 ${cmd}= Catenate test -f /tmp/fan_control_dump.json; cat /tmp/fan_control_dump.json
437 ${json_string} ${stderr} ${rc} = BMC Execute Command ${cmd}
438 ... print_out=1 print_err=1 ignore_err=1
439
440 Should Be True ${rc} == 0 msg=No Fan control config JSON file is generated.
441 ${fan_json}= Evaluate json.loads('''${json_string}''') json
442
George Keishing409df052024-01-17 22:36:14 +0530443 RETURN ${fan_json}
George Keishing8ef9e722023-01-18 10:21:31 +0530444
445
446Get Fan Attribute Value
447 [Documentation] Return the specified value of the matched search key in
448 ... nested dictionary data.
George Keishingc23f3872023-03-16 22:43:33 +0530449 [Arguments] ${fan_dict} ${key_value}
George Keishing8ef9e722023-01-18 10:21:31 +0530450
451 # Description of Argument(s):
452 # key_value User input attribute value in the dictionary.
453
George Keishingc23f3872023-03-16 22:43:33 +0530454 ${empty_dicts}= Create Dictionary
455
456 # Check for JSON response data.
457 # {
458 # "msg": "Unable to create dump on non-JSON config based system"
459 # }
460
461 ${status}= Run Keyword And Return Status
462 ... Should Be Equal ${fan_dict["msg"]} ${fan_json_msg}
463 IF ${status}
464 Log To Console Skipping attribute ${key_value} check.
465 Return From Keyword ${empty_dicts}
466 END
George Keishing8ef9e722023-01-18 10:21:31 +0530467
468 # Python module: get_value_from_nested_dict(key,dict)
469 ${value_list}= utilities.Get Value From Nested Dict ${key_value} ${fan_dict}
470
471 Should Not Be Empty ${value_list} msg=${key_value} key attribute not found.
472
George Keishing409df052024-01-17 22:36:14 +0530473 RETURN ${value_list[0]}