Create a unit-test plugin
[vpp.git] / test / framework.py
index f90197b..4f7c76a 100644 (file)
@@ -25,6 +25,7 @@ from vpp_papi_provider import VppPapiProvider
 from log import RED, GREEN, YELLOW, double_line_delim, single_line_delim, \
     getLogger, colorize
 from vpp_object import VppObjectRegistry
+from util import ppp
 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
 from scapy.layers.inet6 import ICMPv6DestUnreach, ICMPv6EchoRequest
 from scapy.layers.inet6 import ICMPv6EchoReply
@@ -82,7 +83,7 @@ def pump_output(testclass):
     """ pump output from vpp stdout/stderr to proper queues """
     stdout_fragment = ""
     stderr_fragment = ""
-    while not testclass.pump_thread_stop_flag.wait(0):
+    while not testclass.pump_thread_stop_flag.is_set():
         readable = select.select([testclass.vpp.stdout.fileno(),
                                   testclass.vpp.stderr.fileno(),
                                   testclass.pump_thread_wakeup_pipe[0]],
@@ -245,7 +246,8 @@ class VppTestCase(unittest.TestCase):
                            coredump_size, "}", "api-trace", "{", "on", "}",
                            "api-segment", "{", "prefix", cls.shm_prefix, "}",
                            "plugins", "{", "plugin", "dpdk_plugin.so", "{",
-                           "disable", "}", "}", ]
+                           "disable", "}", "plugin", "unittest_plugin.so",
+                           "{", "enable", "}", "}", ]
         if plugin_path is not None:
             cls.vpp_cmdline.extend(["plugin_path", plugin_path])
         cls.logger.info("vpp_cmdline: %s" % cls.vpp_cmdline)
@@ -390,8 +392,8 @@ class VppTestCase(unittest.TestCase):
                 raw_input("When done debugging, press ENTER to kill the "
                           "process and finish running the testcase...")
 
-        os.write(cls.pump_thread_wakeup_pipe[1], 'ding dong wake up')
         cls.pump_thread_stop_flag.set()
+        os.write(cls.pump_thread_wakeup_pipe[1], 'ding dong wake up')
         if hasattr(cls, 'pump_thread'):
             cls.logger.debug("Waiting for pump thread to stop")
             cls.pump_thread.join()
@@ -557,18 +559,16 @@ class VppTestCase(unittest.TestCase):
         return result
 
     @classmethod
-    def create_loopback_interfaces(cls, interfaces):
+    def create_loopback_interfaces(cls, count):
         """
         Create loopback interfaces.
 
-        :param interfaces: iterable indexes of the interfaces.
+        :param count: number of interfaces created.
         :returns: List of created interfaces.
         """
-        result = []
-        for i in interfaces:
-            intf = VppLoInterface(cls, i)
+        result = [VppLoInterface(cls) for i in range(count)]
+        for intf in result:
             setattr(cls, intf.name, intf)
-            result.append(intf)
         cls.lo_interfaces = result
         return result
 
@@ -735,11 +735,14 @@ class VppTestCase(unittest.TestCase):
 
     def assert_packet_checksums_valid(self, packet,
                                       ignore_zero_udp_checksums=True):
+        received = packet.__class__(str(packet))
+        self.logger.debug(
+            ppp("Verifying packet checksums for packet:", received))
         udp_layers = ['UDP', 'UDPerror']
         checksum_fields = ['cksum', 'chksum']
         checksums = []
         counter = 0
-        temp = packet.__class__(str(packet))
+        temp = received.__class__(str(received))
         while True:
             layer = temp.getlayer(counter)
             if layer:
@@ -754,12 +757,17 @@ class VppTestCase(unittest.TestCase):
             else:
                 break
             counter = counter + 1
+        if 0 == len(checksums):
+            return
         temp = temp.__class__(str(temp))
         for layer, cf in checksums:
-            self.assert_equal(getattr(packet[layer], cf),
-                              getattr(temp[layer], cf),
-                              "packet checksum on layer #%d: %s" % (
-                                  layer, temp[layer].name))
+            calc_sum = getattr(temp[layer], cf)
+            self.assert_equal(
+                getattr(received[layer], cf), calc_sum,
+                "packet checksum on layer #%d: %s" % (layer, temp[layer].name))
+            self.logger.debug(
+                "Checksum field `%s` on `%s` layer has correct value `%s`" %
+                (cf, temp[layer].name, calc_sum))
 
     def assert_checksum_valid(self, received_packet, layer,
                               field_name='chksum',
@@ -830,12 +838,13 @@ class VppTestCase(unittest.TestCase):
                 "Finished sleep (%s) - slept %ss (wanted %ss)" % (
                     remark, after - before, timeout))
 
-    def send_and_assert_no_replies(self, intf, pkts, remark=""):
+    def send_and_assert_no_replies(self, intf, pkts, remark="", timeout=None):
         self.vapi.cli("clear trace")
         intf.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start()
-        timeout = 1
+        if not timeout:
+            timeout = 1
         for i in self.pg_interfaces:
             i.get_capture(0, timeout=timeout)
             i.assert_nothing_captured(remark=remark)
@@ -950,7 +959,25 @@ class VppTestResult(unittest.TestResult):
         if hasattr(self, 'test_framework_failed_pipe'):
             pipe = self.test_framework_failed_pipe
             if pipe:
-                pipe.send(test.__class__)
+                if test.__class__.__name__ == "_ErrorHolder":
+                    x = str(test)
+                    if x.startswith("setUpClass"):
+                        # x looks like setUpClass (test_function.test_class)
+                        cls = x.split(".")[1].split(")")[0]
+                        for t in self.test_suite:
+                            if t.__class__.__name__ == cls:
+                                pipe.send(t.__class__)
+                                break
+                        else:
+                            raise Exception("Can't find class name `%s' "
+                                            "(from ErrorHolder) in test suite "
+                                            "`%s'" % (cls, self.test_suite))
+                    else:
+                        raise Exception("FIXME: unexpected special case - "
+                                        "ErrorHolder description is `%s'" %
+                                        str(test))
+                else:
+                    pipe.send(test.__class__)
 
     def addFailure(self, test, err):
         """
@@ -1185,6 +1212,8 @@ class VppTestRunner(unittest.TextTestRunner):
             filtered.countTestCases(), test.countTestCases()))
         if not running_extended_tests():
             print("Not running extended tests (some tests will be skipped)")
+        # super-ugly hack #2
+        VppTestResult.test_suite = filtered
         return super(VppTestRunner, self).run(filtered)