X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=test%2Fframework.py;h=8a92229249bf57d42cb337ce2104649dfa4eb0c5;hb=90cf21b5d8fd2d3e531e841dcd752311df5f8a50;hp=dc7d6107722063f0651acb74123cec82ccd01188;hpb=ea2450fa2d1e8ba0295ea9861a404796100dad1e;p=vpp.git diff --git a/test/framework.py b/test/framework.py index dc7d6107722..8a92229249b 100644 --- a/test/framework.py +++ b/test/framework.py @@ -18,11 +18,14 @@ from threading import Thread, Event from inspect import getdoc, isclass from traceback import format_exception from logging import FileHandler, DEBUG, Formatter + +import scapy.compat from scapy.packet import Raw from hook import StepHook, PollHook, VppDiedError 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 log import RED, GREEN, YELLOW, double_line_delim, single_line_delim, \ @@ -313,6 +316,7 @@ class VppTestCase(unittest.TestCase): "main-core", str(cpu_core_number), "}", "statseg", "{", "socket-name", cls.stats_sock, "}", "plugins", "{", "plugin", "dpdk_plugin.so", "{", "disable", + "}", "plugin", "rdma_plugin.so", "{", "disable", "}", "plugin", "unittest_plugin.so", "{", "enable", "}"] + cls.extra_vpp_plugin_config + ["}", ] if cls.extra_vpp_punt_config is not None: @@ -390,7 +394,7 @@ class VppTestCase(unittest.TestCase): if os.path.exists(cls.stats_sock): ok = True break - time.sleep(0.8) + cls.sleep(0.8) if not ok: cls.logger.critical("Couldn't stat : {}".format(cls.stats_sock)) @@ -407,6 +411,7 @@ class VppTestCase(unittest.TestCase): if hasattr(cls, 'parallel_handler'): cls.logger.addHandler(cls.parallel_handler) cls.logger.propagate = False + cls.tempdir = tempfile.mkdtemp( prefix='vpp-unittest-%s-' % cls.__name__) cls.stats_sock = "%s/stats.sock" % cls.tempdir @@ -416,6 +421,8 @@ class VppTestCase(unittest.TestCase): datefmt="%H:%M:%S")) cls.file_handler.setLevel(DEBUG) cls.logger.addHandler(cls.file_handler) + cls.logger.debug("--- setUpClass() for %s called ---" % + cls.__name__) cls.shm_prefix = os.path.basename(cls.tempdir) os.chdir(cls.tempdir) cls.logger.info("Temporary dir is %s, shm prefix is %s", @@ -511,7 +518,11 @@ class VppTestCase(unittest.TestCase): if hasattr(cls, 'vpp'): if hasattr(cls, 'vapi'): + cls.logger.debug("Disconnecting class vapi client on %s", + cls.__name__) cls.vapi.disconnect() + cls.logger.debug("Deleting class vapi attribute on %s", + cls.__name__) del cls.vapi cls.vpp.poll() if cls.vpp.returncode is None: @@ -519,6 +530,8 @@ class VppTestCase(unittest.TestCase): cls.vpp.kill() cls.logger.debug("Waiting for vpp to die") cls.vpp.communicate() + cls.logger.debug("Deleting class vpp attribute on %s", + cls.__name__) del cls.vpp if cls.vpp_startup_failed: @@ -551,6 +564,8 @@ class VppTestCase(unittest.TestCase): @classmethod def tearDownClass(cls): """ Perform final cleanup after running all tests in this test-case """ + cls.logger.debug("--- tearDownClass() for %s called ---" % + cls.__name__) cls.reporter.send_keep_alive(cls, 'tearDownClass') cls.quit() cls.file_handler.close() @@ -558,19 +573,26 @@ class VppTestCase(unittest.TestCase): if debug_framework: debug_internal.on_tear_down_class(cls) + def show_commands_at_teardown(self): + """ Allow subclass specific teardown logging additions.""" + self.logger.info("--- No test specific show commands provided. ---") + def tearDown(self): """ Show various debug prints after each test """ - super(VppTestCase, self).tearDown() 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) # Save/Dump VPP api trace log api_trace = "vpp_api_trace.%s.log" % self._testMethodName @@ -589,9 +611,6 @@ class VppTestCase(unittest.TestCase): """ Clear trace before running each test""" super(VppTestCase, self).setUp() self.reporter.send_keep_alive(self) - self.logger.debug("--- setUp() for %s.%s(%s) called ---" % - (self.__class__.__name__, self._testMethodName, - self._testMethodDoc)) if self.vpp_dead: raise Exception("VPP is dead when setting up the test") self.sleep(.1, "during setUp") @@ -683,6 +702,20 @@ class VppTestCase(unittest.TestCase): cls.lo_interfaces = result return result + @classmethod + def create_bvi_interfaces(cls, count): + """ + Create BVI interfaces. + + :param count: number of interfaces created. + :returns: List of created interfaces. + """ + result = [VppBviInterface(cls) for i in range(count)] + for intf in result: + setattr(cls, intf.name, intf) + cls.bvi_interfaces = result + return result + @staticmethod def extend_packet(packet, size, padding=' '): """ @@ -746,16 +779,19 @@ class VppTestCase(unittest.TestCase): info.ip, info.proto) @staticmethod - def payload_to_info(payload): + def payload_to_info(payload, payload_field='load'): """ Convert packet payload to _PacketInfo object :param payload: packet payload - + :type payload: + :param payload_field: packet fieldname of payload "load" for + + :type payload_field: str :returns: _PacketInfo object containing de-serialized data from payload """ - numbers = payload.split() + numbers = getattr(payload, payload_field).split() info = _PacketInfo() info.index = int(numbers[0]) info.src = int(numbers[1]) @@ -846,14 +882,14 @@ class VppTestCase(unittest.TestCase): def assert_packet_checksums_valid(self, packet, ignore_zero_udp_checksums=True): - received = packet.__class__(str(packet)) + received = packet.__class__(scapy.compat.raw(packet)) self.logger.debug( ppp("Verifying packet checksums for packet:", received)) udp_layers = ['UDP', 'UDPerror'] checksum_fields = ['cksum', 'chksum'] checksums = [] counter = 0 - temp = received.__class__(str(received)) + temp = received.__class__(scapy.compat.raw(received)) while True: layer = temp.getlayer(counter) if layer: @@ -870,7 +906,7 @@ class VppTestCase(unittest.TestCase): counter = counter + 1 if 0 == len(checksums): return - temp = temp.__class__(str(temp)) + temp = temp.__class__(scapy.compat.raw(temp)) for layer, cf in checksums: calc_sum = getattr(temp[layer], cf) self.assert_equal( @@ -887,9 +923,10 @@ class VppTestCase(unittest.TestCase): received_packet_checksum = getattr(received_packet[layer], field_name) if ignore_zero_checksum and 0 == received_packet_checksum: return - recalculated = received_packet.__class__(str(received_packet)) + recalculated = received_packet.__class__( + scapy.compat.raw(received_packet)) delattr(recalculated[layer], field_name) - recalculated = recalculated.__class__(str(recalculated)) + recalculated = recalculated.__class__(scapy.compat.raw(recalculated)) self.assert_equal(received_packet_checksum, getattr(recalculated[layer], field_name), "packet checksum on layer: %s" % layer) @@ -949,13 +986,26 @@ class VppTestCase(unittest.TestCase): @classmethod def sleep(cls, timeout, remark=None): + + # /* Allow sleep(0) to maintain win32 semantics, and as decreed + # * by Guido, only the main thread can be interrupted. + # */ + # https://github.com/python/cpython/blob/6673decfa0fb078f60587f5cb5e98460eea137c2/Modules/timemodule.c#L1892 # noqa + if timeout == 0: + # yield quantum + if hasattr(os, 'sched_yield'): + os.sched_yield() + else: + time.sleep(0) + return + if hasattr(cls, 'logger'): cls.logger.debug("Starting sleep for %es (%s)", timeout, remark) before = time.time() time.sleep(timeout) after = time.time() if hasattr(cls, 'logger') and after - before > 2 * timeout: - cls.logger.error("unexpected time.sleep() result - " + cls.logger.error("unexpected self.sleep() result - " "slept for %es instead of ~%es!", after - before, timeout) if hasattr(cls, 'logger'): @@ -978,9 +1028,11 @@ class VppTestCase(unittest.TestCase): i.assert_nothing_captured(remark=remark) timeout = 0.1 - def send_and_expect(self, intf, pkts, output): + def send_and_expect(self, intf, pkts, output, n_rx=None): + if not n_rx: + n_rx = len(pkts) self.pg_send(intf, pkts) - rx = output.get_capture(len(pkts)) + rx = output.get_capture(n_rx) return rx def send_and_expect_only(self, intf, pkts, output, timeout=None):