Ejemplo n.º 1
0
    def __init__(self, config_fn=None, assert_fn=None, name='TestableProcess', *args, **kwargs):
        super().__init__()
        self.log = get_logger(name)
        self.name = name
        self.url = _gen_url(name)

        self.config_fn = config_fn  # Function to configure object with mocks
        self.assert_fn = assert_fn  # Function to run assertions on said mocks

        # 'socket' is used to proxy commands to blocking object running in a child process (possibly on a VM)
        self.ctx = zmq.Context()
        self.socket = self.ctx.socket(socket_type=zmq.PAIR)
        self.socket.bind(self.url)

        # Add this object to the registry of testers
        MPTesterBase.testers.append(self)

        # Create a wrapper around the build_obj with args and kwargs. We do this b/c this function will actually be
        # invoked in a separate process/machine, thus we need to capture the function call to serialize it and send
        # it across a socket
        build_fn = wrap_func(type(self).build_obj, *args, **kwargs)

        # Create and start the subprocess that will run the blocking object
        self.test_proc = LProcess(target=self._run_test_proc, args=(self.name, self.url, build_fn,
                                                               self.config_fn, self.assert_fn,))
        self.start_test()
Ejemplo n.º 2
0
    def _config_url_and_test_proc(self, build_fn, always_run_as_subproc):
        # Add this object to the registry of testers
        from .mp_test_case import MPTestCase
        MPTestCase.testers.append(self)

        # Create Tester object in a VM
        if MPTestCase.vmnet_test_active and not always_run_as_subproc:
            assert hasattr(
                MPTestCase, 'ports'
            ), "VMNet test is active, but MPTestCase has no attribute ports"
            assert MPTestCase.ports, "VMNet test is active, but MPTestCase.ports is not set"

            name, ip = MPTestCase.next_container()
            assert name in MPTestCase.ports, "Node named {} not found in ports {}".format(
                name, MPTestCase.ports)
            assert MPTEST_PORT in MPTestCase.ports[name], "MPTEST_PORT {} not found in docker node {}'s ports {}"\
                                                          .format(MPTEST_PORT, name, MPTestCase.ports[name])

            url = MPTestCase.ports[name][
                MPTEST_PORT]  # URL the orchestration node should connect to
            url = url.replace('localhost',
                              '127.0.0.1')  # Adjust localhost to 127.0.0.1
            url = "tcp://{}".format(url)

            remote_url = "tcp://{}:{}".format(
                ip, MPTEST_PORT)  # URL the remote node should bind to
            self.container_name = name
            self.url = url
            self.ip = ip

            self.log.notice(
                "Creating node named {} in a docker container with name {} and ip {}"
                .format(self.name, name, self.ip))

            runner_func = wrap_func(_run_test_proc, self.name, remote_url,
                                    build_fn, self.config_fn, self.assert_fn)

            # TODO -- will i need a ton of imports and stuff to make this run smoothly...?
            MPTestCase.execute_python(name, runner_func, async=True)

        # Create Tester object in a Subprocess
        else:
            self.url = _gen_url(self.name)
            self.log.notice(
                "Creating node named {} in a subprocess with IPC url {}".
                format(self.name, self.url))

            self.test_proc = LProcess(target=_run_test_proc,
                                      name=self.name,
                                      args=(
                                          self.name,
                                          self.url,
                                          build_fn,
                                          self.config_fn,
                                          self.assert_fn,
                                      ))
            self.test_proc.start()
