Code Review
/
vpp.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
tests: move bier tests to src/vnet/bier/test
[vpp.git]
/
test
/
framework.py
diff --git
a/test/framework.py
b/test/framework.py
index
39fd37f
..
f577513
100644
(file)
--- a/
test/framework.py
+++ b/
test/framework.py
@@
-2,10
+2,12
@@
from __future__ import print_function
import gc
from __future__ import print_function
import gc
+import logging
import sys
import os
import select
import signal
import sys
import os
import select
import signal
+import subprocess
import unittest
import tempfile
import time
import unittest
import tempfile
import time
@@
-39,18
+41,11
@@
from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
from scapy.layers.inet6 import ICMPv6DestUnreach, ICMPv6EchoRequest
from scapy.layers.inet6 import ICMPv6EchoReply
from scapy.layers.inet6 import ICMPv6DestUnreach, ICMPv6EchoRequest
from scapy.layers.inet6 import ICMPv6EchoReply
-if os.name == 'posix' and sys.version_info[0] < 3:
- # using subprocess32 is recommended by python official documentation
- # @ https://docs.python.org/2/library/subprocess.html
- import subprocess32 as subprocess
-else:
- import subprocess
-
-# Python2/3 compatible
-try:
- input = raw_input
-except NameError:
- pass
+logger = logging.getLogger(__name__)
+
+# Set up an empty logger for the testcase that can be overridden as necessary
+null_logger = logging.getLogger('VppTestCase')
+null_logger.addHandler(logging.NullHandler())
PASS = 0
FAIL = 1
PASS = 0
FAIL = 1
@@
-217,12
+212,11
@@
def _running_extended_tests():
running_extended_tests = _running_extended_tests()
running_extended_tests = _running_extended_tests()
-def _running_on_centos():
- os_id = os.getenv("OS_ID", "")
- return True if "centos" in os_id.lower() else False
+def _running_gcov_tests():
+ return BoolEnvironmentVariable("GCOV_TESTS")
-running_
on_centos = _running_on_cento
s()
+running_
gcov_tests = _running_gcov_test
s()
class KeepAliveReporter(object):
class KeepAliveReporter(object):
@@
-268,6
+262,7
@@
class VppTestCase(unittest.TestCase):
extra_vpp_punt_config = []
extra_vpp_plugin_config = []
extra_vpp_punt_config = []
extra_vpp_plugin_config = []
+ logger = null_logger
vapi_response_timeout = 5
@property
vapi_response_timeout = 5
@property
@@
-283,6
+278,11
@@
class VppTestCase(unittest.TestCase):
else:
return 0
else:
return 0
+ @classmethod
+ def force_solo(cls):
+ """ if the test case class is timing-sensitive - return true """
+ return False
+
@classmethod
def instance(cls):
"""Return the instance of this testcase"""
@classmethod
def instance(cls):
"""Return the instance of this testcase"""
@@
-374,6
+374,16
@@
class VppTestCase(unittest.TestCase):
if not hasattr(cls, "worker_config"):
cls.worker_config = ""
if not hasattr(cls, "worker_config"):
cls.worker_config = ""
+ default_variant = os.getenv("VARIANT")
+ if default_variant is not None:
+ default_variant = "defaults { %s 100 }" % default_variant
+ else:
+ default_variant = ""
+
+ api_fuzzing = os.getenv("API_FUZZ")
+ if api_fuzzing is None:
+ api_fuzzing = 'off'
+
cls.vpp_cmdline = [cls.vpp_bin, "unix",
"{", "nodaemon", debug_cli, "full-coredump",
coredump_size, "runtime-dir", cls.tempdir, "}",
cls.vpp_cmdline = [cls.vpp_bin, "unix",
"{", "nodaemon", debug_cli, "full-coredump",
coredump_size, "runtime-dir", cls.tempdir, "}",
@@
-381,13
+391,19
@@
class VppTestCase(unittest.TestCase):
"prefix", cls.shm_prefix, "}", "cpu", "{",
"main-core", str(cpu_core_number),
cls.worker_config, "}",
"prefix", cls.shm_prefix, "}", "cpu", "{",
"main-core", str(cpu_core_number),
cls.worker_config, "}",
+ "physmem", "{", "max-size", "32m", "}",
"statseg", "{", "socket-name", cls.stats_sock, "}",
"socksvr", "{", "socket-name", cls.api_sock, "}",
"statseg", "{", "socket-name", cls.stats_sock, "}",
"socksvr", "{", "socket-name", cls.api_sock, "}",
+ "node { ", default_variant, "}",
+ "api-fuzz {", api_fuzzing, "}",
"plugins",
"{", "plugin", "dpdk_plugin.so", "{", "disable",
"}", "plugin", "rdma_plugin.so", "{", "disable",
"plugins",
"{", "plugin", "dpdk_plugin.so", "{", "disable",
"}", "plugin", "rdma_plugin.so", "{", "disable",
+ "}", "plugin", "lisp_unittest_plugin.so", "{",
+ "enable",
"}", "plugin", "unittest_plugin.so", "{", "enable",
"}"] + cls.extra_vpp_plugin_config + ["}", ]
"}", "plugin", "unittest_plugin.so", "{", "enable",
"}"] + cls.extra_vpp_plugin_config + ["}", ]
+
if cls.extra_vpp_punt_config is not None:
cls.vpp_cmdline.extend(cls.extra_vpp_punt_config)
if plugin_path is not None:
if cls.extra_vpp_punt_config is not None:
cls.vpp_cmdline.extend(cls.extra_vpp_punt_config)
if plugin_path is not None:
@@
-445,8
+461,7
@@
class VppTestCase(unittest.TestCase):
try:
cls.vpp = subprocess.Popen(cmdline,
stdout=subprocess.PIPE,
try:
cls.vpp = subprocess.Popen(cmdline,
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- bufsize=1)
+ stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
cls.logger.critical("Subprocess returned with non-0 return code: ("
"%s)", e.returncode)
except subprocess.CalledProcessError as e:
cls.logger.critical("Subprocess returned with non-0 return code: ("
"%s)", e.returncode)
@@
-567,26
+582,37
@@
class VppTestCase(unittest.TestCase):
"VPP-API connection failed, did you forget "
"to 'continue' VPP from within gdb?", RED))
raise
"VPP-API connection failed, did you forget "
"to 'continue' VPP from within gdb?", RED))
raise
+ except vpp_papi.VPPRuntimeError as e:
+ cls.logger.debug("%s" % e)
+ cls.quit()
+ raise
except Exception as e:
cls.logger.debug("Exception connecting to VPP: %s" % e)
except Exception as e:
cls.logger.debug("Exception connecting to VPP: %s" % e)
-
cls.quit()
raise
cls.quit()
raise
+ @classmethod
+ def _debug_quit(cls):
+ if (cls.debug_gdbserver or cls.debug_gdb):
+ try:
+ cls.vpp.poll()
+
+ if cls.vpp.returncode is None:
+ print()
+ print(double_line_delim)
+ print("VPP or GDB server is still running")
+ print(single_line_delim)
+ input("When done debugging, press ENTER to kill the "
+ "process and finish running the testcase...")
+ except AttributeError:
+ pass
+
@classmethod
def quit(cls):
"""
Disconnect vpp-api, kill vpp and cleanup shared memory files
"""
@classmethod
def quit(cls):
"""
Disconnect vpp-api, kill vpp and cleanup shared memory files
"""
- if (cls.debug_gdbserver or cls.debug_gdb) and hasattr(cls, 'vpp'):
- cls.vpp.poll()
- if cls.vpp.returncode is None:
- print()
- print(double_line_delim)
- print("VPP or GDB server is still running")
- print(single_line_delim)
- input("When done debugging, press ENTER to kill the "
- "process and finish running the testcase...")
+ cls._debug_quit()
# first signal that we want to stop the pump thread, then wake it up
if hasattr(cls, 'pump_thread_stop_flag'):
# first signal that we want to stop the pump thread, then wake it up
if hasattr(cls, 'pump_thread_stop_flag'):
@@
-597,7
+623,7
@@
class VppTestCase(unittest.TestCase):
cls.logger.debug("Waiting for pump thread to stop")
cls.pump_thread.join()
if hasattr(cls, 'vpp_stderr_reader_thread'):
cls.logger.debug("Waiting for pump thread to stop")
cls.pump_thread.join()
if hasattr(cls, 'vpp_stderr_reader_thread'):
- cls.logger.debug("Waiting for std
d
err pump to stop")
+ cls.logger.debug("Waiting for stderr pump to stop")
cls.vpp_stderr_reader_thread.join()
if hasattr(cls, 'vpp'):
cls.vpp_stderr_reader_thread.join()
if hasattr(cls, 'vpp'):
@@
-743,7
+769,12
@@
class VppTestCase(unittest.TestCase):
@classmethod
def get_vpp_time(cls):
@classmethod
def get_vpp_time(cls):
- return float(cls.vapi.cli('show clock').replace("Time now ", ""))
+ # processes e.g. "Time now 2.190522, Wed, 11 Mar 2020 17:29:54 GMT"
+ # returns float("2.190522")
+ timestr = cls.vapi.cli('show clock')
+ head, sep, tail = timestr.partition(',')
+ head, sep, tail = head.partition('Time now')
+ return float(tail)
@classmethod
def sleep_on_vpp_time(cls, sec):
@classmethod
def sleep_on_vpp_time(cls, sec):
@@
-1111,23
+1142,22
@@
class VppTestCase(unittest.TestCase):
time.sleep(0)
return
time.sleep(0)
return
- if hasattr(cls, 'logger'):
- cls.logger.debug("Starting sleep for %es (%s)", timeout, remark)
+ cls.logger.debug("Starting sleep for %es (%s)", timeout, remark)
before = time.time()
time.sleep(timeout)
after = time.time()
before = time.time()
time.sleep(timeout)
after = time.time()
- if
hasattr(cls, 'logger') and
after - before > 2 * timeout:
+ if after - before > 2 * timeout:
cls.logger.error("unexpected self.sleep() result - "
"slept for %es instead of ~%es!",
after - before, timeout)
cls.logger.error("unexpected self.sleep() result - "
"slept for %es instead of ~%es!",
after - before, timeout)
- if hasattr(cls, 'logger'):
-
cls.logger.debug(
+
+ cls.logger.debug(
"Finished sleep (%s) - slept %es (wanted %es)",
remark, after - before, timeout)
"Finished sleep (%s) - slept %es (wanted %es)",
remark, after - before, timeout)
- def pg_send(self, intf, pkts):
+ def pg_send(self, intf, pkts
, worker=None
):
self.vapi.cli("clear trace")
self.vapi.cli("clear trace")
- intf.add_stream(pkts)
+ intf.add_stream(pkts
, worker=worker
)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@
-1140,10
+1170,10
@@
class VppTestCase(unittest.TestCase):
i.assert_nothing_captured(remark=remark)
timeout = 0.1
i.assert_nothing_captured(remark=remark)
timeout = 0.1
- def send_and_expect(self, intf, pkts, output, n_rx=None):
+ def send_and_expect(self, intf, pkts, output, n_rx=None
, worker=None
):
if not n_rx:
n_rx = len(pkts)
if not n_rx:
n_rx = len(pkts)
- self.pg_send(intf, pkts)
+ self.pg_send(intf, pkts
, worker=worker
)
rx = output.get_capture(n_rx)
return rx
rx = output.get_capture(n_rx)
return rx
@@
-1261,22
+1291,20
@@
class VppTestResult(unittest.TestResult):
failed_dir,
'%s-FAILED' %
os.path.basename(self.current_test_case_info.tempdir))
failed_dir,
'%s-FAILED' %
os.path.basename(self.current_test_case_info.tempdir))
- if self.current_test_case_info.logger:
-
self.current_test_case_info.logger.debug(
+
+ self.current_test_case_info.logger.debug(
"creating a link to the failed test")
"creating a link to the failed test")
-
self.current_test_case_info.logger.debug(
+ self.current_test_case_info.logger.debug(
"os.symlink(%s, %s)" %
(self.current_test_case_info.tempdir, link_path))
if os.path.exists(link_path):
"os.symlink(%s, %s)" %
(self.current_test_case_info.tempdir, link_path))
if os.path.exists(link_path):
- if self.current_test_case_info.logger:
- self.current_test_case_info.logger.debug(
+ self.current_test_case_info.logger.debug(
'symlink already exists')
else:
os.symlink(self.current_test_case_info.tempdir, link_path)
except Exception as e:
'symlink already exists')
else:
os.symlink(self.current_test_case_info.tempdir, link_path)
except Exception as e:
- if self.current_test_case_info.logger:
- self.current_test_case_info.logger.error(e)
+ self.current_test_case_info.logger.error(e)
def send_result_through_pipe(self, test, result):
if hasattr(self, 'test_framework_result_pipe'):
def send_result_through_pipe(self, test, result):
if hasattr(self, 'test_framework_result_pipe'):
@@
-1371,9
+1399,19
@@
class VppTestResult(unittest.TestResult):
"""
def print_header(test):
"""
def print_header(test):
+ test_doc = getdoc(test)
+ if not test_doc:
+ raise Exception("No doc string for test '%s'" % test.id())
+ test_title = test_doc.splitlines()[0]
+ test_title_colored = colorize(test_title, GREEN)
+ if test.force_solo():
+ # long live PEP-8 and 80 char width limitation...
+ c = YELLOW
+ test_title_colored = colorize("SOLO RUN: " + test_title, c)
+
if not hasattr(test.__class__, '_header_printed'):
print(double_line_delim)
if not hasattr(test.__class__, '_header_printed'):
print(double_line_delim)
- print(
colorize(getdoc(test).splitlines()[0], GREEN)
)
+ print(
test_title_colored
)
print(double_line_delim)
test.__class__._header_printed = True
print(double_line_delim)
test.__class__._header_printed = True
@@
-1487,16
+1525,17
@@
class VppTestRunner(unittest.TextTestRunner):
class Worker(Thread):
class Worker(Thread):
- def __init__(self, args, logger, env=None):
+ def __init__(self, executable_args, logger, env=None, *args, **kwargs):
+ super(Worker, self).__init__(*args, **kwargs)
self.logger = logger
self.logger = logger
- self.args = args
+ self.args =
executable_
args
if hasattr(self, 'testcase') and self.testcase.debug_all:
if self.testcase.debug_gdbserver:
self.args = ['/usr/bin/gdbserver', 'localhost:{port}'
.format(port=self.testcase.gdbserver_port)] + args
elif self.testcase.debug_gdb and hasattr(self, 'wait_for_gdb'):
self.args.append(self.wait_for_gdb)
if hasattr(self, 'testcase') and self.testcase.debug_all:
if self.testcase.debug_gdbserver:
self.args = ['/usr/bin/gdbserver', 'localhost:{port}'
.format(port=self.testcase.gdbserver_port)] + args
elif self.testcase.debug_gdb and hasattr(self, 'wait_for_gdb'):
self.args.append(self.wait_for_gdb)
- self.app_bin = args[0]
+ self.app_bin =
executable_
args[0]
self.app_name = os.path.basename(self.app_bin)
if hasattr(self, 'role'):
self.app_name += ' {role}'.format(role=self.role)
self.app_name = os.path.basename(self.app_bin)
if hasattr(self, 'role'):
self.app_name += ' {role}'.format(role=self.role)
@@
-1504,7
+1543,6
@@
class Worker(Thread):
self.result = None
env = {} if env is None else env
self.env = copy.deepcopy(env)
self.result = None
env = {} if env is None else env
self.env = copy.deepcopy(env)
- super(Worker, self).__init__()
def wait_for_enter(self):
if not hasattr(self, 'testcase'):
def wait_for_enter(self):
if not hasattr(self, 'testcase'):