make test: elegantly handle expected API failures 75/4875/3
authorKlement Sekera <ksekera@cisco.com>
Wed, 25 Jan 2017 07:00:40 +0000 (08:00 +0100)
committerDamjan Marion <dmarion.lists@gmail.com>
Wed, 25 Jan 2017 15:57:14 +0000 (15:57 +0000)
Allow writing simple code to expect API failure when needed:

with self.vapi.expect_negative_api_retval():
    do_api_call()  # expected to return negative retval in response

Change-Id: Id58d91d9ce38d20ad6ff7a43a6897e79ffbd23bf
Signed-off-by: Klement Sekera <ksekera@cisco.com>
test/test_bfd.py
test/vpp_papi_provider.py

index b56df33..d047b5a 100644 (file)
@@ -42,14 +42,11 @@ class BFDAPITestCase(VppTestCase):
         """ create the same BFD session twice (negative case) """
         session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4)
         session.add_vpp_config()
-        try:
+
+        with self.vapi.expect_negative_api_retval():
             session.add_vpp_config()
-        except:
-            session.remove_vpp_config()
-            return
+
         session.remove_vpp_config()
-        raise Exception("Expected failure while adding duplicate "
-                        "configuration")
 
     def test_add_two(self):
         """ create two BFD sessions """
index 901ea27..4f2cea8 100644 (file)
@@ -32,15 +32,17 @@ class VppPapiProvider(object):
     """VPP-api provider using vpp-papi
 
     @property hook: hook object providing before and after api/cli hooks
-
-
     """
 
+    _zero, _negative = range(2)
+
     def __init__(self, name, shm_prefix, test_class):
         self.hook = Hook("vpp-papi-provider")
         self.name = name
         self.shm_prefix = shm_prefix
         self.test_class = test_class
+        self._expect_api_retval = self._zero
+        self._expect_stack = []
         jsonfiles = []
 
         install_dir = os.getenv('VPP_TEST_INSTALL_PATH')
@@ -51,6 +53,24 @@ class VppPapiProvider(object):
         self.papi = VPP(jsonfiles)
         self._events = deque()
 
+    def __enter__(self):
+        return self
+
+    def expect_negative_api_retval(self):
+        """ Expect API failure """
+        self._expect_stack.append(self._expect_api_retval)
+        self._expect_api_retval = self._negative
+        return self
+
+    def expect_zero_api_retval(self):
+        """ Expect API success """
+        self._expect_stack.append(self._expect_api_retval)
+        self._expect_api_retval = self._zero
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        self._expect_api_retval = self._expect_stack.pop()
+
     def register_hook(self, hook):
         """Replace hook registration with new hook
 
@@ -113,11 +133,23 @@ class VppPapiProvider(object):
         """
         self.hook.before_api(api_fn.__name__, api_args)
         reply = api_fn(**api_args)
-        if hasattr(reply, 'retval') and reply.retval != expected_retval:
-            msg = "API call failed, expected retval == %d, got %s" % (
-                expected_retval, repr(reply))
-            self.test_class.logger.info(msg)
-            raise Exception(msg)
+        if self._expect_api_retval == self._negative:
+            if hasattr(reply, 'retval') and reply.retval >= 0:
+                msg = "API call passed unexpectedly: expected negative "\
+                    "return value instead of %d in %s" % \
+                    (reply.retval, repr(reply))
+                self.test_class.logger.info(msg)
+                raise Exception(msg)
+        elif self._expect_api_retval == self._zero:
+            if hasattr(reply, 'retval') and reply.retval != expected_retval:
+                msg = "API call failed, expected zero return value instead "\
+                    "of %d in %s" % (expected_retval, repr(reply))
+                self.test_class.logger.info(msg)
+                raise Exception(msg)
+        else:
+            raise Exception("Internal error, unexpected value for "
+                            "self._expect_api_retval %s" %
+                            self._expect_api_retval)
         self.hook.after_api(api_fn.__name__, api_args)
         return reply