Ejemplo n.º 3
0
class MPTesterBase:
    """
    TODO docstring
    """
    tester_cls = 'UNSET'

    def __init__(self,
                 config_fn=None,
                 assert_fn=None,
                 name='TestableProcess',
                 always_run_as_subproc=False,
                 *args,
                 **kwargs):
        super().__init__()
        self.log = get_logger(name)
        self.name = name

        self.config_fn = config_fn  # Function to configure object with mocks
        self.assert_fn = assert_fn  # Function to run assertions on said mocks

        self.test_proc = None
        self.container_name = None  # Name of the docker container this object is proxying to (if run on VM)

        # Create a wrapper around the build_obj with args and kwargs. We do this b/c this function will actually be
        # invoked in a separate process/machine, thus we need to capture the function call to serialize it and send
        # it across a socket
        build_fn = wrap_func(type(self).build_obj, *args, **kwargs)

        self._config_url_and_test_proc(build_fn, always_run_as_subproc)

        # 'socket' is used to proxy commands to blocking object running in a child process (or possibly on a VM)
        self.ctx = zmq.Context()
        self.socket = self.ctx.socket(socket_type=zmq.PAIR)
        self.log.debug("Test Orchestrator connecting to url {}".format(
            self.url))
        self.socket.connect(self.url)

        # Block this process until we get a ready signal from the subprocess/VM
        self.wait_for_test_object()

    def _config_url_and_test_proc(self, build_fn, always_run_as_subproc):
        # Add this object to the registry of testers
        from .mp_test_case import MPTestCase
        MPTestCase.testers.append(self)

        # Create Tester object in a VM
        if MPTestCase.vmnet_test_active and not always_run_as_subproc:
            assert hasattr(
                MPTestCase, 'ports'
            ), "VMNet test is active, but MPTestCase has no attribute ports"
            assert MPTestCase.ports, "VMNet test is active, but MPTestCase.ports is not set"

            name, ip = MPTestCase.next_container()
            assert name in MPTestCase.ports, "Node named {} not found in ports {}".format(
                name, MPTestCase.ports)
            assert MPTEST_PORT in MPTestCase.ports[name], "MPTEST_PORT {} not found in docker node {}'s ports {}"\
                                                          .format(MPTEST_PORT, name, MPTestCase.ports[name])

            url = MPTestCase.ports[name][
                MPTEST_PORT]  # URL the orchestration node should connect to
            url = url.replace('localhost',
                              '127.0.0.1')  # Adjust localhost to 127.0.0.1
            url = "tcp://{}".format(url)

            remote_url = "tcp://{}:{}".format(
                ip, MPTEST_PORT)  # URL the remote node should bind to
            self.container_name = name
            self.url = url
            self.ip = ip

            self.log.notice(
                "Creating node named {} in a docker container with name {} and ip {}"
                .format(self.name, name, self.ip))

            runner_func = wrap_func(_run_test_proc, self.name, remote_url,
                                    build_fn, self.config_fn, self.assert_fn)

            # TODO -- will i need a ton of imports and stuff to make this run smoothly...?
            MPTestCase.execute_python(name, runner_func, async=True)

        # Create Tester object in a Subprocess
        else:
            self.url = _gen_url(self.name)
            self.log.notice(
                "Creating node named {} in a subprocess with IPC url {}".
                format(self.name, self.url))

            self.test_proc = LProcess(target=_run_test_proc,
                                      name=self.name,
                                      args=(
                                          self.name,
                                          self.url,
                                          build_fn,
                                          self.config_fn,
                                          self.assert_fn,
                                      ))
            self.test_proc.start()

    def wait_for_test_object(self):
        self.log.info("Tester waiting for rdy sig from test process...")
        msg = self.socket.recv_pyobj()
        assert msg == SIG_RDY, "Got msg from child thread {} but expected SIG_RDY".format(
            msg)
        self.log.info("GOT RDY SIG: {}".format(msg))

    @classmethod
    def build_obj(cls, *args, **kwargs) -> tuple:
        """
        Override to define how the blocking object should be initialized. Must return 2 element tuple, in the order
        <loop> (an EventLoop instance), and <object> (an instance of the blocking object to test).
        :return: Tuple of the form (loop, object_instance)

        It is assumed the object being returning is passed an event loop into its constructor, which it uses internally
        to schedule all its events.
        """
        raise NotImplementedError

    def teardown(self):
        self.log.debug("{} tearing down...".format(self.name))

        self.socket.close()

        if self.test_proc:
            self.log.debug("Joining tester terminate {}...".format(self.name))
            self.test_proc.terminate()
            self.test_proc.join()
            self.log.debug("Tester Proc {} joined".format(self.name))

        if self.container_name:
            # TODO clean up container???
            pass

        self.log.debug("{} done tearing down.".format(self.name))

    def __repr__(self):
        return '<' + self.name + "  " + str(type(self)) + '>'
