teststeps: Improvements of step driven TC 45/48645/3
authorMartin Klozik <martinx.klozik@intel.com>
Mon, 11 Dec 2017 13:37:40 +0000 (13:37 +0000)
committerMartin Klozik <martinx.klozik@intel.com>
Tue, 12 Dec 2017 14:50:23 +0000 (14:50 +0000)
This patch adds support of access to VMs deployed automatically
by deployment scenario (e.g. pvp, pvvp4, etc.). It also modifies
filter for checking output of executed commands to correctly
handle different end of line encodings (i.e. \n vs. \n\r).

JIRA: VSPERF-539

Change-Id: Ifc796d992b90e316bad5853aaefce79e439e294d
Signed-off-by: Martin Klozik <martinx.klozik@intel.com>
Reviewed-by: Al Morton <acmorton@att.com>
Reviewed-by: Christian Trautman <ctrautma@redhat.com>
Reviewed-by: Sridhar Rao <sridhar.rao@spirent.com>
Reviewed-by: Trevor Cooper <trevor.cooper@intel.com>
docs/testing/user/userguide/teststeps.rst
testcases/testcase.py
tools/functions.py

index 8be6731..40cc732 100644 (file)
@@ -131,6 +131,21 @@ of supported objects and their most common functions follows:
             ['vnf2', 'stop'],
             ['vnf1', 'stop'],
 
+    * ``VNF[ID]`` - provides access to VNFs deployed automatically by testcase deployment
+      scenario. For Example ``pvvp`` deployment automatically starts two VNFs before any
+      TestStep is executed. It is possible to access these VNFs by VNF0 and VNF1 labels.
+
+      List of supported functions is identical to ``vnf[ID]`` option above except functions
+      ``start`` and ``stop``.
+
+      Examples:
+
+      .. code-block:: python
+
+          ['VNF0', 'execute_and_wait', 'ifconfig eth2 5.5.5.1/24 up'],
+          ['VNF1', 'execute_and_wait', 'ifconfig eth2 5.5.5.2/24 up', 120, 'root.*#'],
+          ['VNF2', 'execute_and_wait', 'ping -c1 5.5.5.1'],
+
     * ``trafficgen`` - triggers traffic generation
 
       List of supported functions:
index 37cdefa..b3300b8 100644 (file)
@@ -78,6 +78,7 @@ class TestCase(object):
         self._step_result_mapping = {}
         self._step_status = None
         self._step_send_traffic = False # indication if send_traffic was called within test steps
+        self._vnf_list = []
         self._testcase_run_time = None
 
         S.setValue('VSWITCH', cfg.get('vSwitch', S.getValue('VSWITCH')))
@@ -201,6 +202,8 @@ class TestCase(object):
             loader.get_vnf_class(),
             len(self._step_vnf_list))
 
+        self._vnf_list = self._vnf_ctl.get_vnfs()
+
         # verify enough hugepages are free to run the testcase
         if not self._check_for_enough_hugepages():
             raise RuntimeError('Not enough hugepages free to run test.')
@@ -792,10 +795,21 @@ class TestCase(object):
                     # so it is not sent again after the execution of teststeps
                     self._step_send_traffic = True
             elif step[0].startswith('vnf'):
+                # use vnf started within TestSteps
                 if not self._step_vnf_list[step[0]]:
                     # initialize new VM
                     self._step_vnf_list[step[0]] = loader.get_vnf_class()()
                 test_object = self._step_vnf_list[step[0]]
+            elif step[0].startswith('VNF'):
+                if step[1] in ('start', 'stop'):
+                    raise RuntimeError("Cannot execute start() or stop() method of "
+                                       "VNF deployed automatically by scenario.")
+                # use vnf started by scenario deployment (e.g. pvp)
+                vnf_index = int(step[0][3:])
+                try:
+                    test_object = self._vnf_list[vnf_index]
+                except IndexError:
+                    raise RuntimeError("VNF with index {} is not running.".format(vnf_index))
             elif step[0] == 'wait':
                 input(os.linesep + "Step {}: Press Enter to continue with "
                       "the next step...".format(i) + os.linesep + os.linesep)
index c0d1e5f..d35f1f8 100644 (file)
@@ -190,17 +190,15 @@ def filter_output(output, regex):
     """
     result = []
     if isinstance(output, str):
-        for line in output.split('\n'):
+        for line in output.splitlines():
             result += re.findall(regex, line)
-        return result
-    elif isinstance(output, list) or isinstance(output, tuple):
-        tmp_res = []
+    elif isinstance(output, (list, tuple)):
         for item in output:
-            tmp_res.append(filter_output(item, regex))
-        return tmp_res
+            result.append(filter_output(item, regex))
     else:
         raise RuntimeError('Only strings and lists are supported by filter_output(), '
                            'but output has type {}'.format(type(output)))
+    return result
 
 def format_description(desc, length):
     """ Split description into multiple lines based on given line length.