tests: add worker count to class description
[vpp.git] / test / remote_test.py
index f5b3c62..134d90f 100644 (file)
@@ -1,33 +1,28 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import inspect
 import os
 
 import inspect
 import os
+import reprlib
 import unittest
 from framework import VppTestCase
 from multiprocessing import Process, Pipe
 from pickle import dumps
 import unittest
 from framework import VppTestCase
 from multiprocessing import Process, Pipe
 from pickle import dumps
-import six
-from six import moves
 import sys
 import sys
-if sys.version_info <= (3, 4):
-    from aenum import IntEnum
-else:
-    from enum import IntEnum
 
 
-if sys.version_info <= (3, 6):
-    from aenum import IntFlag
-else:
-    from enum import IntFlag
+from enum import IntEnum, IntFlag
 
 
 
 
-class SerializableClassCopy(object):
+class SerializableClassCopy:
     """
     Empty class used as a basis for a serializable copy of another class.
     """
     pass
 
     """
     Empty class used as a basis for a serializable copy of another class.
     """
     pass
 
+    def __repr__(self):
+        return '<SerializableClassCopy dict=%s>' % self.__dict__
+
 
 
-class RemoteClassAttr(object):
+class RemoteClassAttr:
     """
     Wrapper around attribute of a remotely executed class.
     """
     """
     Wrapper around attribute of a remotely executed class.
     """
@@ -51,7 +46,8 @@ class RemoteClassAttr(object):
     def __getattr__(self, attr):
         if attr[0] == '_':
             if not (attr.startswith('__') and attr.endswith('__')):
     def __getattr__(self, attr):
         if attr[0] == '_':
             if not (attr.startswith('__') and attr.endswith('__')):
-                raise AttributeError
+                raise AttributeError('tried to get private attribute: %s ',
+                                     attr)
         self._path.append(attr)
         return self
 
         self._path.append(attr)
         return self
 
@@ -62,11 +58,11 @@ class RemoteClassAttr(object):
                 return
         self._path.append(attr)
         self._remote._remote_exec(RemoteClass.SETATTR, self.path_to_str(),
                 return
         self._path.append(attr)
         self._remote._remote_exec(RemoteClass.SETATTR, self.path_to_str(),
-                                  True, value=val)
+                                  value=val)
 
     def __call__(self, *args, **kwargs):
         return self._remote._remote_exec(RemoteClass.CALL, self.path_to_str(),
 
     def __call__(self, *args, **kwargs):
         return self._remote._remote_exec(RemoteClass.CALL, self.path_to_str(),
-                                         True, *args, **kwargs)
+                                         *args, **kwargs)
 
 
 class RemoteClass(Process):
 
 
 class RemoteClass(Process):
@@ -113,7 +109,7 @@ class RemoteClass(Process):
         self._pipe = Pipe()  # pipe for input/output arguments
 
     def __repr__(self):
         self._pipe = Pipe()  # pipe for input/output arguments
 
     def __repr__(self):
-        return moves.reprlib.repr(RemoteClassAttr(self, None))
+        return reprlib.repr(RemoteClassAttr(self, None))
 
     def __str__(self):
         return str(RemoteClassAttr(self, None))
 
     def __str__(self):
         return str(RemoteClassAttr(self, None))
@@ -126,7 +122,7 @@ class RemoteClass(Process):
             if not (attr.startswith('__') and attr.endswith('__')):
                 if hasattr(super(RemoteClass, self), '__getattr__'):
                     return super(RemoteClass, self).__getattr__(attr)
             if not (attr.startswith('__') and attr.endswith('__')):
                 if hasattr(super(RemoteClass, self), '__getattr__'):
                     return super(RemoteClass, self).__getattr__(attr)
-                raise AttributeError
+                raise AttributeError('missing: %s', attr)
         return RemoteClassAttr(self, attr)
 
     def __setattr__(self, attr, val):
         return RemoteClassAttr(self, attr)
 
     def __setattr__(self, attr, val):
@@ -136,7 +132,7 @@ class RemoteClass(Process):
                 return
         setattr(RemoteClassAttr(self, None), attr, val)
 
                 return
         setattr(RemoteClassAttr(self, None), attr, val)
 
-    def _remote_exec(self, op, path=None, ret=True, *args, **kwargs):
+    def _remote_exec(self, op, path=None, *args, **kwargs):
         """
         Execute given operation on a given, possibly nested, member remotely.
         """
         """
         Execute given operation on a given, possibly nested, member remotely.
         """
@@ -144,23 +140,20 @@ class RemoteClass(Process):
         mutable_args = list(args)
         for i, val in enumerate(mutable_args):
             if isinstance(val, RemoteClass) or \
         mutable_args = list(args)
         for i, val in enumerate(mutable_args):
             if isinstance(val, RemoteClass) or \