Ejemplo n.º 4
0
class MPTesterBase:
    """
    TODO docstring
    """
    testers = []
    tester_cls = 'UNSET'

    def __init__(self, config_fn=None, assert_fn=None, name='TestableProcess', *args, **kwargs):
        super().__init__()
        self.log = get_logger(name)
        self.name = name
        self.url = _gen_url(name)

        self.config_fn = config_fn  # Function to configure object with mocks
        self.assert_fn = assert_fn  # Function to run assertions on said mocks

        # 'socket' is used to proxy commands to blocking object running in a child process (possibly on a VM)
        self.ctx = zmq.Context()
        self.socket = self.ctx.socket(socket_type=zmq.PAIR)
        self.socket.bind(self.url)

        # Add this object to the registry of testers
        MPTesterBase.testers.append(self)

        # Create a wrapper around the build_obj with args and kwargs. We do this b/c this function will actually be
        # invoked in a separate process/machine, thus we need to capture the function call to serialize it and send
        # it across a socket
        build_fn = wrap_func(type(self).build_obj, *args, **kwargs)

        # Create and start the subprocess that will run the blocking object
        self.test_proc = LProcess(target=self._run_test_proc, args=(self.name, self.url, build_fn,
                                                               self.config_fn, self.assert_fn,))
        self.start_test()

    def start_test(self):
        self.test_proc.start()

        # self.log.critical("\n\n attempting to execute stuff on the vm \n\n")
        # execute_python('node_8', wrap_func(start_vm_test, self.name, self.url, type(self).build_obj,
        #                                    self.config_fn, self.assert_fn), async=True)
        # execute_python('node_8', wrap_func(start_vm_test, self.name, self.url, build_reactor_obj,
        #                                    self.config_fn, self.assert_fn), async=True)
        # execute_python('node_8', wrap_func(start_vm_test), async=True)

        self.log.critical("tester waiting for child proc rdy sig...")
        msg = self.socket.recv_pyobj()
        assert msg == SIG_RDY, "Got msg from child thread {} but expected SIG_RDY".format(msg)
        self.log.critical("GOT RDY SIG: {}".format(msg))

    def _run_test_proc(self, name, url, build_fn, config_fn, assert_fn):
        # TODO create socket outside of loop and pass it in for
        tester = MPTesterProcess(name=name, url=url, build_fn=build_fn, config_fn=config_fn, assert_fn=assert_fn)
        tester_socket = tester.socket

        try:
            tester.start_test()
        except Exception as e:
            self.log.error("\n\n TesterProcess encountered exception outside of internal loop! Error:\n {}\n\n"
                           .format(traceback.format_exc()))
            tester_socket.send_pyobj(SIG_FAIL)
            tester._teardown()

    @classmethod
    def build_obj(cls, *args, **kwargs) -> tuple:
        """
        Override to define how the blocking object should be initialized. Must return 2 element tuple, in the order
        <loop> (an EventLoop instance), and <object> (an instance of the blocking object to test).
        :return: Tuple of the form (loop, object_instance)

        It is assumed the object being returning is passed an event loop into its constructor, which it uses internally
        to schedule all its events.
        """
        raise NotImplementedError

    def teardown(self):
        # self.log.critical("\n\nTEARING DOWN\n\n")
        self.socket.close()
        # self.log.debug("---- joining {} ---".format(self.test_proc.name))
        self.test_proc.join()
        # self.log.debug("***** {} joined *****".format(self.test_proc.name))

    def __repr__(self):
        return self.name + "  " + str(type(self))
Ejemplo n.º 5
0
            await asyncio.sleep(self.rest_time)

    @input(AnswerReply)
    def handle_answer(self, answer: AnswerReply, envelope: Envelope, **kwargs):
        self.log.important2("Got answer {} ".format(answer.answer))


if __name__ == "__main__":
    # All these kwargs get set as instance variables on the Producer instance. So, for example,
    # inside producer code, self.num_pokes = 36, self.rest_time = 3, ect ect
    producer = LProcess(target=Producer,
                        kwargs={
                            'name': 'Sir Producer',
                            'num_pokes': 36,
                            'rest_time': 3,
                            'pubsub_port': PUBSUB_PORT,
                            'dealroute_port': DEALROUTE_PORT,
                            'ip': LOCAL_HOST,
                            'filter': FILTER,
                            'signing_key': PROD_SK
                        })

    pubsub_consumer = LProcess(target=PubSubConsumer,
                               kwargs={
                                   'name': 'Mr. PubSubConsumer',
                                   'pubsub_port': PUBSUB_PORT,
                                   'ip': LOCAL_HOST,
                                   'filter': FILTER,
                                   'signing_key': CONSUMER1_SK
                               })
    dealroute_consumer = LProcess(target=RepReplyConsumer,