From e41f46a29c4d635ee3f864e36cfd0ac123bac4ec Mon Sep 17 00:00:00 2001 From: dave kormann Date: Fri, 1 Nov 2019 11:59:43 -0400 Subject: [PATCH] IMPL: MC Xapp tests This change adds tests and supporting code for the measurement campaign (MC) XApp. The change also makes some cleanups to the robot files, moving utility keywords to a separate resource file and adding some missing license headers. signed-off-by: dave kormann Change-Id: I5ae1a41157f29fc95545aa18bad127b6c9efb968 --- .../public/properties/global_properties.robot | 27 +++++- .../public/properties/mcxapp_properties.robot | 23 +++++ .../configmap-src/public/testsuites/ete.robot | 14 +++ .../public/testsuites/health-check.robot | 56 +++++++---- .../configmap-src/public/testsuites/mcxapp.robot | 82 ++++++++++++++++ .../public/testsuites/ricdeployment.robot | 12 +-- .../public/testsuites/update_ric_page.robot | 14 +++ .../helm/nanobot/templates/job-ric-robot-run.yaml | 5 +- ric_robot_suite/helm/nanobot/values.yaml | 34 +++++-- .../ric-python-utils/ricutils/KubernetesEntity.py | 17 ++++ .../robot/resources/appmgr/appmgr_interface.robot | 19 +--- .../robot/resources/ric/placeholder_for_files | 0 .../robot/resources/ric/ric_utils.robot | 90 ++++++++++++++++++ .../robot/resources/xapps/mcxapp_properties.robot | 30 ++++++ .../robot/resources/xapps/placeholder_for_files | 0 ric_robot_suite/robot/testsuites/mcxapp.robot | 103 +++++++++++++++++++++ .../robot/testsuites/ricdeployment.robot | 14 +-- 17 files changed, 475 insertions(+), 65 deletions(-) create mode 100644 ric_robot_suite/helm/nanobot/configmap-src/public/properties/mcxapp_properties.robot create mode 100644 ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/mcxapp.robot delete mode 100644 ric_robot_suite/robot/resources/ric/placeholder_for_files create mode 100644 ric_robot_suite/robot/resources/ric/ric_utils.robot create mode 100644 ric_robot_suite/robot/resources/xapps/mcxapp_properties.robot delete mode 100644 ric_robot_suite/robot/resources/xapps/placeholder_for_files create mode 100644 ric_robot_suite/robot/testsuites/mcxapp.robot diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/properties/global_properties.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/properties/global_properties.robot index 58f22dd..3c15f62 100644 --- a/ric_robot_suite/helm/nanobot/configmap-src/public/properties/global_properties.robot +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/properties/global_properties.robot @@ -1,3 +1,17 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + {{- $domain := default "cluster.local" .Values.ric.cluster.domain }} {{- $ricpltNS := include "common.namespace.platform" . }} {{- $xappNS := include "common.namespace.xapp" . }} @@ -21,24 +35,31 @@ Documentation store all properties that can change or are used in multipl ${GLOBAL_APPLICATION_ID} {{ default "r0" .Values.ric.robot.release | printf "nanobot-%s" }} ${GLOBAL_BUILD_NUMBER} {{ default "0" .Values.ric.platform.build }} ${GLOBAL_RICPLT_NAMESPACE} {{ $ricpltNS }} +${GLOBAL_XAPP_NAMESPACE} {{ $xappNS }} # +{{- if .Values.ric.platform.components.appmgr }} ${GLOBAL_APPMGR_SERVER_PROTOCOL} {{ default "http" .Values.ric.platform.components.appmgr.protocol }} ${GLOBAL_INJECTED_APPMGR_IP_ADDR} {{ printf "%s.%s" (include "common.servicename.appmgr.http" .) $ricplt }} ${GLOBAL_APPMGR_SERVER_PORT} {{ include "common.serviceport.appmgr.http" . }} ${GLOBAL_INJECTED_APPMGR_USER} {{ .Values.ric.platform.components.appmgr.user }} ${GLOBAL_INJECTED_APPMGR_PASSWORD} {{ .Values.ric.platform.components.appmgr.password }} +{{- end }} # +{{- if .Values.ric.platform.components.e2mgr }} ${GLOBAL_E2MGR_SERVER_PROTOCOL} {{ default "http" .Values.ric.platform.components.e2mgr.protocol }} ${GLOBAL_INJECTED_E2MGR_IP_ADDR} {{ printf "%s.%s" (include "common.servicename.e2mgr.http" .) $ricplt }} ${GLOBAL_E2MGR_SERVER_PORT} {{ include "common.serviceport.e2mgr.http" . }} ${GLOBAL_INJECTED_E2MGR_USER} {{ .Values.ric.platform.components.e2mgr.user }} ${GLOBAL_INJECTED_E2MGR_PASSWORD} {{ .Values.ric.platform.components.e2mgr.password }} +{{- end }} # +{{- if .Values.ric.platform.components.rtmgr }} ${GLOBAL_RTMGR_SERVER_PROTOCOL} {{ default "http" .Values.ric.platform.components.rtmgr.protocol }} ${GLOBAL_INJECTED_RTMGR_IP_ADDR} {{ printf "%s.%s" (include "common.servicename.rtmgr.http" .) $ricplt }} ${GLOBAL_RTMGR_SERVER_PORT} {{ include "common.serviceport.e2mgr.http" . }} ${GLOBAL_INJECTED_RTMGR_USER} {{ .Values.ric.platform.components.rtmgr.user }} ${GLOBAL_INJECTED_RTMGR_PASSWORD} {{ .Values.ric.platform.components.rtmgr.password }} +{{- end }} # ${GLOBAL_INJECTED_DBAAS_IP_ADDR} {{ printf "%s.%s" (include "common.servicename.dbaas.tcp" .) $ricplt }} ${GLOBAL_DBAAS_SERVER_PORT} {{ include "common.serviceport.dbaas.tcp" . }} @@ -47,4 +68,8 @@ ${GLOBAL_TEST_XAPP} {{ default "xapp-std" .Values.ric.robot.en # ${GLOBAL_TEST_NODEB_NAME} {{ default "AAAA456789" .Values.ric.robot.environment.gNodeB.name }} ${GLOBAL_TEST_NODEB_ADDRESS} {{ default "10.0.0.3" .Values.ric.robot.environment.gNodeB.address }} -${GLOBAL_TEST_NODEB_PORT} {{ default "36421" .Values.ric.robot.environment.gNodeB.port }} \ No newline at end of file +${GLOBAL_TEST_NODEB_PORT} {{ default "36421" .Values.ric.robot.environment.gNodeB.port }} +# +${GLOBAL_DASH_SERVER_PROTOCOL} {{ default "http" .Values.ric.robot.environment.dashboard.protocol }} +${GLOBAL_DASH_SERVER_PORT} {{ default "31080" .Values.ric.robot.environment.dashboard.port }} +${GLOBAL_INJECTED_DASH_IP_ADDR} {{ default "127.0.0.1" .Values.ric.robot.environment.dashboard.port }} diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/properties/mcxapp_properties.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/properties/mcxapp_properties.robot new file mode 100644 index 0000000..6d69dd9 --- /dev/null +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/properties/mcxapp_properties.robot @@ -0,0 +1,23 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +*** Settings *** +Documentation This file contains configuration specific to the MC xapp. + +*** Variables *** +${GLOBAL_MCXAPP_LISTENER_NAME} {{ default "mc-xapp-listener" .Values.ric.xapp.mcxapp.listener.containername }} +${GLOBAL_MCXAPP_WRITER_NAME} {{ default "mc-xapp-writer" .Values.ric.xapp.mcxapp.writer.containername }} +@{GLOBAL_MCXAPP_WRITER_STATISTICS} {{- range .Values.ric.xapp.mcxapp.writer.statistics }} +... {{.}} + {{- end }} diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ete.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ete.robot index 8f8b282..35d12a3 100644 --- a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ete.robot +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ete.robot @@ -1,3 +1,17 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + *** Settings *** Documentation Executes the End To End Test cases ... diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/health-check.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/health-check.robot index a8faacf..5e5fdba 100644 --- a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/health-check.robot +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/health-check.robot @@ -1,20 +1,42 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + *** Settings *** -Documentation Testing RIC components are available via calls. -... -... Testing RIC components are available via calls. -Test Timeout 10 second -Resource ../resources/appmgr/appmgr_interface.robot -Resource ../resources/e2mgr/e2mgr_interface.robot -Resource ../resources/rtmgr/rtmgr_interface.robot +Documentation Run basic health checks for all known components which have one -*** Test Cases *** -Basic AppMgr Health Check - [Tags] health - Run AppMgr Health Check -Basic E2Mgr Health Check - [Tags] health - Run E2Mgr Health Check -Basic RtMgr Health Check - [Tags] health - Run RtMgr Health Check +Resource /robot/resources/global_properties.robot +Resource /robot/resources/ric/ric_utils.robot + +*** Test Cases *** +Basic Component Health Checks + [Documentation] For any defined RIC component with a health check keyword, + ... Run that keyword. "Health check" keywords have names of the + ... form "Run ${component} Health Check". + # This could have been entirely implemented in Helm; however, I wanted to + # allow for the possibility that it would be used (with some modification) + # by the ric-robot, which does not perform template expansion on testsuites. + [Tags] health + Set Test Variable ${finalStatus} PASS + :FOR ${component} IN @{GLOBAL_RICPLT_COMPONENTS} + \ Run Keyword And Ignore Error + ... Import Resource /robot/resources/${component}/${component}_interface.robot + \ ${healthCheck} = Set Variable Run ${component} Health Check + \ ${status} = Run Keyword If Present ${healthCheck} + \ ${finalStatus} = Set Variable If '${status}' == 'FAIL' FAIL ${finalStatus} + \ Run Keyword If '${status}' == 'FAIL' + ... Log ${component} is unhealthy + Run Keyword If '${finalStatus}' == 'FAIL' + ... Fail One or more Health Checks failed diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/mcxapp.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/mcxapp.robot new file mode 100644 index 0000000..756ff23 --- /dev/null +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/mcxapp.robot @@ -0,0 +1,82 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +*** Settings *** +Documentation Tests for the Measurement Campaign XApp + + +Resource /robot/resources/global_properties.robot +Resource /robot/resources/mcxapp_properties.robot + +Resource /robot/resources/ric/ric_utils.robot + +Library Collections +Library KubernetesEntity ${GLOBAL_XAPP_NAMESPACE} + +*** Variables *** +${listenerContainerName} mc-xapp-listener +${listenerStatRegex} ^[0-9]+\\s*\\[STAT\\]\\s*\\(mcl\\) +${recentListenerDrops} .*last 60s.*drops\\s*=\\s*([1-9][0-9]*) +${recentListenerErrors} .*last 60s.*errs\\s*=\\s*([1-9][0-9]*) +${writerVesSuccesses} .*successful\\s+ves\\s+posts\\s*-\\s*([1-9][0-9]*) +${writerVesErrors} .*failed\\s+ves\\s+posts\\s*-\\s*([1-9][0-9]*) + +*** Test Cases *** +XApp Should Be Available + [Tags] etetests xapptests mcxapptests + ${deploymentName} = Get From Dictionary ${GLOBAL_RICPLT_XAPPS} mcxapp + Set Suite Variable ${deploymentName} + ${deploy} = Deployment ${deploymentName} + ${status} = Most Recent Availability Condition @{deploy.status.conditions} + Should Be Equal As Strings ${status} True ignore_case=True + +Listener Should Not Be Dropping Messages + [Tags] etetests xapptests mcxapptests + ${log} = Most Recent Container Logs ${deploymentName} + ... ${GLOBAL_MCXAPP_LISTENER_NAME} + ... ${listenerStatRegex} + Should Not Contain Match ${log} regexp=${recentListenerDrops} + +Listener Should Not Be Producing Errors + [Tags] etetests xapptests mcxapptests + ${log} = Most Recent Container Logs ${deploymentName} + ... ${GLOBAL_MCXAPP_LISTENER_NAME} + ... ${listenerStatRegex} + Should Not Contain Match ${log} regexp=${recentListenerErrors} + +Writer Should Be Successfully Sending Statistics + [Tags] etetests xapptests mcxapptests + Set Test Variable ${finalStatus} PASS + :FOR ${stat} IN @{GLOBAL_MCXAPP_WRITER_STATISTICS} + \ ${statRE} = Regexp Escape ${stat} + \ ${log} = Most Recent Container Logs ${deploymentName} + ... ${GLOBAL_MCXAPP_WRITER_NAME} + ... ^${statRE}:\\s+successful\\s+ves\\s+posts\\.* + \ ${status} ${u} = Run Keyword And Ignore Error + ... Should Contain Match ${log} regexp=${writerVesSuccesses} + \ ${finalStatus} = Set Variable If "${status}" == "FAIL" + ... FAIL + ... ${finalStatus} + \ Run Keyword If "${status}" == "FAIL" + ... Log No messages have been sent to VES for ${stat} + \ ${status} ${u} = Run Keyword And Ignore Error + ... Should Not Contain Match ${log} regexp=${writerVesErrors} + \ ${finalStatus} = Set Variable If "${status}" == "FAIL" + ... FAIL + ... ${finalStatus} + \ Run Keyword If "${status}" == "FAIL" + ... Log ${stat} is producing errors logging to VES + Run Keyword If "${finalStatus}" == "FAIL" + ... Fail One or more statistics is not being succesfully logged + diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ricdeployment.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ricdeployment.robot index 3417675..85920f7 100644 --- a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ricdeployment.robot +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/ricdeployment.robot @@ -18,6 +18,8 @@ Documentation Tests for the existence and functionality of RIC components Resource /robot/resources/global_properties.robot +Resource /robot/resources/ric/ric_utils.robot + Library KubernetesEntity ${GLOBAL_RICPLT_NAMESPACE} Library Collections Library String @@ -30,13 +32,3 @@ Ensure RIC components are deployed and available \ ${deploy} = Deployment ${deploymentName} \ ${status} = Most Recent Availability Condition @{deploy.status.conditions} \ Should Be Equal As Strings ${status} True ignore_case=True msg=${Component} is not available - -*** Keywords *** -Most Recent Availability Condition - # this makes the probably-unsafe assumption that the conditions are ordered - # temporally. - [Arguments] @{Conditions} - ${status} = Set Variable 'False' - :FOR ${Condition} IN @{Conditions} - \ ${status} = Set Variable If '${Condition.type}' == 'Available' ${Condition.status} ${status} - [Return] ${status} diff --git a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/update_ric_page.robot b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/update_ric_page.robot index a2efd1c..5fab634 100644 --- a/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/update_ric_page.robot +++ b/ric_robot_suite/helm/nanobot/configmap-src/public/testsuites/update_ric_page.robot @@ -1,3 +1,17 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + *** Settings *** Documentation Initializes RIC Test Web Page and Password diff --git a/ric_robot_suite/helm/nanobot/templates/job-ric-robot-run.yaml b/ric_robot_suite/helm/nanobot/templates/job-ric-robot-run.yaml index 2ca4ffb..c476853 100644 --- a/ric_robot_suite/helm/nanobot/templates/job-ric-robot-run.yaml +++ b/ric_robot_suite/helm/nanobot/templates/job-ric-robot-run.yaml @@ -72,7 +72,7 @@ metadata: namespace: {{ $xappNamespace }} rules: - apiGroups: [""] - resources: ["pods", "services"] + resources: ["pods", "pods/log", "services"] verbs: ["get", "list"] - apiGroups: ["apps"] resources: ["deployments", "daemonsets", "replicasets", "statefulsets"] @@ -103,10 +103,11 @@ metadata: name: {{ $jobName }}-ric-robot-run namespace: {{ .Release.Namespace }} spec: + backoffLimit: {{ default 0 .Values.ric.robot.job.backoffLimit }} template: spec: serviceAccountName: {{ $serviceAccountName }} - restartPolicy: Never + restartPolicy: {{ default "Never" .Values.ric.robot.job.restartPolicy }} initContainers: - name: {{ $jobName }}-generate-robot-kubeconfig {{ with .Values.images.ric.robot.job.init }} diff --git a/ric_robot_suite/helm/nanobot/values.yaml b/ric_robot_suite/helm/nanobot/values.yaml index 0abfda0..16ac5a6 100644 --- a/ric_robot_suite/helm/nanobot/values.yaml +++ b/ric_robot_suite/helm/nanobot/values.yaml @@ -54,20 +54,37 @@ ric: # platform source tree releaseName: r0 components: + a1mediator: appmgr: user: test password: test - rtmgr: - user: test - password: test + dbaas: e2mgr: user: test password: test e2term: - a1mediator: + rtmgr: + user: test + password: test + submgr: xapp: - anr: - servicename: anr + mcxapp: + listener: + containername: mc-xapp-listener + writer: + containername: mc-xapp-writer + # statistics sent to ves by the writer. the tests + # will check that these are actually being sent + statistics: + - mc_connected_cnt + - mc_connection_stats + - mc_connects_cnt + - mc_disconnects_cnt + - mc_unique_ue_cnt + - rrcx_pdf_serv_cell + - rrcx_pdf_serv_gnb + - rrcx_stats_serv_cell + - rrcx_stats_serv_gnb robot: release: r1 # @@ -96,7 +113,7 @@ ric: # set this to a true value to cause # the job to fail (and, typically, be resubmitted) # when tests fail - failOnTestFail: false + failOnTestFail: true serviceAccount: # by default, the job will create # a temporary serviceaccount and @@ -123,3 +140,6 @@ ric: name: AAAA456789 address: 10.0.0.3 port: 36421 + dashboard: + address: 10.1.0.1 + port: 31080 \ No newline at end of file diff --git a/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py b/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py index 7b2535a..8944167 100644 --- a/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py +++ b/ric_robot_suite/ric-python-utils/ricutils/KubernetesEntity.py @@ -17,6 +17,7 @@ from kubernetes import client, config import string import random import time +import sys # This library provides a massively-simplified interface to the kubernetes # API library to reduce bloat in robot tests. @@ -82,3 +83,19 @@ class KubernetesEntity(object): timeout -= 1 raise TimeoutError('Kubernetes timeout waiting for ' + name + ' to become available') + def RetrievePodsForDeployment(self, name): + # return the pod names associated with a deployment + d = self.Deployment(name) + labels = d.spec.selector.match_labels + pods = self._k8sCore.list_namespaced_pod(self._ns, + label_selector=",".join(map(lambda k: k + "=" + labels[k], + labels))) + return map(lambda i: i.metadata.name, pods.items) + + def RetrieveLogForPod(self, pod, container='', tail=sys.maxsize): + # not really an "entity" thing per se, but. + # kinda want to include timestamps, but i don't have a use case for them. + return self._k8sCore.read_namespaced_pod_log(namespace=self._ns, + name=pod, + container=container, + tail_lines=tail).split('\n')[0:-1] diff --git a/ric_robot_suite/robot/resources/appmgr/appmgr_interface.robot b/ric_robot_suite/robot/resources/appmgr/appmgr_interface.robot index 3f14604..c346e95 100644 --- a/ric_robot_suite/robot/resources/appmgr/appmgr_interface.robot +++ b/ric_robot_suite/robot/resources/appmgr/appmgr_interface.robot @@ -5,6 +5,8 @@ Library RequestsLibrary Resource ../global_properties.robot +Resource ../ric/ric_utils.robot + *** Variables *** ${APPMGR_BASE_PATH} /ric/v1/xapps ${APPMGR_ENDPOINT} ${GLOBAL_APPMGR_SERVER_PROTOCOL}://${GLOBAL_INJECTED_APPMGR_IP_ADDR}:${GLOBAL_APPMGR_SERVER_PORT} @@ -104,20 +106,3 @@ Run AppMgr DELETE Request ${headers} = Create Dictionary Accept=application/json Content-Type=application/json ${resp} = Delete Request roboAppmgrDelete ${APPMGR_BASE_PATH}${path} headers=${headers} [Return] ${resp} - - -# a few useful list routines that should probably live elsewhere -Pluck - [Documentation] Get the values of a specific key from a list of dictionaries - [Arguments] ${k} ${l} - @{names} = Evaluate filter(lambda v: v != None, [i.get('${k}', None) for i in ${l}]) - [Return] ${names} - -Subtract From List - [Documentation] Remove the elements of the second argument from the first - [Arguments] ${x} ${y} - ${diff} = Run Keyword If ${y} - ... Evaluate filter(lambda v: v not in ${y}, ${x}) - ... ELSE - ... Set Variable ${x} - [Return] ${diff} diff --git a/ric_robot_suite/robot/resources/ric/placeholder_for_files b/ric_robot_suite/robot/resources/ric/placeholder_for_files deleted file mode 100644 index e69de29..0000000 diff --git a/ric_robot_suite/robot/resources/ric/ric_utils.robot b/ric_robot_suite/robot/resources/ric/ric_utils.robot new file mode 100644 index 0000000..30ed937 --- /dev/null +++ b/ric_robot_suite/robot/resources/ric/ric_utils.robot @@ -0,0 +1,90 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +*** Settings *** +Documentation A library of utility keywords that may be useful +... in various test suites. + +Library Collections + +*** Keywords *** +# +# Kubernetes Utilities +Most Recent Availability Condition + # this makes the probably-unsafe assumption that the conditions are ordered + # temporally. + [Arguments] @{Conditions} + ${status} = Set Variable 'False' + :FOR ${Condition} IN @{Conditions} + \ ${status} = Set Variable If '${Condition.type}' == 'Available' ${Condition.status} ${status} + [Return] ${status} + +Most Recent Container Logs + [Arguments] ${deployment} ${container}=${EMPTY} ${regex}=${EMPTY} + ${pods} = Retrieve Pods For Deployment ${deployment} + ${logs} = Create List + :FOR ${pod} IN @{pods} + \ ${log} = Retrieve Log For Pod ${pod} ${container} + \ Should Not Be Empty ${log} No log entries for ${pod}/${container} + \ ${line} = Run Keyword If "${regex}" != "${EMPTY}" + ... Most Recent Match ${log} ${regex} + ... ELSE + ... Get From List ${log} -1 + \ Append To List ${logs} ${line} + [Return] ${logs} + +# +# Robot metatools +Run Keyword If Present + [Documentation] Run the given keyword, ignoring errors and returning status, if it exists. + ... Returns "PASS" if the keyword does not exist. + [Arguments] ${kw} + ${exists} ${u} = Run Keyword And Ignore Error + ... Keyword Should Exist ${kw} + ${status} ${u} = Run Keyword If '${exists}' == 'PASS' + ... Run Keyword And Ignore Error ${kw} + ... ELSE + ... Set Variable PASS unused + [Return] ${status} + +# +# Data manipulation +Toggle Flag + [Documentation] Apply "not" to a boolean flag + [Arguments] ${flag} + ${bFlag} = Convert To Boolean ${flag} + ${bFlag} = Set Variable If ${bFlag} ${false} ${true} + [Return] ${bFlag} + +Most Recent Match + [Arguments] ${list} ${regex} + ${matches} = Get Matches ${list} regexp=${regex} + Should Not Be Empty ${matches} No log entries matching ${regex} + ${match} = Get From List ${matches} -1 + [Return] ${match} + +Pluck + [Documentation] Get the values of a specific key from a list of dictionaries + [Arguments] ${k} ${l} + @{names} = Evaluate filter(lambda v: v != None, [i.get('${k}', None) for i in ${l}]) + [Return] ${names} + +Subtract From List + [Documentation] Remove the elements of the second argument from the first + [Arguments] ${x} ${y} + ${diff} = Run Keyword If ${y} + ... Evaluate filter(lambda v: v not in ${y}, ${x}) + ... ELSE + ... Set Variable ${x} + [Return] ${diff} diff --git a/ric_robot_suite/robot/resources/xapps/mcxapp_properties.robot b/ric_robot_suite/robot/resources/xapps/mcxapp_properties.robot new file mode 100644 index 0000000..c9ca587 --- /dev/null +++ b/ric_robot_suite/robot/resources/xapps/mcxapp_properties.robot @@ -0,0 +1,30 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +*** Settings *** +Documentation This file contains configuration specific to the MC xapp. + +*** Variables *** +${GLOBAL_MCXAPP_LISTENER_NAME} mc-xapp-listener +${GLOBAL_MCXAPP_WRITER_NAME} mc-xapp-writer +@{GLOBAL_MCXAPP_WRITER_STATISTICS} +... mc_connected_cnt +... mc_connection_stats +... mc_connects_cnt +... mc_disconnects_cnt +... mc_unique_ue_cnt +... rrcx_pdf_serv_cell +... rrcx_pdf_serv_gnb +... rrcx_stats_serv_cell +... rrcx_stats_serv_gnb diff --git a/ric_robot_suite/robot/resources/xapps/placeholder_for_files b/ric_robot_suite/robot/resources/xapps/placeholder_for_files deleted file mode 100644 index e69de29..0000000 diff --git a/ric_robot_suite/robot/testsuites/mcxapp.robot b/ric_robot_suite/robot/testsuites/mcxapp.robot new file mode 100644 index 0000000..dd85e45 --- /dev/null +++ b/ric_robot_suite/robot/testsuites/mcxapp.robot @@ -0,0 +1,103 @@ +# Copyright (c) 2019 AT&T Intellectual Property. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +*** Settings *** +Documentation Tests for the Measurement Campaign XApp + +Resource ../resources/xapps/mcxapp_properties.robot +Resource ../resources/global_properties.robot + +Library Collections +Library KubernetesEntity ${GLOBAL_XAPP_NAMESPACE} + +*** Variables *** +${deploymentName} = ${GLOBAL_XAPP_NAMESPACE}-mcxapp +${listenerContainerName} = mc-xapp-listener +${listenerStatRegex} = ^[0-9]+\\s*\\[STAT\\]\\s*\\(mcl\\) +${recentListenerDrops} = last 60s.*drops\\s*=\\s*[1-9] +${recentListenerErrors} = last 60s.*errs\\s*=\\s*[1-9] + +*** Test Cases *** +MC XApp Should Be Available + [Tags] etetests xapptests mcxapptests + ${deploy} = Deployment ${deploymentName} + ${status} = Most Recent Availability Condition @{deploy.status.conditions} + Should Be Equal As Strings ${status} True ignore_case=True + +MC XApp Listener Should Not Be Dropping Messages + [Tags] etetests xapptests mcxapptests + ${log} = Most Recent Container Log ${listenerContainerName} ${listenerStatRegex} + Should Not Contain Match ${log} ${recentListenerDrops} + +MC XApp Listener Should Not Be Producing Errors + [Tags] etetests xapptests mcxapptests + ${log} = Most Recent Container Log ${listenerContainerName} ${listenerStatRegex} + Should Not Contain Match ${log} ${recentListenerErrors} + +Writer Should Be Successfully Sending Statistics + [Tags] etetests xapptests mcxapptests + Set Test Variable ${finalStatus} PASS + :FOR ${stat} IN @{GLOBAL_MCXAPP_WRITER_STATISTICS} + \ ${statRE} = Regexp Escape ${stat} + \ ${log} = Most Recent Container Log + ... ${GLOBAL_MCXAPP_WRITER_NAME} + ... ^${statRE}:\\s+successful\\s+ves\\s+posts\\.* + \ ${status} ${u} = Run Keyword And Ignore Error + ... Should Contain Match ${log} regexp=${writerVesSuccesses} + \ ${finalStatus} = Set Variable If "${status}" == "FAIL" + ... FAIL + ... ${finalStatus} + \ Run Keyword If "${status}" == "FAIL" + ... Log No messages have been sent to VES for ${stat} + \ ${status} ${u} = Run Keyword And Ignore Error + ... Should Not Contain Match ${log} regexp=${writerVesErrors} + \ ${finalStatus} = Set Variable If "${status}" == "FAIL" + ... FAIL + ... ${finalStatus} + \ Run Keyword If "${status}" == "FAIL" + ... Log ${stat} is producing errors logging to VES + Run Keyword If "${finalStatus}" == "FAIL" + ... Fail One or more statistics is not being succesfully logged + +*** Keywords *** +Most Recent Availability Condition + # this makes the probably-unsafe assumption that the conditions are ordered + # temporally. + [Arguments] @{Conditions} + ${status} = Set Variable 'False' + :FOR ${Condition} IN @{Conditions} + \ ${status} = Set Variable If '${Condition.type}' == 'Available' ${Condition.status} ${status} + [Return] ${status} + +Most Recent Match + [Arguments] ${list} ${regex} + ${matches} = Get Matches ${list} regexp=${regex} + Should Not Be Empty ${matches} No log entries matching ${regex} + ${match} = Get From List ${matches} -1 + [Return] ${match} + +Most Recent Container Log + [Arguments] ${container}=${EMPTY} ${regex}=${EMPTY} + ${pods} = Retrieve Pods For Deployment ${deploymentName} + ${logs} = Create List + :FOR ${pod} IN @{pods} + \ ${log} = Retrieve Log For Pod ${pod} ${container} + \ Should Not Be Empty ${log} No log entries for ${pod}/${container} + \ ${line} = Run Keyword If "${regex}" != "${EMPTY}" + ... Most Recent Match ${log} ${regex} + ... ELSE + ... Get From List ${log} -1 + \ Append To List ${logs} ${line} + [Return] ${logs} + diff --git a/ric_robot_suite/robot/testsuites/ricdeployment.robot b/ric_robot_suite/robot/testsuites/ricdeployment.robot index 5bede0a..db952c2 100644 --- a/ric_robot_suite/robot/testsuites/ricdeployment.robot +++ b/ric_robot_suite/robot/testsuites/ricdeployment.robot @@ -16,7 +16,9 @@ *** Settings *** Documentation Tests for the existence and functionality of RIC components -Resource /robot/resources/global_properties.robot +Resource ../global_properties.robot + +Resource ../ric/ric_utils.robot Library KubernetesEntity ${GLOBAL_RICPLT_NAMESPACE} Library Collections @@ -30,13 +32,3 @@ Deployments \ ${deploy} = Deployment ${deploymentName} \ ${status} = Most Recent Availability Condition @{deploy.status.conditions} \ Should Be Equal As Strings ${status} True ignore_case=True msg=${Component} is not available - -*** Keywords *** -Most Recent Availability Condition - # this makes the probably-unsafe assumption that the conditions are ordered - # temporally. - [Arguments] @{Conditions} - ${status} = Set Variable 'False' - :FOR ${Condition} IN @{Conditions} - \ ${status} = Set Variable If '${Condition.type}' == 'Available' ${Condition.status} ${status} - [Return] ${status} -- 2.16.6