-               isinstance(val, RemoteClassAttr):
+                    isinstance(val, RemoteClassAttr):
                 mutable_args[i] = val.get_remote_value()
         args = tuple(mutable_args)
                 mutable_args[i] = val.get_remote_value()
         args = tuple(mutable_args)
-        for key, val in six.iteritems(kwargs):
+        for key, val in kwargs.items():
             if isinstance(val, RemoteClass) or \
             if isinstance(val, RemoteClass) or \
-               isinstance(val, RemoteClassAttr):
+                    isinstance(val, RemoteClassAttr):
                 kwargs[key] = val.get_remote_value()
         # send request
         args = self._make_serializable(args)
         kwargs = self._make_serializable(kwargs)
         self._pipe[RemoteClass.PIPE_PARENT].send((op, path, args, kwargs))
                 kwargs[key] = val.get_remote_value()
         # send request
         args = self._make_serializable(args)
         kwargs = self._make_serializable(kwargs)
         self._pipe[RemoteClass.PIPE_PARENT].send((op, path, args, kwargs))
-        if not ret:
-            # no return value expected
-            return None
         timeout = self._timeout
         # adjust timeout specifically for the .sleep method
         timeout = self._timeout
         # adjust timeout specifically for the .sleep method
-        if path.split('.')[-1] == 'sleep':
+        if path is not None and path.split('.')[-1] == 'sleep':
             if args and isinstance(args[0], (long, int)):
                 timeout += args[0]
             elif 'timeout' in kwargs:
             if args and isinstance(args[0], (long, int)):
                 timeout += args[0]
             elif 'timeout' in kwargs:
@@ -207,7 +200,7 @@ class RemoteClass(Process):
     def _get_local_repr(self, path):
         try:
             obj = self._get_local_object(path)
     def _get_local_repr(self, path):
         try:
             obj = self._get_local_object(path)
-            return moves.reprlib.repr(obj)
+            return reprlib.repr(obj)
         except AttributeError:
             return None
 
         except AttributeError:
             return None
 
@@ -251,13 +244,18 @@ class RemoteClass(Process):
 
         # copy at least serializable attributes and properties
         for name, member in inspect.getmembers(obj):
 
         # copy at least serializable attributes and properties
         for name, member in inspect.getmembers(obj):
-            if name[0] == '_':  # skip private members
+            # skip private members and non-writable dunder methods.
+            if name[0] == '_':
+                if name in ['__weakref__']:
+                    continue
+                if name in ['__dict__']:
+                    continue
                 if not (name.startswith('__') and name.endswith('__')):
                     continue
             if callable(member) and not isinstance(member, property):
                 continue
             if not self._serializable(member):
                 if not (name.startswith('__') and name.endswith('__')):
                     continue
             if callable(member) and not isinstance(member, property):
                 continue
             if not self._serializable(member):
-                continue
+                member = self._make_serializable(member)
             setattr(copy, name, member)
         return copy
 
             setattr(copy, name, member)
         return copy
 
@@ -304,7 +302,7 @@ class RemoteClass(Process):
 
     def quit_remote(self):
         """ Quit remote execution """
 
     def quit_remote(self):
         """ Quit remote execution """
-        self._remote_exec(RemoteClass.QUIT, None, False)
+        self._remote_exec(RemoteClass.QUIT, None)
 
     def get_remote_value(self):
         """ Get value of a remotely held object """
 
     def get_remote_value(self):
         """ Get value of a remotely held object """
@@ -360,7 +358,7 @@ class RemoteVppTestCase(VppTestCase):
 
         @classmethod
         def setUpClass(cls):
 
         @classmethod
         def setUpClass(cls):
-            # fork new process before clinet connects to VPP
+            # fork new process before client connects to VPP
             cls.remote_test = RemoteClass(RemoteVppTestCase)
 
             # start remote process
             cls.remote_test = RemoteClass(RemoteVppTestCase)
 
             # start remote process
@@ -408,6 +406,10 @@ class RemoteVppTestCase(VppTestCase):
         super(RemoteVppTestCase, cls).setUpClass()
         os.environ = orig_env
 
         super(RemoteVppTestCase, cls).setUpClass()
         os.environ = orig_env
 
+    @classmethod
+    def tearDownClass(cls):
+        super(RemoteVppTestCase, cls).tearDownClass()
+
     @unittest.skip("Empty test")
     def emptyTest(self):
         """ Do nothing """
     @unittest.skip("Empty test")
     def emptyTest(self):
         """ Do nothing """