aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docker/Dockerfile10
-rw-r--r--robot/assets/cmpv2/blueprintTemplate.json12
-rw-r--r--robot/assets/cmpv2/k8s-mongo.yaml31
-rw-r--r--robot/assets/cmpv2/k8s-pnf-simulator.yaml65
-rw-r--r--robot/assets/templates/deployment/VesTlsCmpv2Inputs.jinja25
-rw-r--r--robot/assets/templates/ves/pnf_simulator_single_event.jinja4
-rw-r--r--robot/resources/dcae/deployment.robot36
-rw-r--r--robot/resources/dcae/inventory.robot43
-rw-r--r--robot/resources/test_templates/cmpv2.robot45
-rw-r--r--robot/testsuites/cmpv2.robot95
10 files changed, 365 insertions, 1 deletions
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d0f32e7d..0ec88c0a 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -10,6 +10,8 @@ ARG TESTSUITE_TAG=master
ARG HEATBRIDGE_TAG=master
ARG PYTHON_UTILS_TAG=master
ARG DEMO_TAG=master
+ARG KUBERNETES_VERSION="v1.15.11"
+
ARG TESTSUITE_REPO=git.onap.org/testsuite
ARG HEATBRIDGE_REPO=git.onap.org/testsuite/heatbridge.git
@@ -18,6 +20,11 @@ ARG DEMO_REPO=git.onap.org/demo
COPY requirements.txt requirements.txt
+# Install kubectl
+# Note: Latest version may be found on:
+# https://aur.archlinux.org/packages/kubectl-bin/
+ADD https://storage.googleapis.com/kubernetes-release/release/${KUBERNETES_VERSION}/bin/linux/amd64/kubectl /usr/local/bin/kubectl
+
# Install Python, Pip, Robot framework, chromium, lighttpd web server
RUN apt-get update \
&& apt-get install \
@@ -47,7 +54,8 @@ RUN apt-get update \
git+https://$HEATBRIDGE_REPO@$HEATBRIDGE_TAG#egg=heatbridge\&subdirectory=heatbridge \
git+https://$PYTHON_UTILS_REPO@$PYTHON_UTILS_TAG#egg=robotframework-onap\&subdirectory=robotframework-onap && \
git clone --depth 1 https://$TESTSUITE_REPO -b $TESTSUITE_TAG /var/opt/ONAP && \
- git clone --depth 1 https://$DEMO_REPO -b $DEMO_TAG /var/opt/ONAP/demo
+ git clone --depth 1 https://$DEMO_REPO -b $DEMO_TAG /var/opt/ONAP/demo && \
+ chmod +x /usr/local/bin/kubectl && \
RUN python3.7 -m pip install setuptools wheel
RUN python3.7 -m pip install virtualenv
diff --git a/robot/assets/cmpv2/blueprintTemplate.json b/robot/assets/cmpv2/blueprintTemplate.json
new file mode 100644
index 00000000..f3b87e7d
--- /dev/null
+++ b/robot/assets/cmpv2/blueprintTemplate.json
@@ -0,0 +1,12 @@
+{
+ "asdcResourceId": "",
+ "asdcServiceId": "",
+ "asdcServiceURL": "",
+ "blueprintTemplate": "",
+ "owner": "robot",
+ "serviceIds": [],
+ "serviceLocations": [],
+ "typeName": "",
+ "typeVersion": 100,
+ "vnfTypes": []
+}
diff --git a/robot/assets/cmpv2/k8s-mongo.yaml b/robot/assets/cmpv2/k8s-mongo.yaml
new file mode 100644
index 00000000..8e4b4634
--- /dev/null
+++ b/robot/assets/cmpv2/k8s-mongo.yaml
@@ -0,0 +1,31 @@
+tosca_definitions_version: cloudify_dsl_1_3
+imports:
+ - 'http://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml'
+ - 'plugin:k8splugin?version=3.4.2'
+inputs:
+ tag_version:
+ type: string
+ description: Docker image to be used
+ default: 'mongo'
+ replicas:
+ type: integer
+ description: Number of instances
+ default: 1
+node_templates:
+ mongo:
+ type: dcae.nodes.ContainerizedServiceComponent
+ interfaces:
+ cloudify.interfaces.lifecycle:
+ start:
+ inputs:
+ envs:
+ MONGO_INITDB_ROOT_USERNAME: root
+ MONGO_INITDB_ROOT_PASSWORD: zXcVbN123!
+ MONGO_INITDB_DATABASE: pnf_simulator
+ ports:
+ - '27017:0'
+ properties:
+ service_component_type: mongo
+ service_component_name_override: mongo
+ image: { get_input: tag_version }
+ replicas: { get_input: replicas }
diff --git a/robot/assets/cmpv2/k8s-pnf-simulator.yaml b/robot/assets/cmpv2/k8s-pnf-simulator.yaml
new file mode 100644
index 00000000..24a1030f
--- /dev/null
+++ b/robot/assets/cmpv2/k8s-pnf-simulator.yaml
@@ -0,0 +1,65 @@
+tosca_definitions_version: cloudify_dsl_1_3
+imports:
+ - 'http://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml'
+ - 'plugin:k8splugin?version=3.4.2'
+inputs:
+ tag_version:
+ type: string
+ description: Docker image to be used
+ default: 'nexus3.onap.org:10001/onap/org.onap.integration.simulators.pnfsimulator:latest'
+ replicas:
+ type: integer
+ description: Number of instances
+ default: 1
+ external_cert_cert_type:
+ type: string
+ description: Output type
+ default: 'P12'
+ external_cert_ca_name:
+ type: string
+ description: Name of Certificate Authority configured on CertService side.
+ default: 'RA'
+ external_cert_common_name:
+ type: string
+ description: Common name which should be present in certificate.
+ default: 'pnf-simulator'
+ external_cert_sans:
+ type: string
+ description: 'List of Subject Alternative Names (SANs) which should be present
+ in certificate. Delimiter - : Should contain common_name value and other FQDNs
+ under which given component is accessible.'
+ default: 'pnf-simulator'
+ external_cert_use_external_tls:
+ type: boolean
+ description: Flag to indicate external tls enable/disable.
+ default: true
+node_templates:
+ pnf-simulator:
+ type: dcae.nodes.ContainerizedServiceComponent
+ interfaces:
+ cloudify.interfaces.lifecycle:
+ start:
+ inputs:
+ ports:
+ - '5000:0'
+ properties:
+ service_component_type: pnf-simulator
+ service_component_name_override: pnf-simulator
+ image: { get_input: tag_version }
+ replicas: { get_input: replicas }
+ always_pull_image: true
+ tls_info:
+ cert_directory: '/app/store/'
+ external_cert:
+ external_cert_directory: '/app/store/'
+ use_external_tls:
+ get_input: external_cert_use_external_tls
+ cert_type:
+ get_input: external_cert_cert_type
+ ca_name:
+ get_input: external_cert_ca_name
+ external_certificate_parameters:
+ common_name:
+ get_input: external_cert_common_name
+ sans:
+ get_input: external_cert_sans
diff --git a/robot/assets/templates/deployment/VesTlsCmpv2Inputs.jinja b/robot/assets/templates/deployment/VesTlsCmpv2Inputs.jinja
new file mode 100644
index 00000000..6505552e
--- /dev/null
+++ b/robot/assets/templates/deployment/VesTlsCmpv2Inputs.jinja
@@ -0,0 +1,25 @@
+{
+ "serviceTypeId": "{{serviceTypeId}}",
+ "inputs": {
+ "external_port": 0,
+ "external_port_tls": {{external_port_tls}},
+ "auth_method": "certBasicAuth",
+ "service_component_name_override": "{{service_component_name_override}}",
+ "service_id": "{{service_component_name_override}}",
+ "service_component_type": "{{service_component_name_override}}",
+ "enable_tls": true,
+ "ves_other_publish_url": "http://message-router:3904/events/unauthenticated.SEC_OTHER_OUTPUT/",
+ "ves_heartbeat_publish_url": "http://message-router:3904/events/unauthenticated.SEC_HEARTBEAT_OUTPUT/",
+ "ves_fault_publish_url": "http://message-router:3904/events/unauthenticated.SEC_FAULT_OUTPUT/",
+ "ves_measurement_publish_url": "http://message-router:3904/events/unauthenticated.VES_MEASUREMENT_OUTPUT/",
+ "ves_pnfRegistration_publish_url": "http://message-router:3904/events/unauthenticated.VES_PNFREG_OUTPUT/",
+ "ves_notification_publish_url": "http://message-router:3904/events/unauthenticated.VES_NOTIFICATION_OUTPUT/",
+ "user_list": "sample1,$2a$10$0buh.2WeYwN868YMwnNNEuNEAMNYVU9.FSMJGyIKV3dGET/7oGOi6|demouser,$2a$10$1cc.COcqV/d3iT2N7BjPG.S6ZKv2jpb9a5MV.o7lMih/GpjJRX.Ce",
+ "external_cert_ca_name": "RA",
+ "external_cert_common_name": "{{service_component_name_override}}",
+ "external_cert_sans": "{{external_cert_sans}}",
+ "external_cert_cert_type": "JKS",
+ "external_cert_use_external_tls": true,
+ "tag_version": "{{image}}"
+ }
+} \ No newline at end of file
diff --git a/robot/assets/templates/ves/pnf_simulator_single_event.jinja b/robot/assets/templates/ves/pnf_simulator_single_event.jinja
new file mode 100644
index 00000000..d800d992
--- /dev/null
+++ b/robot/assets/templates/ves/pnf_simulator_single_event.jinja
@@ -0,0 +1,4 @@
+{
+ "vesServerUrl": "{{ves_url}}",
+ "event": {{event}}
+} \ No newline at end of file
diff --git a/robot/resources/dcae/deployment.robot b/robot/resources/dcae/deployment.robot
new file mode 100644
index 00000000..30a5efce
--- /dev/null
+++ b/robot/resources/dcae/deployment.robot
@@ -0,0 +1,36 @@
+*** Settings ***
+Documentation The main interface for interacting with 5G Bulkpm.
+Library RequestsLibrary
+Library OperatingSystem
+Library String
+
+*** Variables ***
+${DEPLOYMENT_SERVER} ${GLOBAL_DEPLOYMENT_HANDLER_SERVER_PROTOCOL}://${GLOBAL_DEPLOYMENT_HANDLER_SERVER_NAME}:${GLOBAL_DEPLOYMENT_HANDLER_SERVER_PORT}
+${DEPLOYMENT_ENDPOINT} dcae-deployments
+
+*** Keywords ***
+Deploy Service
+ [Arguments] ${inputs} ${deployment_name} ${wait_time}=5 minute
+ Disable Warnings
+ ${headers}= Create Dictionary content-type=application/json
+ ${deployment_data}= Set Variable ${inputs}
+ ${session}= Create Session deployment_session ${DEPLOYMENT_SERVER}
+ ${resp}= Put Request deployment_session /${DEPLOYMENT_ENDPOINT}/${deployment_name} data=${deployment_data} headers=${headers}
+ ${operationLink} Set Variable ${resp.json().get('links').get('status')}
+ ${operationId} Fetch From Right ${operationLink} /
+ Wait Until Keyword Succeeds ${wait_time} 20 sec Deployment Status ${deployment_name} ${operationId}
+
+Deployment Status
+ [Arguments] ${deployment_name} ${operationId}
+ Disable Warnings
+ ${session}= Create Session deployment_session ${DEPLOYMENT_SERVER}
+ ${resp}= Get Request deployment_session /${DEPLOYMENT_ENDPOINT}/${deployment_name}/operation/${operationId}
+ ${status} Set Variable ${resp.json().get('status')}
+ Should Be Equal As Strings ${status} succeeded
+
+Undeploy Service
+ [Arguments] ${deployment_name}
+ Disable Warnings
+ ${session}= Create Session deployment_session ${DEPLOYMENT_SERVER}
+ ${resp}= Delete Request deployment_session /${DEPLOYMENT_ENDPOINT}/${deployment_name}
+ [Return] ${resp}
diff --git a/robot/resources/dcae/inventory.robot b/robot/resources/dcae/inventory.robot
new file mode 100644
index 00000000..647c3780
--- /dev/null
+++ b/robot/resources/dcae/inventory.robot
@@ -0,0 +1,43 @@
+*** Settings ***
+Documentation The main interface for interacting with 5G Bulkpm.
+Library RequestsLibrary
+Library OperatingSystem
+Library String
+Library ONAPLibrary.Templating WITH NAME Templating
+Resource ../global_properties.robot
+
+
+*** Variables ***
+${INVENTORY_SERVER} ${GLOBAL_INVENTORY_SERVER_PROTOCOL}://${GLOBAL_INVENTORY_SERVER_NAME}:${GLOBAL_INVENTORY_SERVER_PORT}
+${INVENTORY_ENDPOINT} /dcae-service-types
+${BLUEPRINT_TEMPLATE} ${EXECDIR}/robot/assets/cmpv2/blueprintTemplate.json
+*** Keywords ***
+
+Load Blueprint To Inventory
+ [Arguments] ${blueprint_path} ${typeName}
+ Disable Warnings
+ ${blueprint}= OperatingSystem.Get File ${blueprint_path}
+ ${templatejson}= Load JSON From File ${BLUEPRINT_TEMPLATE}
+ ${templatejson}= Update Value To Json ${templatejson} blueprintTemplate ${blueprint}
+ ${templatejson}= Update Value To Json ${templatejson} typeName ${typeName}
+ ${data} Convert JSON To String ${templatejson}
+ ${headers}= Create Dictionary content-type=application/json
+ ${session}= Create Session inventory_session ${INVENTORY_SERVER}
+ ${resp}= Post Request inventory_session ${INVENTORY_ENDPOINT} data=${data} headers=${headers}
+ ${serviceTypeId}= Set Variable ${resp.json().get('typeId')}
+ [Return] ${serviceTypeId}
+
+Delete Blueprint From Inventory
+ [Arguments] ${serviceTypeId}
+ Disable Warnings
+ ${session}= Create Session inventory_session ${INVENTORY_SERVER}
+ ${resp}= Delete Request inventory_session ${INVENTORY_ENDPOINT}/${serviceTypeId}
+ [Return] ${resp}
+
+Get Blueprint From Inventory
+ [Arguments] ${typeName}
+ Disable Warnings
+ ${headers}= Create Dictionary content-type=application/json
+ ${session}= Create Session inventory_session ${INVENTORY_SERVER}
+ ${resp}= Get Request inventory_session ${INVENTORY_ENDPOINT}?typeName=${typeName} headers=${headers}
+ [Return] ${resp} \ No newline at end of file
diff --git a/robot/resources/test_templates/cmpv2.robot b/robot/resources/test_templates/cmpv2.robot
new file mode 100644
index 00000000..685306f5
--- /dev/null
+++ b/robot/resources/test_templates/cmpv2.robot
@@ -0,0 +1,45 @@
+*** Settings ***
+Documentation CMPv2 test cases
+Library OperatingSystem
+Library RequestsLibrary
+Library Collections
+Library ONAPLibrary.JSON
+Library ONAPLibrary.Utilities
+Library ONAPLibrary.Templating WITH NAME Templating
+Resource pnf_registration_without_SO_template.robot
+Resource ../dcae/deployment.robot
+Resource ../dcae/inventory.robot
+Resource ../global_properties.robot
+
+
+*** Variables ***
+${pnf_simulator_single_event}= ves/pnf_simulator_single_event.jinja
+${VES_ENDPOINT} ${GLOBAL_DCAE_VES_HTTPS_PROTOCOL}://${GLOBAL_INJECTED_DCAE_VES_HOST}:${GLOBAL_DCAE_VES_HTTPS_SERVER_PORT}
+${VES_data_path} eventListener/v7
+${single_event_data_path} /simulator/event
+${users} ${EXECDIR}/robot/assets/cmpv2/mongo-users.json
+
+
+*** Keywords ***
+Pnf simulator send single VES event
+ [Arguments] ${event} ${ves_host} ${ves_port} ${pnf_sim_host} ${pnf_sim_port}
+ ${pnf_sim_endpoint}= Set Variable http://${pnf_sim_host}:${pnf_sim_port}
+ ${ves_url}= Set Variable ${GLOBAL_DCAE_VES_HTTPS_PROTOCOL}://${ves_host}:${ves_port}/${VES_data_path}
+ ${single_event}= Create Dictionary event=${event} ves_url=${ves_url}
+ Templating.Create Environment pnf ${GLOBAL_TEMPLATE_FOLDER}
+ ${data}= Templating.Apply Template pnf ${pnf_simulator_single_event} ${single_event}
+ ${pnf_sim_endpoint}= Set Variable http://${pnf_sim_host}:${pnf_sim_port}
+ ${session}= Create Session pnf_sim ${pnf_sim_endpoint}
+ ${headers}= Create Dictionary Accept=application/json Content-Type=application/json
+ ${post_resp}= Post Request pnf_sim ${single_event_data_path} data=${data} headers=${headers}
+ Log PNF registration request ${data}
+ Should Be Equal As Strings ${post_resp.status_code} 202
+ Log VES has accepted event with status code ${post_resp.status_code}
+
+
+Usecase Teardown
+ Undeploy Service mongo-dep
+ Undeploy Service pnf-simulator-dep
+ Undeploy Service ves-collector-cmpv2-dep
+ Delete Blueprint From Inventory ${serviceTypeIdMongo}
+ Delete Blueprint From Inventory ${serviceTypeIdPnfSimulator} \ No newline at end of file
diff --git a/robot/testsuites/cmpv2.robot b/robot/testsuites/cmpv2.robot
new file mode 100644
index 00000000..3d20606a
--- /dev/null
+++ b/robot/testsuites/cmpv2.robot
@@ -0,0 +1,95 @@
+*** Settings ***
+Documentation CMPv2 Usecase functionality
+Test Timeout 15m
+Library RequestsLibrary
+Library OperatingSystem
+Library Collections
+Library String
+Library JSONLibrary
+Library ONAPLibrary.JSON
+Library ONAPLibrary.Utilities
+Library ONAPLibrary.Templating WITH NAME Templating
+Resource ../resources/dcae/deployment.robot
+Resource ../resources/dcae/inventory.robot
+Resource ../resources/global_properties.robot
+Resource ../resources/test_templates/cmpv2.robot
+Resource ../resources/test_templates/pnf_registration_without_SO_template.robot
+Suite Setup Send VES integration request ${initial entry}
+Suite Teardown Usecase Teardown
+
+*** Variables ***
+${MONGO_BLUEPRINT_PATH} ${EXECDIR}/robot/assets/cmpv2/k8s-mongo.yaml
+${PNF_SIMULATOR_BLUEPRINT_PATH} ${EXECDIR}/robot/assets/cmpv2/k8s-pnf-simulator.yaml
+${VES_INPUTS} deployment/VesTlsCmpv2Inputs.jinja
+${pnf_ves_integration_request} ves/pnf_registration_request.jinja
+${NEXUS3} ${GLOBAL_INJECTED_NEXUS_DOCKER_REPO}
+&{initial entry} correlation_id=dummy PNF_IPv4_address=11.11.11.1 PNF_IPv6_address=2001:0db8:0:0:0:0:1428:57ab
+${PNF_SIMULATOR_ERROR_GREP_COMMAND} kubectl logs $(kubectl get pods -n onap | grep pnf-simulator | awk '{print $1}' | grep -v NAME) -n onap --tail=2 --since=20s | grep 'Error sending message to ves: Received fatal alert: certificate_unknown'
+
+*** Test Cases ***
+
+Deploying PNF Simulator
+ [Documentation]
+ ... This test case deploys PNF simulator with "enable_tls": set to false and "external_cert_use_external_tls" (CMPv2) set to true as DCAE applictaion
+ [Tags] CMPv2
+ ${serviceTypeIdMongo} Load Blueprint To Inventory ${MONGO_BLUEPRINT_PATH} mongo
+ ${serviceTypeIdPnfSimulator} Load Blueprint To Inventory ${PNF_SIMULATOR_BLUEPRINT_PATH} pnf-simulator
+ Set Suite Variable ${serviceTypeIdMongo}
+ Set Suite Variable ${serviceTypeIdPnfSimulator}
+ ${deployment_data}= Set Variable {"serviceTypeId": "${serviceTypeIdMongo}"}
+ Deploy Service ${deployment_data} mongo-dep 2 minutes
+ ${resp}= Get Blueprint From Inventory pnf-simulator
+ ${json}= Set Variable ${resp.json()}
+ ${image} Get Regexp Matches ${json['items'][0]['blueprintTemplate']} nexus3(.)*?(?=\')
+ ${image} Replace String ${image}[0] nexus3.onap.org:10001 ${NEXUS3}
+ ${deployment_data}= Set Variable {"serviceTypeId": "${serviceTypeIdPnfSimulator}", "inputs": {"tag_version": "${image}"}}
+ Deploy Service ${deployment_data} pnf-simulator-dep 4 minutes
+
+Deploying VES collector with CMPv2
+ [Documentation]
+ ... This test case deploys second VES instance with "enable_tls": set to true and "external_cert_use_external_tls" (CMPv2) set to true as DCAE applictaion
+ ... Both CMPv2 and AAF certificates are present
+ [Tags] CMPv2
+ ${resp}= Get Blueprint From Inventory k8s-ves
+ ${json}= Set Variable ${resp.json()}
+ ${serviceTypeIdVes} Set Variable ${json['items'][0]['typeId']}
+ ${image} Get Regexp Matches ${json['items'][0]['blueprintTemplate']} nexus3(.)*?(?=\")
+ ${image} Replace String ${image}[0] nexus3.onap.org:10001 ${NEXUS3}
+ ${arguments}= Create Dictionary serviceTypeId=${serviceTypeIdVes}
+ Set To Dictionary ${arguments} image ${image}
+ Set To Dictionary ${arguments} external_port_tls 32226
+ Set To Dictionary ${arguments} service_component_name_override dcae-ves-collector-cmpv2-cert
+ Set To Dictionary ${arguments} external_cert_sans dcae-ves-collector-cmpv2-cert:ves-collector-cmpv2-cert:ves-cmpv2-cert
+ Templating.Create Environment deployment ${GLOBAL_TEMPLATE_FOLDER}
+ ${deployment_data}= Templating.Apply Template deployment ${VES_INPUTS} ${arguments}
+ Deploy Service ${deployment_data} ves-collector-cmpv2-dep 4 minutes
+
+Send registration request to CMPv2 VES
+ [Documentation]
+ ... This test case triggers registration request from PNF Simulator(where is present only CMPv2 certificate) to VES collector
+ ... with enabled CMPv2 (both CMPv2 and AAF certificates are present).
+ ... Test expects successful registration
+ [Tags] CMPv2
+ ${pnf_correlation_id}= Generate Random String 20 [LETTERS][NUMBERS]
+ ${PNF_entry_dict}= Create Dictionary correlation_id=${pnf_correlation_id} PNF_IPv4_address=13.13.13.13 PNF_IPv6_address=2001:0db8:0:0:0:0:1428:57ab
+ Wait Until Keyword Succeeds 10x 5s Check VES_PNFREG_OUTPUT topic presence in MR
+ Create PNF initial entry in A&AI ${PNF_entry_dict}
+ Templating.Create Environment ves ${GLOBAL_TEMPLATE_FOLDER}
+ ${template}= Templating.Apply Template ves ${pnf_ves_integration_request} ${PNF_entry_dict}
+ Pnf simulator send single VES event ${template} dcae-ves-collector-cmpv2-cert 8443 pnf-simulator 5000
+ Verify PNF Integration Request in A&AI ${PNF_entry_dict}
+
+
+Send registration request to VES without CMPv2 certificate
+ [Documentation]
+ ... This test case triggers registration request from PNF Simulator (where is present only CMPv2 certificate) to VES collector
+ ... with disabled CMPv2 (only AAF certificate is present - VES collector deployed during whole ONAP deploy).
+ ... Test expects exceptyion in PNF Simualtor logs
+ [Tags] CMPv2
+ ${pnf_correlation_id}= Generate Random String 20 [LETTERS][NUMBERS]
+ ${PNF_entry_dict}= Create Dictionary correlation_id=${pnf_correlation_id} PNF_IPv4_address=14.14.14.14 PNF_IPv6_address=2001:0db8:0:0:0:0:1428:57ab
+ Templating.Create Environment ves ${GLOBAL_TEMPLATE_FOLDER}
+ ${template}= Templating.Apply Template ves ${pnf_ves_integration_request} ${PNF_entry_dict}
+ Pnf simulator send single VES event ${template} dcae-ves-collector 8443 pnf-simulator 5000
+ ${rc} = Run and Return RC ${PNF_SIMULATOR_ERROR_GREP_COMMAND}
+ Should Be Equal As Integers ${rc} 0