X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Fframework.py;h=79dfe1ae8664896f05e14d8a31f92e1e6621d340;hb=1b534f5a4ad33f78159113f5a922465df6b32cef;hp=989fb3d75cfaf36e4e29ff7e14022988fe9af925;hpb=3e9b7a219df7ba52db719af5216a44b31f21f770;p=vpp.git diff --git a/test/framework.py b/test/framework.py index 989fb3d75cf..79dfe1ae866 100644 --- a/test/framework.py +++ b/test/framework.py @@ -5,6 +5,7 @@ import gc import sys import os import select +import signal import unittest import tempfile import time @@ -21,13 +22,14 @@ from logging import FileHandler, DEBUG, Formatter import scapy.compat from scapy.packet import Raw -from hook import StepHook, PollHook, VppDiedError +import hook as hookmodule from vpp_pg_interface import VppPGInterface from vpp_sub_interface import VppSubInterface from vpp_lo_interface import VppLoInterface from vpp_bvi_interface import VppBviInterface from vpp_papi_provider import VppPapiProvider from vpp_papi.vpp_stats import VPPStats +from vpp_papi.vpp_transport_shmem import VppTransportShmemIOError from log import RED, GREEN, YELLOW, double_line_delim, single_line_delim, \ get_logger, colorize from vpp_object import VppObjectRegistry @@ -68,6 +70,36 @@ if os.getenv('TEST_DEBUG', "0") == "1": """ +class VppDiedError(Exception): + """ exception for reporting that the subprocess has died.""" + + signals_by_value = {v: k for k, v in signal.__dict__.items() if + k.startswith('SIG') and not k.startswith('SIG_')} + + def __init__(self, rv=None, testcase=None, method_name=None): + self.rv = rv + self.signal_name = None + self.testcase = testcase + self.method_name = method_name + + try: + self.signal_name = VppDiedError.signals_by_value[-rv] + except KeyError: + pass + + if testcase is None and method_name is None: + in_msg = '' + else: + in_msg = 'running %s.%s ' % (testcase, method_name) + + msg = "VPP subprocess died %sunexpectedly with return code: %d%s." % ( + in_msg, + self.rv, + ' [%s]' % self.signal_name if + self.signal_name is not None else '') + super(VppDiedError, self).__init__(msg) + + class _PacketInfo(object): """Private class to create packet info object. @@ -144,12 +176,14 @@ def pump_output(testclass): def _is_skip_aarch64_set(): return os.getenv('SKIP_AARCH64', 'n').lower() in ('yes', 'y', '1') + is_skip_aarch64_set = _is_skip_aarch64_set() def _is_platform_aarch64(): return platform.machine() == 'aarch64' + is_platform_aarch64 = _is_platform_aarch64() @@ -157,6 +191,7 @@ def _running_extended_tests(): s = os.getenv("EXTENDED_TESTS", "n") return True if s.lower() in ("y", "yes", "1") else False + running_extended_tests = _running_extended_tests() @@ -164,6 +199,7 @@ def _running_on_centos(): os_id = os.getenv("OS_ID", "") return True if "centos" in os_id.lower() else False + running_on_centos = _running_on_centos @@ -286,6 +322,7 @@ class VppTestCase(unittest.TestCase): cls.set_debug_flags(d) cls.vpp_bin = os.getenv('VPP_BIN', "vpp") cls.plugin_path = os.getenv('VPP_PLUGIN_PATH') + cls.test_plugin_path = os.getenv('VPP_TEST_PLUGIN_PATH') cls.extern_plugin_path = os.getenv('EXTERN_PLUGINS') plugin_path = None if cls.plugin_path is not None: @@ -325,6 +362,9 @@ class VppTestCase(unittest.TestCase): cls.vpp_cmdline.extend(cls.extra_vpp_punt_config) if plugin_path is not None: cls.vpp_cmdline.extend(["plugin_path", plugin_path]) + if cls.test_plugin_path is not None: + cls.vpp_cmdline.extend(["test_plugin_path", cls.test_plugin_path]) + cls.logger.info("vpp_cmdline args: %s" % cls.vpp_cmdline) cls.logger.info("vpp_cmdline: %s" % " ".join(cls.vpp_cmdline)) @@ -342,12 +382,13 @@ class VppTestCase(unittest.TestCase): print(single_line_delim) print("You can debug the VPP using e.g.:") if cls.debug_gdbserver: - print("gdb " + cls.vpp_bin + " -ex 'target remote localhost:7777'") + print("sudo gdb " + cls.vpp_bin + + " -ex 'target remote localhost:7777'") print("Now is the time to attach a gdb by running the above " "command, set up breakpoints etc. and then resume VPP from " "within gdb by issuing the 'continue' command") elif cls.debug_gdb: - print("gdb " + cls.vpp_bin + " -ex 'attach %s'" % cls.vpp.pid) + print("sudo gdb " + cls.vpp_bin + " -ex 'attach %s'" % cls.vpp.pid) print("Now is the time to attach a gdb by running the above " "command and set up breakpoints etc.") print(single_line_delim) @@ -482,9 +523,9 @@ class VppTestCase(unittest.TestCase): cls.vapi = VppPapiProvider(cls.shm_prefix, cls.shm_prefix, cls, read_timeout) if cls.step: - hook = StepHook(cls) + hook = hookmodule.StepHook(cls) else: - hook = PollHook(cls) + hook = hookmodule.PollHook(cls) cls.vapi.register_hook(hook) cls.wait_for_stats_socket() cls.statistics = VPPStats(socketname=cls.stats_sock) @@ -509,10 +550,8 @@ class VppTestCase(unittest.TestCase): "to 'continue' VPP from within gdb?", RED)) raise except Exception: - try: - cls.quit() - except Exception: - pass + + cls.quit() raise @classmethod @@ -608,18 +647,18 @@ class VppTestCase(unittest.TestCase): self.logger.debug("--- tearDown() for %s.%s(%s) called ---" % (self.__class__.__name__, self._testMethodName, self._testMethodDoc)) - if not self.vpp_dead: - self.logger.info( - "--- Logging show commands common to all testcases. ---") - self.logger.debug(self.vapi.cli("show trace max 1000")) - self.logger.info(self.vapi.ppcli("show interface")) - self.logger.info(self.vapi.ppcli("show hardware")) - self.logger.info(self.statistics.set_errors_str()) - self.logger.info(self.vapi.ppcli("show run")) - self.logger.info(self.vapi.ppcli("show log")) - self.logger.info("Logging testcase specific show commands.") - self.show_commands_at_teardown() - self.registry.remove_vpp_config(self.logger) + + try: + if not self.vpp_dead: + self.logger.debug(self.vapi.cli("show trace max 1000")) + self.logger.info(self.vapi.ppcli("show interface")) + self.logger.info(self.vapi.ppcli("show hardware")) + self.logger.info(self.statistics.set_errors_str()) + self.logger.info(self.vapi.ppcli("show run")) + self.logger.info(self.vapi.ppcli("show log")) + self.logger.info("Logging testcase specific show commands.") + self.show_commands_at_teardown() + self.registry.remove_vpp_config(self.logger) # Save/Dump VPP api trace log api_trace = "vpp_api_trace.%s.log" % self._testMethodName tmp_api_trace = "/tmp/%s" % api_trace @@ -630,6 +669,10 @@ class VppTestCase(unittest.TestCase): os.rename(tmp_api_trace, vpp_api_trace_log) self.logger.info(self.vapi.ppcli("api trace custom-dump %s" % vpp_api_trace_log)) + except VppTransportShmemIOError: + self.logger.debug("VppTransportShmemIOError: Vpp dead. " + "Cannot log show commands.") + self.vpp_dead = True else: self.registry.unregister_all(self.logger) @@ -638,7 +681,10 @@ class VppTestCase(unittest.TestCase): super(VppTestCase, self).setUp() self.reporter.send_keep_alive(self) if self.vpp_dead: - raise Exception("VPP is dead when setting up the test") + raise VppDiedError(self.__class__.__name__, self._testMethodName, + "VPP is dead when setting up the test " + "(%s.%s)." % (self.__class__.__name__, + self._testMethodName)) self.sleep(.1, "during setUp") self.vpp_stdout_deque.append( "--- test setUp() for %s.%s(%s) starts here ---\n" % @@ -756,8 +802,8 @@ class VppTestCase(unittest.TestCase): packet_len = len(packet) + 4 extend = size - packet_len if extend > 0: - num = (extend / len(padding)) + 1 - packet[Raw].load += (padding * num)[:extend] + num = (extend // len(padding)) + 1 + packet[Raw].load += (padding * num)[:extend].encode("ascii") @classmethod def reset_packet_infos(cls): @@ -922,8 +968,8 @@ class VppTestCase(unittest.TestCase): for cf in checksum_fields: if hasattr(layer, cf): if ignore_zero_udp_checksums and \ - 0 == getattr(layer, cf) and \ - layer.name in udp_layers: + 0 == getattr(layer, cf) and \ + layer.name in udp_layers: continue delattr(layer, cf) checksums.append((counter, cf)) @@ -996,19 +1042,28 @@ class VppTestCase(unittest.TestCase): if pkt.haslayer(ICMPv6EchoReply): self.assert_checksum_valid(pkt, 'ICMPv6EchoReply', 'cksum') - def assert_packet_counter_equal(self, counter, expected_value): + def get_packet_counter(self, counter): if counter.startswith("/"): counter_value = self.statistics.get_counter(counter) - self.assert_equal(counter_value, expected_value, - "packet counter `%s'" % counter) else: counters = self.vapi.cli("sh errors").split('\n') - counter_value = -1 + counter_value = 0 for i in range(1, len(counters) - 1): results = counters[i].split() if results[1] == counter: counter_value = int(results[0]) break + return counter_value + + def assert_packet_counter_equal(self, counter, expected_value): + counter_value = self.get_packet_counter(counter) + self.assert_equal(counter_value, expected_value, + "packet counter `%s'" % counter) + + def assert_error_counter_equal(self, counter, expected_value): + counter_value = self.statistics.get_err_counter(counter) + self.assert_equal(counter_value, expected_value, + "error counter `%s'" % counter) @classmethod def sleep(cls, timeout, remark=None): @@ -1433,5 +1488,6 @@ class Worker(Thread): self.logger.info(single_line_delim) self.result = self.process.returncode + if __name__ == '__main__': pass