+
+Run Process With Logging And Status Check
+ [Arguments] @{proc_args}
+ [Documentation] Execute an OS command, log STDOUT and STDERR output and check exit code to be 0
+ ${result}= Run Process @{proc_args}
+ Log ${result.stdout}
+ Log ${result.stderr}
+ Should Be Equal As Integers ${result.rc} 0
+ [Return] ${result}
+
+Get Data From URI
+ [Arguments] ${session} ${uri} ${headers}=${NONE}
+ [Documentation] Issue a GET request and return the data obtained or on error log the error and fail.
+ ... Issues a GET request for ${uri} in ${session} using headers from
+ ... ${headers}. If the request returns a HTTP error, fails. Otherwise
+ ... returns the data obtained by the request.
+ ${response}= RequestsLibrary.Get Request ${session} ${uri} ${headers}
+ Builtin.Return_From_Keyword_If ${response.status_code} == 200 ${response.text}
+ Builtin.Log ${response.text}
+ Builtin.Fail The request failed with code ${response.status_code}
+
+No Content From URI
+ [Arguments] ${session} ${uri} ${headers}=${NONE}
+ [Documentation] Issue a GET request and return on error 404 (No content) or will fail and log the content.
+ ... Issues a GET request for ${uri} in ${session} using headers from
+ ... ${headers}. If the request returns a HTTP error, fails. Otherwise
+ ... returns the data obtained by the request.
+ ${response}= RequestsLibrary.Get Request ${session} ${uri} ${headers}
+ Builtin.Return_From_Keyword_If ${response.status_code} == 404
+ Builtin.Log ${response.text}
+ Builtin.Fail The request failed with code ${response.status_code}
+
+Get Index From List Of Dictionaries
+ [Arguments] ${dictionary_list} ${key} ${value}
+ [Documentation] Extract index for the dictionary in a list that contains a key-value pair. Returns -1 if key-value is not found.
+ ${length}= Get Length ${dictionary_list}
+ ${index}= Set Variable -1
+ : FOR ${i} IN RANGE ${length}
+ \ ${dictionary}= Get From List ${dictionary_list} ${i}
+ \ Run Keyword If '&{dictionary}[${key}]' == '${value}' Set Test Variable ${index} ${i}
+ [Return] ${index}
+
+Check Item Occurrence
+ [Arguments] ${string} ${dictionary_item_occurrence}
+ [Documentation] Check string for occurrences of items expressed in a list of dictionaries {item=occurrences}. 0 occurences means item is not present.
+ : FOR ${item} IN @{dictionary_item_occurrence}
+ \ Should Contain X Times ${string} ${item} &{dictionary_item_occurrence}[${item}]
+
+Post Log Check
+ [Arguments] ${uri} ${body} ${status_code}=200
+ [Documentation] Post body to ${uri}, log response content, and check status
+ ${resp}= RequestsLibrary.Post Request session ${uri} ${body}
+ Log ${resp.content}
+ Should Be Equal As Strings ${resp.status_code} ${status_code}
+ [Return] ${resp}
+
+Get Log File Name
+ [Arguments] ${testtool} ${testcase}=${EMPTY}
+ [Documentation] Get the name of the suite sanitized to be usable as a part of filename.
+ ... These names are used to constructs names of the log files produced
+ ... by the testing tools so two suites using a tool wont overwrite the
+ ... log files if they happen to run in one job.
+ ${name}= BuiltIn.Evaluate """${SUITE_NAME}""".replace(" ","-").replace("/","-").replace(".","-")
+ ${suffix}= BuiltIn.Set_Variable_If '${testcase}' != '' --${testcase} ${EMPTY}
+ [Return] ${testtool}--${name}${suffix}.log
+
+Set_User_Configurable_Variable_Default
+ [Arguments] ${name} ${value}
+ [Documentation] Set a default value for an user configurable variable.
+ ... This keyword is needed if your default value is calculated using
+ ... a complex expression which needs BuiltIn.Evaluate or even more
+ ... complex keywords. It sets the variable ${name} to ${value} but
+ ... only if the variable ${name} was not set previously. This keyword
+ ... is intended for user configurable variables which are supposed to
+ ... be set only with pybot -v; calling this keyword on a variable
+ ... that was already set by another keyword is a bug in the suite or
+ ... resource trying to call this keyword.
+ # TODO: Figure out how to make the ${value} evaluation "lazy" (meaning
+ # evaluating it only when the user did not set anything and thus the
+ # default is needed). This might be needed to avoid potentially costly
+ # keyword invocations when they are not needed. Currently no need for
+ # this was identified, thus leaving it here as a TODO. Based on
+ # comments the best approach would be to create another keyword that
+ # expects a ScalarClosure in the place of ${value} and calls the
+ # closure to get the value but only if the value is needed).
+ ${value}= BuiltIn.Get_Variable_Value \${${name}} ${value}
+ BuiltIn.Set_Suite_Variable \${${name}} ${value}