def test_1_1_1(self): """ Tests pub/sub 1-1 (one sub one pub) with one message """ def configure_interface(reactor: ReactorInterface): reactor._run_callback = MagicMock() return reactor def run_assertions(reactor: ReactorInterface): callback = 'route' data = env.serialize() reactor._run_callback.assert_called_once_with(callback, data) env = random_envelope() sub = MPReactorInterface(config_fn=configure_interface, assert_fn=run_assertions, name='** SUB') pub = MPReactorInterface(name='++ PUB') # test self.execute_python('node_1', something_silly, async=True) # end tests add_sub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_sub.__name__, url=URL, filter=FILTER) add_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_pub.__name__, url=URL) send_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.send_pub.__name__, envelope=env, filter=FILTER) sub.send_cmd(add_sub_cmd) pub.send_cmd(add_pub_cmd) time.sleep(0.2) # To allow time for subs to connect to pub before pub sends data pub.send_cmd(send_pub_cmd) self.start()
def test_subpub_1_n_1(self): """ Tests sub/pub with 1 publisher and 3 subs, with one message """ def configure_interface(reactor: ReactorInterface): reactor._run_callback = MagicMock() return reactor def run_assertions(reactor: ReactorInterface): callback = 'route' data = env.serialize() reactor._run_callback.assert_called_once_with(callback, data) env = random_envelope() sub1 = MPReactorInterface(config_fn=configure_interface, assert_fn=run_assertions, name='** SUB1') sub2 = MPReactorInterface(config_fn=configure_interface, assert_fn=run_assertions, name='** SUB2') sub3 = MPReactorInterface(config_fn=configure_interface, assert_fn=run_assertions, name='** SUB3') pub = MPReactorInterface(name='++ PUB') add_sub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_sub.__name__, url=URL, filter=FILTER) add_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_pub.__name__, url=URL) send_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.send_pub.__name__, envelope=env, filter=FILTER) sub1.send_cmd(add_sub_cmd) sub2.send_cmd(add_sub_cmd) sub3.send_cmd(add_sub_cmd) pub.send_cmd(add_pub_cmd) time.sleep(0.2) pub.send_cmd(send_pub_cmd) self.start()
def test_pubsub_1_1_n_filters(self): """ Test pub/sub 1-1 with multiple filters, only some of which should be received """ def configure_interface(reactor: ReactorInterface): reactor._run_callback = MagicMock() return reactor def run_assertions(reactor: ReactorInterface): callback = 'route' data = env.serialize() reactor._run_callback.assert_called_once_with(callback, data) env = random_envelope() env2 = random_envelope() sub = MPReactorInterface(config_fn=configure_interface, assert_fn=run_assertions, name='** SUB') pub = MPReactorInterface(name='++ PUB 1') pub = MPReactorInterface(name='++ PUB 2') add_sub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_sub.__name__, url=URL, filter=FILTER) add_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_pub.__name__, url=URL) send_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.send_pub.__name__, envelope=env, filter=FILTER) sub.send_cmd(add_sub_cmd) pub.send_cmd(add_pub_cmd) time.sleep(0.2) # To allow time for subs to connect to pub before pub sends data pub.send_cmd(send_pub_cmd) time.sleep(0.2) # Allow pubs to go through self.start()
def send_request_env(self, envelope: Envelope, timeout=0, ip: str='', vk: str=''): url = "tcp://{}:{}".format(ip or vk, Constants.Ports.RouterDealer) reply_uuid = EnvelopeAuth.reply_uuid(envelope.meta.uuid) cmd = ReactorCommand.create_cmd(DealerRouterExecutor.__name__, DealerRouterExecutor.request.__name__, url=url, envelope=envelope, timeout=timeout, reply_uuid=reply_uuid) self.interface.send_cmd(cmd)
def add_router(self, ip: str='', vk: str=''): """ Add a router socket at url. Routers are like 'async repliers', and can connect to many Dealer sockets (N-1) :param url: The URL the router socket should BIND to :param vk: The Node's VK to connect to. This will be looked up in the overlay network """ url = "tcp://{}:{}".format(ip or vk, Constants.Ports.RouterDealer) cmd = ReactorCommand.create_cmd(DealerRouterExecutor.__name__, DealerRouterExecutor.add_router.__name__, url=url) self.interface.send_cmd(cmd)
def remove_pub(self, ip: str='', vk: str=''): """ Removes a publisher (duh) :param url: The URL of the router that the created dealer socket should CONNECT to. :param vk: The Node's VK to connect to. This will be looked up in the overlay network """ url = "tcp://{}:{}".format(ip or vk, Constants.Ports.PubSub) cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.remove_pub.__name__, url=url) self.interface.send_cmd(cmd)
def add_pub(self, ip: str=''): """ Create a publisher socket that BINDS to 'url' :param url: The URL to publish under. :param vk: The Node's VK to connect to. This will be looked up in the overlay network """ url = "tcp://{}:{}".format(ip or vk, Constants.Ports.PubSub) cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_pub.__name__, url=url) self.interface.send_cmd(cmd)
def send_pub_env(self, filter: str, envelope: Envelope): """ Publish envelope with filter frame 'filter'. :param filter: A string to use as the filter frame :param envelope: An instance of Envelope """ cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.send_pub.__name__, filter=filter, envelope=envelope) self.interface.send_cmd(cmd)
def test_req_1_1_1(self): """ Tests dealer router 1/1 (1 dealer, 1 router) with 1 message request (dealer sends router 1 message) """ def run_assertions(reactor: ReactorInterface): cb = ReactorCommand.create_callback(callback=ROUTE_REQ_CALLBACK, envelope=env, header=DEALER_ID) reactor._run_callback.assert_called_once_with(cb) DEALER_URL = URLS[0] DEALER_ID = "id-" + DEALER_URL # irl this would a node's vk ROUTER_URL = URLS[1] env = random_envelope() dealer = MPReactorInterface(name='DEALER') router = MPReactorInterface(config_fn=config_reactor, assert_fn=run_assertions, name='ROUTER') add_dealer = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_dealer.__name__, url=ROUTER_URL, id=DEALER_ID) add_router = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_router.__name__, url=ROUTER_URL) request = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.request.__name__, url=ROUTER_URL, envelope=env) dealer.send_cmd(add_dealer) router.send_cmd(add_router) time.sleep(0.2) dealer.send_cmd(request) self.start()
def add_sub(self, filter: str, ip: str='', vk: str=''): """ Connects the subscriber socket to listen to 'URL' with filter 'filter'. :param url: The URL to CONNECT the sub socket to (ex 'tcp://17.1.3.4:4200') :param filter: The filter to subscribe to. Only data published with this filter will be received. Currently, only one filter per CONNECT is supported. """ # url = "tcp://{}:{}".format(ip or vk, Constants.Ports.PubSub) url = "tcp://{}:{}".format(ip or vk, Constants.Ports.PubSub) cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_sub.__name__, filter=filter, url=url, vk=vk) self.interface.send_cmd(cmd)
def add_dealer(self, ip: str='', vk: str=''): """ Add a dealer socket at url. Dealers are like 'async requesters', and can connect to a single Router socket (1-1) (side note: A router socket, however, can connect to N dealers) 'id' socketopt for the dealer socket will be this node's verifying key :param url: The URL of the router that the created dealer socket should CONNECT to. :param vk: The Node's VK to connect to. This will be looked up in the overlay network """ url = "tcp://{}:{}".format(ip or vk, Constants.Ports.RouterDealer) cmd = ReactorCommand.create_cmd(DealerRouterExecutor.__name__, DealerRouterExecutor.add_dealer.__name__, id=self.verifying_key, url=url, vk=vk) self.interface.send_cmd(cmd)
def test_create_with_envelope(self): """ Tests creating a message with an envelope produces an object with the expected properties """ sk, vk = ED25519Wallet.new() tx = StandardTransactionBuilder.random_tx() sender = 'me' env = Envelope.create_from_message(message=tx, signing_key=sk) cmd = ReactorCommand.create_cmd('some_cls', 'some_func', envelope=env) self.assertTrue(ReactorCommand.envelope, env)
def send_reply(self, message: MessageBase, request_envelope: Envelope): """ Send a reply message (via a Router socket) for the original reqeust in request_envelope (which came from a Dealer socket). Replies envelope are created as a deterministic function of their original request envelope, so that both parties (the sender and receiver) are in agreement on what the reply envelope should look like :param message: A MessageBase instance that denotes the reply data :param request_envelope: An Envelope instance that denotes the envelope of the original request that we are replying to """ requester_id = request_envelope.seal.verifying_key reply_env = self._package_reply(reply=message, req_env=request_envelope) cmd = ReactorCommand.create_cmd(DealerRouterExecutor.__name__, DealerRouterExecutor.reply.__name__, id=requester_id, envelope=reply_env) self.interface.send_cmd(cmd)
def test_req_reply_1_1_1(self): """ Tests a request/reply round trip between dealer and router. """ def config_dealer(reactor: ReactorInterface): reactor._run_callback = MagicMock() return reactor def config_router(reactor: ReactorInterface): def reply_effect(*args, **kwargs): # log = get_logger("ASSERT ROUTER SIDE EFFECT WTIH") # log.critical("\n\n sending reply command... \n\n") reactor.send_cmd(reply) dealer.send_cmd(reply) reactor._run_callback = MagicMock() reactor._run_callback.side_effect = reply_effect return reactor def assert_dealer(reactor: ReactorInterface): cb = ReactorCommand.create_callback(callback=ROUTE_CALLBACK, envelope=rep_env) reactor._run_callback.assert_called_once_with(cb) def assert_router(reactor: ReactorInterface): cb = ReactorCommand.create_callback(callback=ROUTE_REQ_CALLBACK, envelope=req_env, header=DEALER_ID) reactor._run_callback.assert_called_once_with(cb) # reactor._run_callback.side_effect = reply_effect DEALER_URL = URLS[0] DEALER_ID = "id-" + DEALER_URL # irl this would a node's vk ROUTER_URL = URLS[1] req_env = random_envelope() rep_env = random_envelope() add_dealer = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_dealer.__name__, url=ROUTER_URL, id=DEALER_ID) add_router = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_router.__name__, url=ROUTER_URL) request = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.request.__name__, url=ROUTER_URL, envelope=req_env) reply = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.reply.__name__, id=DEALER_ID, envelope=rep_env) dealer = MPReactorInterface(name='DEALER', config_fn=config_dealer, assert_fn=assert_dealer) router = MPReactorInterface(config_fn=config_router, assert_fn=assert_router, name='ROUTER') dealer.send_cmd(add_dealer) router.send_cmd(add_router) time.sleep(0.2) dealer.send_cmd(request) self.start()
def test_req_1_n_1(self): """ Tests req from 1 dealer to 2 routers. """ def run_assertions(reactor: ReactorInterface): cb = ReactorCommand.create_callback(callback=ROUTE_REQ_CALLBACK, envelope=env, header=DEALER_ID) reactor._run_callback.assert_called_once_with(cb) DEALER_URL = URLS[0] DEALER_ID = "id-" + DEALER_URL # irl this would a node's vk ROUTER1_URL = URLS[0] ROUTER2_URL = URLS[1] env = random_envelope() dealer = MPReactorInterface(name='DEALER') router1 = MPReactorInterface(config_fn=config_reactor, assert_fn=run_assertions, name='ROUTER 1') router2 = MPReactorInterface(config_fn=config_reactor, assert_fn=run_assertions, name='ROUTER 2') add_dealer1 = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_dealer.__name__, url=ROUTER1_URL, id=DEALER_ID) add_dealer2 = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_dealer.__name__, url=ROUTER2_URL, id=DEALER_ID) add_router1 = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_router.__name__, url=ROUTER1_URL) add_router2 = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.add_router.__name__, url=ROUTER2_URL) request1 = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.request.__name__, url=ROUTER1_URL, envelope=env) request2 = ReactorCommand.create_cmd( class_name=DealerRouterExecutor.__name__, func_name=DealerRouterExecutor.request.__name__, url=ROUTER2_URL, envelope=env) dealer.send_cmd(add_dealer1) dealer.send_cmd(add_dealer2) router1.send_cmd(add_router1) router2.send_cmd(add_router2) time.sleep(0.2) dealer.send_cmd(request1) dealer.send_cmd(request2) self.start()
print(reactor._run_callback.assert_called()) def do_nothing(reactor: ReactorInterface): print("do nothing this will pass") pass if __name__ == '__main__': log = get_logger("Main") log.debug("hello test") sub = TestableReactor(configure_interface, run_assertions) pub = TestableReactor(configure_interface, do_nothing) env = random_envelope() add_sub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_sub.__name__, url=URL, filter=FILTER) add_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.add_pub.__name__, url=URL) send_pub_cmd = ReactorCommand.create_cmd(SubPubExecutor.__name__, SubPubExecutor.send_pub.__name__, envelope=env, filter=FILTER) sub.send_cmd(add_sub_cmd) pub.send_cmd(add_pub_cmd) import time time.sleep(1) pub.send_cmd(send_pub_cmd) log.critical("waiting for kill switching from tester...") msg = sub.sig_q.get() log.critical("GOT MSG FROM TESTER PROC: {}".format(msg))