def test_unsubscribe_and_subscribe_again(nsproxy, socket_type): """ Test resubscribing to topics after unsubscribing works fine. """ server = run_agent('server', base=ServerNumbers) client = run_agent('client') addr = server.bind(socket_type, alias='pub', handler=append_received) client.set_attr(received=[]) client.connect(addr, alias='sub', handler=append_received) # Establish a connection server.each(0.1, 'send', 'pub', 'connecting...', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Subscribe to two topics client.unsubscribe('sub', '') client.subscribe('sub', handler={'negate': receive_negate, 'normal': append_received}) # Make server to start publishing messages server.each(0.1, 'publish') assert wait_agent_condition(client, match_tail, [-1, 2] * 4) # Unsubscribe from one topic client.unsubscribe('sub', 'negate') assert wait_agent_condition(client, match_tail, [2] * 8) # Subscribe again client.subscribe('sub', handler={'negate': receive_negate}) assert wait_agent_condition(client, match_tail, [-1, 2] * 4)
def test_resubscribe(nsproxy, socket_type): """ After subscribing to the same topic with a different handler after a subscription to that topic was already made, we should override the original handler. Note that we will only override explicitly given topics (previous subscriptions of other topics will remain untouched). """ server = run_agent('server', base=ServerNumbers) client = run_agent('client') addr = server.bind(socket_type, alias='pub', handler=append_received) client.set_attr(received=[]) client.connect(addr, alias='sub', handler=append_received) # Establish a connection server.each(0.1, 'send', 'pub', 'connecting...', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Subscribe to two topics client.unsubscribe('sub', '') client.subscribe('sub', handler={'negate': receive_negate, 'normal': append_received}) server.each(0.1, 'publish') assert wait_agent_condition(client, match_tail, [-1, 2] * 4) # Resubscribe, so as to store the 'normal' (2) messages negated client.subscribe('sub', handler={'normal': receive_negate}) assert wait_agent_condition(client, match_tail, [-1, -2] * 4)
def test_subscribe(nsproxy, socket_type, subscribe_separately): """ Test subscribing to various topics/handlers works fine. """ server = run_agent('server', base=ServerNumbers) client = run_agent('client') addr = server.bind(socket_type, alias='pub', handler=append_received) client.set_attr(received=[]) client.connect(addr, alias='sub', handler=append_received) # Establish a connection server.each(0.1, 'send', 'pub', 'connecting...', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Subscribe to two topics. Client should only receive -1 and 2. client.unsubscribe('sub', '') if subscribe_separately: client.subscribe('sub', handler={'negate': receive_negate}) client.subscribe('sub', handler={'normal': append_received}) else: client.subscribe('sub', handler={ 'negate': receive_negate, 'normal': append_received }) server.each(0.1, 'publish') assert wait_agent_condition(client, match_tail, [-1, 2] * 4)
def test_subscribe(nsproxy, socket_type, subscribe_separately): """ Test subscribing to various topics/handlers works fine. """ server = run_agent('server', base=ServerNumbers) client = run_agent('client') addr = server.bind(socket_type, alias='pub', handler=append_received) client.set_attr(received=[]) client.connect(addr, alias='sub', handler=append_received) # Establish a connection server.each(0.1, 'send', 'pub', 'connecting...', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Subscribe to two topics. Client should only receive -1 and 2. client.unsubscribe('sub', '') if subscribe_separately: client.subscribe('sub', handler={'negate': receive_negate}) client.subscribe('sub', handler={'normal': append_received}) else: client.subscribe('sub', handler={'negate': receive_negate, 'normal': append_received}) server.each(0.1, 'publish') assert wait_agent_condition(client, match_tail, [-1, 2] * 4)
def test_unsubscribe_various(nsproxy, socket_type): """ Test that unsubscribing from various topics works fine. The server will be publishing zeroes through two topics quickly, and ones through a single topic slowly. A subscriber will subscribe to all numbers, and then unsubscribe from the topics related to the zeroes, therefore receiving three (or more) ones in a row. """ def check_sum_three(agent): """ Check whether the last three received numbers sum to three. For this test in particular, the last three numbers should be one, received through the 'one' topic. """ return sum(agent.received[-3:]) == 3 def publish_zeroes(agent): agent.send('pub', 0, topic='zero') agent.send('pub', 0, topic='other_zero') def publish_one(agent): agent.send('pub', 1, topic='one') # Set up the agents server = run_agent('server') client = run_agent('client', base=Client) addr = server.bind(socket_type, alias='pub', handler=append_received) client.connect( addr, alias='sub', handler={ 'zero': append_received, 'other_zero': append_received, 'one': append_received, }, ) # Make sure the connection is established server.each(0.1, 'send', 'pub', 'connecting...', topic='zero', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Wait until client receives some numbers client.set_attr(received=[]) server.each(0.1, publish_zeroes) server.each(0.2, publish_one) assert wait_agent_attr(client, length=5) assert not client.execute_as_method(check_sum_three) # Unsubscribe from zeroes numbers (receiving only ones) client.unsubscribe('sub', ('zero', 'other_zero')) assert wait_agent_condition(client, check_sum_three)
def test_unsubscribe(nsproxy, socket_type): """ Test that unsubscribing from topics works fine. The server will be publishing the natural numbers, in ascending order, starting at one. Odd numbers will be sent with `odd` topic and even numbers with `even` topic. A subscriber will subscribe to all numbers, and then it will unsubscribe from the odd numbers. Two non consecutive numbers must be received consecutively at that point, since they both will be even. """ def check_non_consecutive(agent): """ Check whether the last two received numbers are non-consecutive. """ return agent.received[-1] - agent.received[-2] != 1 def publish(agent): assert agent.count % 2 == 1 agent.send('pub', agent.count, topic='odd') agent.send('pub', agent.count + 1, topic='even') agent.count += 2 # Set up the agents server = run_agent('server') client = run_agent('client', base=Client) server.set_attr(count=1) addr = server.bind(socket_type, alias='pub', handler=append_received) client.connect( addr, alias='sub', handler={ 'odd': append_received, 'even': append_received }, ) # Make sure the connection is established server.each(0.1, 'send', 'pub', 'connecting...', topic='odd', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Wait until client receives some numbers client.set_attr(received=[]) server.each(0.1, publish) assert wait_agent_attr(client, length=5) assert not client.execute_as_method(check_non_consecutive) # Unsubscribe from odd numbers (receiving only even numbers) client.unsubscribe('sub', 'odd') assert wait_agent_condition(client, check_non_consecutive) assert client.get_attr('received')[-1] % 2 == 0
def test_unsubscribe_various(nsproxy, socket_type): """ Test that unsubscribing from various topics works fine. The server will be publishing zeroes through two topics quickly, and ones through a single topic slowly. A subscriber will subscribe to all numbers, and then unsubscribe from the topics related to the zeroes, therefore receiving three (or more) ones in a row. """ def check_sum_three(agent): """ Check whether the last three received numbers sum to three. For this test in particular, the last three numbers should be one, received through the 'one' topic. """ return sum(agent.received[-3:]) == 3 def publish_zeroes(agent): agent.send('pub', 0, topic='zero') agent.send('pub', 0, topic='other_zero') def publish_one(agent): agent.send('pub', 1, topic='one') # Set up the agents server = run_agent('server') client = run_agent('client', base=Client) addr = server.bind(socket_type, alias='pub', handler=append_received) client.connect(addr, alias='sub', handler={'zero': append_received, 'other_zero': append_received, 'one': append_received}) # Make sure the connection is established server.each(0.1, 'send', 'pub', 'connecting...', topic='zero', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Wait until client receives some numbers client.set_attr(received=[]) server.each(0.1, publish_zeroes) server.each(0.2, publish_one) assert wait_agent_attr(client, length=5) assert not client.execute_as_method(check_sum_three) # Unsubscribe from zeroes numbers (receiving only ones) client.unsubscribe('sub', ('zero', 'other_zero')) assert wait_agent_condition(client, check_sum_three)
def test_unsubscribe(nsproxy, socket_type): """ Test that unsubscribing from topics works fine. The server will be publishing the natural numbers, in ascending order, starting at one. Odd numbers will be sent with `odd` topic and even numbers with `even` topic. A subscriber will subscribe to all numbers, and then it will unsubscribe from the odd numbers. Two non consecutive numbers must be received consecutively at that point, since they both will be even. """ def check_non_consecutive(agent): """ Check whether the last two received numbers are non-consecutive. """ return agent.received[-1] - agent.received[-2] != 1 def publish(agent): assert agent.count % 2 == 1 agent.send('pub', agent.count, topic='odd') agent.send('pub', agent.count + 1, topic='even') agent.count += 2 # Set up the agents server = run_agent('server') client = run_agent('client', base=Client) server.set_attr(count=1) addr = server.bind(socket_type, alias='pub', handler=append_received) client.connect(addr, alias='sub', handler={'odd': append_received, 'even': append_received}) # Make sure the connection is established server.each(0.1, 'send', 'pub', 'connecting...', topic='odd', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Wait until client receives some numbers client.set_attr(received=[]) server.each(0.1, publish) assert wait_agent_attr(client, length=5) assert not client.execute_as_method(check_non_consecutive) # Unsubscribe from odd numbers (receiving only even numbers) client.unsubscribe('sub', 'odd') assert wait_agent_condition(client, check_non_consecutive) assert client.get_attr('received')[-1] % 2 == 0
def test_unsubscribe_and_subscribe_again(nsproxy, socket_type): """ Test resubscribing to topics after unsubscribing works fine. """ server = run_agent('server', base=ServerNumbers) client = run_agent('client') addr = server.bind(socket_type, alias='pub', handler=append_received) client.set_attr(received=[]) client.connect(addr, alias='sub', handler=append_received) # Establish a connection server.each(0.1, 'send', 'pub', 'connecting...', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Subscribe to two topics client.unsubscribe('sub', '') client.subscribe('sub', handler={ 'negate': receive_negate, 'normal': append_received }) # Make server to start publishing messages server.each(0.1, 'publish') assert wait_agent_condition(client, match_tail, [-1, 2] * 4) # Unsubscribe from one topic client.unsubscribe('sub', 'negate') assert wait_agent_condition(client, match_tail, [2] * 8) # Subscribe again client.subscribe('sub', handler={'negate': receive_negate}) assert wait_agent_condition(client, match_tail, [-1, 2] * 4)
def test_wait_agent_condition(nsproxy): """ Test `wait_agent_condition` function. """ class Counter(Agent): def on_init(self): self.count = 0 self.log = [] def increment(self): self.log.append(self.count) self.count += 1 time.sleep(0.1) def log_length(agent, size): return len(agent.log) > size a0 = run_agent('a0', base=Counter) a0.each(0., 'increment') assert not wait_agent_condition(a0, log_length, size=4, timeout=0.2) assert wait_agent_condition(a0, log_length, size=10, timeout=1.) assert wait_agent_condition(a0, lambda agent: agent.count > 8, timeout=0.)
def test_wait_agent_condition(nsproxy): """ Test `wait_agent_condition` function. """ class Counter(Agent): def on_init(self): self.count = 0 self.log = [] def increment(self): self.log.append(self.count) self.count += 1 time.sleep(0.1) def log_length(agent, size): return len(agent.log) > size a0 = run_agent('a0', base=Counter) a0.each(0., 'increment') assert not wait_agent_condition(a0, log_length, size=4, timeout=0.2) assert wait_agent_condition(a0, log_length, size=10, timeout=1.) assert wait_agent_condition(a0, lambda agent: agent.count > 8, timeout=0.)
def test_resubscribe(nsproxy, socket_type): """ After subscribing to the same topic with a different handler after a subscription to that topic was already made, we should override the original handler. Note that we will only override explicitly given topics (previous subscriptions of other topics will remain untouched). """ server = run_agent('server', base=ServerNumbers) client = run_agent('client') addr = server.bind(socket_type, alias='pub', handler=append_received) client.set_attr(received=[]) client.connect(addr, alias='sub', handler=append_received) # Establish a connection server.each(0.1, 'send', 'pub', 'connecting...', alias='tmp') assert wait_agent_attr(client, data='connecting...') server.stop_timer('tmp') # Subscribe to two topics client.unsubscribe('sub', '') client.subscribe('sub', handler={ 'negate': receive_negate, 'normal': append_received }) server.each(0.1, 'publish') assert wait_agent_condition(client, match_tail, [-1, 2] * 4) # Resubscribe, so as to store the 'normal' (2) messages negated client.subscribe('sub', handler={'normal': receive_negate}) assert wait_agent_condition(client, match_tail, [-1, -2] * 4)
def test_timer_recursion(nsproxy): """ This bug occurred with the first implementation of the timer. After some iterations the timer would throw an exception when the recursion limit was exceeded. Timers should never reach a recursion limit. """ def inc(agent): agent.count += 1 agent = run_agent('a0') agent.set_attr(count=0) agent.each(0.0, inc) limit = sys.getrecursionlimit() assert wait_agent_condition(agent, lambda agent: agent.count > limit, timeout=10)
def test_pubsub_topics_raw(nsproxy, serializer): """ Simple publisher-subscriber pattern test. Different messages sent with different agents subscribed to different topics are tested within this method. In the raw version of PUBSUB, we want to replicate the raw message passing of ZMQ, in which the topic is passed along the message and it is the responsibility of the handler to split them. """ a0 = run_agent('a0') a1 = run_agent('a1') a2 = run_agent('a2') a3 = run_agent('a3') a4 = run_agent('a4') a5 = run_agent('a5') for agent in (a1, a2, a3, a4, a5): agent.set_attr(received=[]) addr = a0.bind('PUB', alias='pub', serializer=serializer) a1.connect(addr, handler=append_received) a2.connect(addr, handler={'foo': append_received}) a3.connect(addr, handler={'bar': append_received, 'foo': append_received}) a4.connect(addr, handler={'bar': append_received}) a5.connect(addr, handler={'fo': append_received}) # Make sure all agents are connected a0.each(0.1, 'send', 'pub', b'first', topic='foo') a0.each(0.1, 'send', 'pub', b'first', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, b'first') a0.stop_all_timers() # Send some messages message_01 = b'Hello' a0.send('pub', message_01) message_02 = b'World' a0.send('pub', message_02, topic='foo') message_03 = b'FOO' a0.send('pub', message_03, topic='foobar') message_04 = b'BAR' a0.send('pub', message_04, topic='fo') # Make sure all agents are connected a0.send('pub', b'last', topic='foo') a0.send('pub', b'last', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, b'last') # Check each agent received the corresponding messages assert message_01 in a1.get_attr('received') assert b'fooWorld' in a1.get_attr('received') assert b'foobarFOO' in a1.get_attr('received') assert b'foBAR' in a1.get_attr('received') assert message_01 not in a2.get_attr('received') assert b'fooWorld' in a2.get_attr('received') assert b'foobarFOO' in a2.get_attr('received') assert b'foBAR' not in a2.get_attr('received') assert message_01 not in a3.get_attr('received') assert b'fooWorld' in a3.get_attr('received') assert b'foobarFOO' in a3.get_attr('received') assert b'foBAR' not in a3.get_attr('received') assert message_01 not in a4.get_attr('received') assert b'fooWorld' not in a4.get_attr('received') assert b'foobarFOO' not in a4.get_attr('received') assert b'foBAR' not in a4.get_attr('received') assert message_01 not in a5.get_attr('received') assert b'fooWorld' in a5.get_attr('received') assert b'foobarFOO' in a5.get_attr('received') assert b'foBAR' in a5.get_attr('received')
def test_pubsub_topics_separator(nsproxy, serializer): """ Simple publisher-subscriber pattern test using serializers that require a separation in message composition. Different messages sent with different agents subscribed to different topics are tested within this method. """ a0 = run_agent('a0') a1 = run_agent('a1') a2 = run_agent('a2') a3 = run_agent('a3') a4 = run_agent('a4') a5 = run_agent('a5') for agent in (a1, a2, a3, a4, a5): agent.set_attr(received=[]) addr = a0.bind('PUB', alias='pub', serializer=serializer) a1.connect(addr, handler=append_received) a2.connect(addr, handler={'foo': append_received}) a3.connect(addr, handler={'bar': append_received, 'foo': append_received}) a4.connect(addr, handler={'bar': append_received}) a5.connect(addr, handler={'fo': append_received}) # Make sure all agents are connected a0.each(0.1, 'send', 'pub', 'first', topic='foo') a0.each(0.1, 'send', 'pub', 'first', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, 'first') a0.stop_all_timers() # Send some messages message_01 = 'Hello' a0.send('pub', message_01) message_02 = 'World' a0.send('pub', message_02, topic='foo') message_03 = 'FOO' a0.send('pub', message_03, topic='foobar') message_04 = 'BAR' a0.send('pub', message_04, topic='fo') # Make sure all messages are processed a0.send('pub', 'last', topic='foo') a0.send('pub', 'last', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, 'last') # Check each agent received the corresponding messages assert message_01 in a1.get_attr('received') assert message_02 in a1.get_attr('received') assert message_03 in a1.get_attr('received') assert message_04 in a1.get_attr('received') assert message_01 not in a2.get_attr('received') assert message_02 in a2.get_attr('received') assert message_03 in a2.get_attr('received') assert message_04 not in a2.get_attr('received') assert message_01 not in a3.get_attr('received') assert message_02 in a3.get_attr('received') assert message_03 in a3.get_attr('received') assert message_04 not in a3.get_attr('received') assert message_01 not in a4.get_attr('received') assert message_02 not in a4.get_attr('received') assert message_03 not in a4.get_attr('received') assert message_04 not in a4.get_attr('received') assert message_01 not in a5.get_attr('received') assert message_02 in a5.get_attr('received') assert message_03 in a5.get_attr('received') assert message_04 in a5.get_attr('received')
def test_pubsub_topics_separator(nsproxy, serializer): """ Simple publisher-subscriber pattern test using serializers that require a separation in message composition. Different messages sent with different agents subscribed to different topics are tested within this method. """ a0 = run_agent('a0') a1 = run_agent('a1') a2 = run_agent('a2') a3 = run_agent('a3') a4 = run_agent('a4') a5 = run_agent('a5') for agent in (a1, a2, a3, a4, a5): agent.set_attr(received=[]) addr = a0.bind('PUB', alias='pub', serializer=serializer) a1.connect(addr, handler=append_received) a2.connect(addr, handler={'foo': append_received}) a3.connect(addr, handler={'bar': append_received, 'foo': append_received}) a4.connect(addr, handler={'bar': append_received}) a5.connect(addr, handler={'fo': append_received}) # Make sure all agents are connected a0.each(0.1, 'send', 'pub', 'first', topic='foo') a0.each(0.1, 'send', 'pub', 'first', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, 'first') a0.stop_all_timers() # Send some messages message_01 = 'Hello' a0.send('pub', message_01) message_02 = 'World' a0.send('pub', message_02, topic='foo') message_03 = 'FOO' a0.send('pub', message_03, topic='foobar') message_04 = 'BAR' a0.send('pub', message_04, topic='fo') # Make sure all messages are processed a0.send('pub', 'last', topic='foo') a0.send('pub', 'last', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, 'last') # Check each agent received the corresponding messages assert message_01 in a1.get_attr('received') assert message_02 in a1.get_attr('received') assert message_03 in a1.get_attr('received') assert message_04 in a1.get_attr('received') assert message_01 not in a2.get_attr('received') assert message_02 in a2.get_attr('received') assert message_03 in a2.get_attr('received') assert message_04 not in a2.get_attr('received') assert message_01 not in a3.get_attr('received') assert message_02 in a3.get_attr('received') assert message_03 in a3.get_attr('received') assert message_04 not in a3.get_attr('received') assert message_01 not in a4.get_attr('received') assert message_02 not in a4.get_attr('received') assert message_03 not in a4.get_attr('received') assert message_04 not in a4.get_attr('received') assert message_01 not in a5.get_attr('received') assert message_02 in a5.get_attr('received') assert message_03 in a5.get_attr('received') assert message_04 in a5.get_attr('received')
def test_pubsub_topics_raw(nsproxy, serializer): """ Simple publisher-subscriber pattern test. Different messages sent with different agents subscribed to different topics are tested within this method. In the raw version of PUBSUB, we want to replicate the raw message passing of ZMQ, in which the topic is passed along the message and it is the responsibility of the handler to split them. """ a0 = run_agent('a0') a1 = run_agent('a1') a2 = run_agent('a2') a3 = run_agent('a3') a4 = run_agent('a4') a5 = run_agent('a5') for agent in (a1, a2, a3, a4, a5): agent.set_attr(received=[]) addr = a0.bind('PUB', alias='pub', serializer=serializer) a1.connect(addr, handler=append_received) a2.connect(addr, handler={'foo': append_received}) a3.connect(addr, handler={'bar': append_received, 'foo': append_received}) a4.connect(addr, handler={'bar': append_received}) a5.connect(addr, handler={'fo': append_received}) # Make sure all agents are connected a0.each(0.1, 'send', 'pub', b'first', topic='foo') a0.each(0.1, 'send', 'pub', b'first', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, b'first') a0.stop_all_timers() # Send some messages message_01 = b'Hello' a0.send('pub', message_01) message_02 = b'World' a0.send('pub', message_02, topic='foo') message_03 = b'FOO' a0.send('pub', message_03, topic='foobar') message_04 = b'BAR' a0.send('pub', message_04, topic='fo') # Make sure all agents are connected a0.send('pub', b'last', topic='foo') a0.send('pub', b'last', topic='bar') for agent in (a1, a2, a3, a4, a5): assert wait_agent_condition(agent, last_received_endswith, b'last') # Check each agent received the corresponding messages assert message_01 in a1.get_attr('received') assert b'fooWorld' in a1.get_attr('received') assert b'foobarFOO' in a1.get_attr('received') assert b'foBAR' in a1.get_attr('received') assert message_01 not in a2.get_attr('received') assert b'fooWorld' in a2.get_attr('received') assert b'foobarFOO' in a2.get_attr('received') assert b'foBAR' not in a2.get_attr('received') assert message_01 not in a3.get_attr('received') assert b'fooWorld' in a3.get_attr('received') assert b'foobarFOO' in a3.get_attr('received') assert b'foBAR' not in a3.get_attr('received') assert message_01 not in a4.get_attr('received') assert b'fooWorld' not in a4.get_attr('received') assert b'foobarFOO' not in a4.get_attr('received') assert b'foBAR' not in a4.get_attr('received') assert message_01 not in a5.get_attr('received') assert b'fooWorld' in a5.get_attr('received') assert b'foobarFOO' in a5.get_attr('received') assert b'foBAR' in a5.get_attr('received')