def test_query_items_cache_clears_on_disconnect(self): to = structs.JID.fromstr("[email protected]/res1") response1 = disco_xso.ItemsQuery() self.cc.stream.send_iq_and_wait_for_reply.return_value = response1 with self.assertRaises(TypeError): self.s.query_items(to, "foobar") result1 = run_coroutine( self.s.query_items(to, node="foobar") ) self.cc.on_stream_destroyed() response2 = disco_xso.ItemsQuery() self.cc.stream.send_iq_and_wait_for_reply.return_value = response2 result2 = run_coroutine( self.s.query_items(to, node="foobar") ) self.assertIs(result1, response1) self.assertIs(result2, response2) self.assertEqual( 2, len(self.cc.stream.send_iq_and_wait_for_reply.mock_calls) )
def test_query_info_cache_override(self): to = structs.JID.fromstr("[email protected]/res1") with unittest.mock.patch.object( self.s, "send_and_decode_info_query", new=CoroutineMock()) as send_and_decode: response1 = {} send_and_decode.return_value = response1 result1 = run_coroutine( self.s.query_info(to, node="foobar") ) response2 = {} send_and_decode.return_value = response2 result2 = run_coroutine( self.s.query_info(to, node="foobar", require_fresh=True) ) self.assertIs(result1, response1) self.assertIs(result2, response2) self.assertEqual( 2, len(send_and_decode.mock_calls) )
def test_set_info_future_stays_even_with_exception(self): exc = ConnectionError() to = structs.JID.fromstr("[email protected]/res1") fut = asyncio.Future() self.s.set_info_future( to, None, fut ) request = asyncio.async( self.s.query_info(to) ) run_coroutine(asyncio.sleep(0)) self.assertFalse(request.done()) fut.set_exception(exc) with self.assertRaises(Exception) as ctx: run_coroutine(request) self.assertIs(ctx.exception, exc)
def test_update_groups_on_update(self): request = roster_xso.Query(items=[ roster_xso.Item( jid=self.user1, groups=[ roster_xso.Group(name="group4") ], ) ]) run_coroutine(self.s.handle_roster_push( stanza.IQ( structs.IQType.SET, payload=request ) )) self.assertNotIn("group3", self.s.groups) self.assertSetEqual( {self.s.items[self.user2]}, self.s.groups["group1"] ) self.assertSetEqual( {self.s.items[self.user2]}, self.s.groups["group2"] ) self.assertSetEqual( {self.s.items[self.user1]}, self.s.groups["group4"] )
def test_query_info_transparent_deduplication_when_cancelled(self): to = structs.JID.fromstr("[email protected]/res1") response = disco_xso.InfoQuery() with unittest.mock.patch.object( self.s, "send_and_decode_info_query", new=CoroutineMock()) as send_and_decode: response = {} send_and_decode.return_value = response send_and_decode.delay = 0.1 q1 = asyncio.async(self.s.query_info(to)) q2 = asyncio.async(self.s.query_info(to)) run_coroutine(asyncio.sleep(0.05)) q1.cancel() result = run_coroutine(q2) self.assertIs(result, response) self.assertSequenceEqual( [ unittest.mock.call(to, None), unittest.mock.call(to, None), ], send_and_decode.mock_calls )
def test_on_entry_removed(self): request = roster_xso.Query( items=[ roster_xso.Item( jid=self.user1, subscription="remove", ), ], ver="foobar" ) iq = stanza.IQ(type_=structs.IQType.SET) iq.payload = request old_item = self.s.items[self.user1] cb = unittest.mock.Mock() with self.s.on_entry_removed.context_connect(cb): run_coroutine(self.s.handle_roster_push(iq)) run_coroutine(self.s.handle_roster_push(iq)) self.assertSequenceEqual( [ unittest.mock.call(old_item), ], cb.mock_calls )
def test_on_entry_removed_called_from_initial_roster(self): response = roster_xso.Query( items=[ roster_xso.Item( jid=self.user2, name="some bar user", subscription="both" ) ], ver="foobar" ) old_item = self.s.items[self.user1] self.cc.stream.send_iq_and_wait_for_reply.return_value = response cb = unittest.mock.Mock() with self.s.on_entry_removed.context_connect(cb): run_coroutine(self.cc.before_stream_established()) self.assertSequenceEqual( [ unittest.mock.call(old_item), ], cb.mock_calls )
def test_exception(self): @asyncio.coroutine def test(): raise ValueError() with self.assertRaises(ValueError): run_coroutine(test())
def test_timeout(self): @asyncio.coroutine def test(): yield from asyncio.sleep(1) with self.assertRaises(asyncio.TimeoutError): run_coroutine(test(), timeout=0.01)
def test_re_raise_NoNameservers_on_validation_query(self): self.tlr.define_actions([ ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD), ), dns.resolver.NoNameservers(), ), ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD | dns.flags.CD), ), dns.resolver.NoNameservers() ), ]) with self.tlr: with self.assertRaises(dns.resolver.NoNameservers): run_coroutine(network.repeated_query( "äöü.example.com".encode("idna"), dns.rdatatype.A, ))
def test_treat_NXDOMAIN_as_succeeded_query_in_validation_query(self): self.tlr.define_actions([ ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD), ), dns.resolver.NoNameservers(), ), ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD | dns.flags.CD), ), dns.resolver.NXDOMAIN(), ), ]) with self.tlr: with self.assertRaisesRegex( network.ValidationError, "nameserver error, most likely DNSSEC validation failed"): run_coroutine(network.repeated_query( "äöü.example.com".encode("idna"), dns.rdatatype.A, require_ad=True, ))
def test_connect_spawn_emits_always(self): signal = AdHocSignal() mock = CoroutineMock() @asyncio.coroutine def coro(*args, **kwargs): yield from mock(*args, **kwargs) signal.connect(coro, AdHocSignal.SPAWN_WITH_LOOP(None)) signal.fire("a", 1, b="c") signal.fire("x") self.assertSequenceEqual(mock.mock_calls, []) run_coroutine(asyncio.sleep(0)) run_coroutine(asyncio.sleep(0)) self.assertSequenceEqual( mock.mock_calls, [ unittest.mock.call("a", 1, b="c"), unittest.mock.call("x"), ] )
def test_ibr_cancel_registration(self): self.cc.local_jid = TEST_PEER run_coroutine(self.s.cancel_registration()) self.cc.send.assert_called_once_with(unittest.mock.ANY) _, (iq, ), _ = self.cc.send.mock_calls[0] self.assertIsInstance( iq, aioxmpp.IQ, ) self.assertEqual( iq.to, TEST_PEER.bare().replace(localpart=None), ) self.assertEqual( iq.type_, aioxmpp.IQType.SET, ) self.assertIsInstance( iq.payload, ibr_xso.Query, ) self.assertEqual( iq.payload.remove, True, )
def test__check_for_feature_raises_if_feature_not_present(self): info = unittest.mock.Mock() info.features = set() with contextlib.ExitStack() as stack: query_info = stack.enter_context(unittest.mock.patch.object( self.disco_client, "query_info", new=CoroutineMock(), )) query_info.return_value = info with self.assertRaisesRegex( RuntimeError, r"Message Carbons \({}\) are not supported by " "the server".format( namespaces.xep0280_carbons_2 )): run_coroutine( self.s._check_for_feature() ) query_info.assert_called_once_with( self.cc.local_jid.replace( localpart=None, resource=None ) )
def test_initial_roster_discards_information(self): self.cc.mock_calls.clear() response = roster_xso.Query( items=[ roster_xso.Item( jid=self.user2, name="some bar user", subscription="both" ) ], ver="foobar" ) self.cc.stream.send_iq_and_wait_for_reply.return_value = response run_coroutine(self.cc.before_stream_established()) self.assertSequenceEqual( [ unittest.mock.call.stream.send_iq_and_wait_for_reply( unittest.mock.ANY, timeout=self.cc.negotiation_timeout.total_seconds() ) ], self.cc.mock_calls ) self.assertNotIn(self.user1, self.s.items)
def test_close(self): closing_handler = unittest.mock.Mock() fut = self.xmlstream.error_future() obj = self.Cls() self.xmlstream.on_closing.connect(closing_handler) def handler(obj): self.xmlstream.close() self.xmlstream.stanza_parser.add_class(self.Cls, handler) run_coroutine(self.xmlstream.run_test( [ XMLStreamMock.Close(), ], stimulus=XMLStreamMock.Receive(obj) )) self.assertSequenceEqual( [ unittest.mock.call(None), ], closing_handler.mock_calls ) self.assertTrue(fut.done()) self.assertIsInstance( fut.exception(), ConnectionError )
def test_on_entry_subscription_state_changed(self): request = roster_xso.Query( items=[ roster_xso.Item( jid=self.user1, subscription="both", approved=True, ask="subscribe" ), ], ver="foobar" ) iq = stanza.IQ(type_=structs.IQType.SET) iq.payload = request cb = unittest.mock.Mock() with self.s.on_entry_subscription_state_changed.context_connect(cb): run_coroutine(self.s.handle_roster_push(iq)) run_coroutine(self.s.handle_roster_push(iq)) self.assertSequenceEqual( [ unittest.mock.call(self.s.items[self.user1]), ], cb.mock_calls )
def test_starttls_reject_incorrect_arguments(self): ssl_context = unittest.mock.MagicMock() post_handshake_callback = unittest.mock.MagicMock() self.xmlstream.transport = object() with self.assertRaisesRegex(AssertionError, "mismatched starttls argument"): run_coroutine( asyncio.gather( self.xmlstream.starttls(object(), post_handshake_callback), self.xmlstream.run_test( [ XMLStreamMock.STARTTLS( ssl_context, post_handshake_callback) ], ) ) ) with self.assertRaisesRegex(AssertionError, "mismatched starttls argument"): run_coroutine( asyncio.gather( self.xmlstream.starttls(ssl_context, object()), self.xmlstream.run_test( [ XMLStreamMock.STARTTLS( ssl_context, post_handshake_callback) ], ) ) )
def test_on_entry_added(self): new_jid = structs.JID.fromstr("*****@*****.**") request = roster_xso.Query( items=[ roster_xso.Item( jid=new_jid, subscription="none", ), ], ver="foobar" ) iq = stanza.IQ(type_=structs.IQType.SET) iq.payload = request cb = unittest.mock.Mock() with self.s.on_entry_added.context_connect(cb): run_coroutine(self.s.handle_roster_push(iq)) run_coroutine(self.s.handle_roster_push(iq)) self.assertSequenceEqual( [ unittest.mock.call(self.s.items[new_jid]), ], cb.mock_calls )
def test_initial_roster_does_not_emit_entry_added_for_existing(self): old_item = self.s.items[self.user2] response = roster_xso.Query( items=[ roster_xso.Item( jid=self.user2, name="new name", subscription="both" ), roster_xso.Item( jid=self.user2.replace(localpart="user2"), name="other name", ) ], ver="foobar" ) mock = unittest.mock.Mock() mock.return_value = False self.s.on_entry_added.connect(mock) self.cc.send.return_value = response run_coroutine(self.cc.before_stream_established()) self.assertSequenceEqual( [ unittest.mock.call( self.s.items[self.user2.replace(localpart="user2")] ), ], mock.mock_calls )
def test_process_none_response_to_versioned_request(self): self.cc.stream_features[...] = roster_xso.RosterVersioningFeature() self.cc.stream.send_iq_and_wait_for_reply.return_value = None cb = unittest.mock.Mock() cb.return_value = True self.s.on_initial_roster_received.connect(cb) run_coroutine(self.cc.before_stream_established()) call, = self.cc.stream.send_iq_and_wait_for_reply.mock_calls _, call_args, call_kwargs = call iq_request, = call_args self.assertEqual( "foobar", iq_request.payload.ver ) self.assertIn(self.user1, self.s.items) self.assertIn(self.user2, self.s.items) self.assertSequenceEqual( [ unittest.mock.call(), ], cb.mock_calls )
def test_initial_roster_removes_contact_from_groups(self): response = roster_xso.Query( items=[ roster_xso.Item( jid=self.user2, name="some bar user", subscription="both", groups=[ roster_xso.Group(name="group1"), roster_xso.Group(name="group2"), ] ) ], ver="foobar" ) self.cc.send.return_value = response run_coroutine(self.cc.before_stream_established()) self.assertSetEqual( self.s.groups["group1"], {self.s.items[self.user2]}, ) self.assertSetEqual( self.s.groups["group2"], {self.s.items[self.user2]}, ) self.assertSetEqual( self.s.groups.get("group3", set()), set(), )
def test_retry_up_to_2_times_with_fixed_resolver(self): resolver = MockResolver(self) resolver.define_actions([ ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD), ), dns.resolver.Timeout() ), ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, True, (dns.flags.RD | dns.flags.AD), ), dns.resolver.Timeout() ), ]) with resolver: with self.assertRaises(TimeoutError): run_coroutine(network.repeated_query( "äöü.example.com".encode("idna"), dns.rdatatype.A, resolver=resolver, )) self.assertSequenceEqual(self.base.mock_calls, [])
def test_initial_roster_fires_group_removed_event_for_changed_contact(self): # NOQA response = roster_xso.Query( items=[ roster_xso.Item( jid=self.user2, name="some bar user", subscription="both", groups=[ roster_xso.Group(name="group1"), roster_xso.Group(name="group2"), ] ), roster_xso.Item( jid=self.user1, name="some foo user", subscription="both", groups={roster_xso.Group(name="group1")} ) ], ver="foobar" ) self.cc.send.return_value = response run_coroutine(self.cc.before_stream_established()) self.assertCountEqual( self.listener.on_group_removed.mock_calls, [ unittest.mock.call("group3"), ] )
def test_query_info_cache_clears_on_disconnect(self): to = structs.JID.fromstr("[email protected]/res1") with unittest.mock.patch.object( self.s, "send_and_decode_info_query", new=CoroutineMock()) as send_and_decode: response1 = {} send_and_decode.return_value = response1 result1 = run_coroutine( self.s.query_info(to, node="foobar") ) self.cc.on_stream_destroyed() response2 = {} send_and_decode.return_value = response2 result2 = run_coroutine( self.s.query_info(to, node="foobar") ) self.assertIs(result1, response1) self.assertIs(result2, response2) self.assertEqual( 2, len(send_and_decode.mock_calls) )
def setUp(self): self.cc = make_connected_client() self.s = roster_service.Service(self.cc) self.user1 = structs.JID.fromstr("*****@*****.**") self.user2 = structs.JID.fromstr("*****@*****.**") response = roster_xso.Query( items=[ roster_xso.Item( jid=self.user1, groups=[ roster_xso.Group(name="group1"), roster_xso.Group(name="group3"), ] ), roster_xso.Item( jid=self.user2, name="some bar user", subscription="both", groups=[ roster_xso.Group(name="group1"), roster_xso.Group(name="group2"), ] ) ], ver="foobar" ) self.cc.stream.send_iq_and_wait_for_reply.return_value = response run_coroutine(self.cc.before_stream_established()) self.cc.stream.send_iq_and_wait_for_reply.reset_mock()
def test_query_info_reraises_and_aliases_exception(self): to = structs.JID.fromstr("[email protected]/res1") ncall = 0 @asyncio.coroutine def mock(*args, **kwargs): nonlocal ncall ncall += 1 if ncall == 1: raise errors.XMPPCancelError( condition=(namespaces.stanzas, "feature-not-implemented"), ) else: raise ConnectionError() with unittest.mock.patch.object( self.s, "send_and_decode_info_query", new=mock): task1 = asyncio.async( self.s.query_info(to, node="foobar") ) task2 = asyncio.async( self.s.query_info(to, node="foobar") ) with self.assertRaises(errors.XMPPCancelError): run_coroutine(task1) with self.assertRaises(errors.XMPPCancelError): run_coroutine(task2)
def test_shutdown(self): self.cc.mock_calls.clear() run_coroutine(self.s.shutdown()) self.assertSequenceEqual( [ unittest.mock.call.stream.unregister_presence_callback( structs.PresenceType.UNSUBSCRIBE, None ), unittest.mock.call.stream.unregister_presence_callback( structs.PresenceType.UNSUBSCRIBED, None ), unittest.mock.call.stream.unregister_presence_callback( structs.PresenceType.SUBSCRIBED, None ), unittest.mock.call.stream.unregister_presence_callback( structs.PresenceType.SUBSCRIBE, None ), unittest.mock.call.stream.unregister_iq_request_coro( structs.IQType.SET, roster_xso.Query ), ], self.cc.mock_calls )
def test_query_items_transparent_deduplication_when_cancelled(self): to = structs.JID.fromstr("[email protected]/res1") response = disco_xso.ItemsQuery() self.cc.stream.send_iq_and_wait_for_reply.return_value = response self.cc.stream.send_iq_and_wait_for_reply.delay = 0.1 q1 = asyncio.async(self.s.query_items(to)) q2 = asyncio.async(self.s.query_items(to)) run_coroutine(asyncio.sleep(0.05)) q1.cancel() result = run_coroutine(q2) self.assertIs(result, response) self.assertSequenceEqual( [ unittest.mock.call(unittest.mock.ANY), unittest.mock.call(unittest.mock.ANY), ], self.cc.stream.send_iq_and_wait_for_reply.mock_calls )
def test_ping_sends_ping(self): self.cc.send.return_value = ping_xso.Ping() run_coroutine(self.s.ping(TEST_PEER)) self.cc.send.assert_called_once_with(unittest.mock.ANY) _, (iq, ), _ = self.cc.send.mock_calls[0] self.assertIsInstance( iq, aioxmpp.IQ, ) self.assertEqual( iq.to, TEST_PEER, ) self.assertEqual( iq.type_, aioxmpp.IQType.GET, ) self.assertIsInstance( iq.payload, ping_xso.Ping, )
def test_iq_errors_are_not_replied_to(self): import aioxmpp.protocol import aioxmpp.stream version = (1, 0) fut = asyncio.Future() p = aioxmpp.protocol.XMLStream(to=TEST_PEER, sorted_attributes=True, features_future=fut) t = TransportMock(self, p) s = aioxmpp.stream.StanzaStream(TEST_FROM.bare()) run_coroutine( t.run_test([ TransportMock.Write( STREAM_HEADER, response=[ TransportMock.Receive( PEER_STREAM_HEADER_TEMPLATE.format( minor=version[1], major=version[0]).encode("utf-8")), ]), ], partial=True)) self.assertEqual(p.state, aioxmpp.protocol.State.OPEN) s.start(p) run_coroutine( t.run_test( [], stimulus=[ TransportMock.Receive(b'<iq type="error" id="foo">' b'<payload xmlns="fnord"/>' b'</iq>') ], partial=True, )) s.flush_incoming() run_coroutine(asyncio.sleep(0)) run_coroutine(t.run_test([], )) s.stop()
def test_proceed_rejects_disallowed_action(self): initial_response = unittest.mock.Mock() initial_response.payload = [ unittest.mock.sentinel.payload1, unittest.mock.sentinel.payload2, ] initial_response.actions.allowed_actions = set() self.send_iq_and_wait_for_reply.return_value = initial_response self.send_iq_and_wait_for_reply.side_effect = None run_coroutine(self.session.start()) self.send_iq_and_wait_for_reply.mock_calls.clear() with self.assertRaisesRegex( ValueError, r"action .*NEXT not allowed in this stage"): run_coroutine(self.session.proceed( action=adhoc_xso.ActionType.NEXT )) self.assertSequenceEqual( self.send_iq_and_wait_for_reply.mock_calls, [] )
def test_query_items_cache_clears_on_disconnect(self): to = structs.JID.fromstr("[email protected]/res1") response1 = disco_xso.ItemsQuery() self.cc.stream.send_iq_and_wait_for_reply.return_value = response1 with self.assertRaises(TypeError): self.s.query_items(to, "foobar") result1 = run_coroutine(self.s.query_items(to, node="foobar")) self.cc.on_stream_destroyed() response2 = disco_xso.ItemsQuery() self.cc.stream.send_iq_and_wait_for_reply.return_value = response2 result2 = run_coroutine(self.s.query_items(to, node="foobar")) self.assertIs(result1, response1) self.assertIs(result2, response2) self.assertEqual( 2, len(self.cc.stream.send_iq_and_wait_for_reply.mock_calls))
def test_return_None_on_nxdomain(self): self.base.repeated_query.return_value = None self.assertIsNone( run_coroutine(network.lookup_srv( b"foo.test", "xmpp-client", )), ) self.base.repeated_query.assert_called_with( b"_xmpp-client._tcp.foo.test", dns.rdatatype.SRV, )
def test__check_for_feature_uses_disco(self): info = unittest.mock.Mock() info.features = {namespaces.xep0280_carbons_2} with contextlib.ExitStack() as stack: query_info = stack.enter_context(unittest.mock.patch.object( self.disco_client, "query_info", new=CoroutineMock(), )) query_info.return_value = info run_coroutine( self.s._check_for_feature() ) query_info.assert_called_once_with( self.cc.local_jid.replace( localpart=None, resource=None ) )
def test_fetch_avatar_returns_None_if__get_image_bytes_returns_None(self): with contextlib.ExitStack() as stack: _get_image_bytes = stack.enter_context( unittest.mock.patch.object(self.ap, "_get_image_bytes", new=CoroutineMock())) _get_image_bytes.return_value = None self.assertIsNone( run_coroutine( self.ap.fetch_avatar(unittest.mock.sentinel.address, ))) _get_image_bytes.assert_called_once_with( unittest.mock.sentinel.address)
def test_handle_unblock_push_all(self): handle_block = unittest.mock.Mock() handle_unblock = unittest.mock.Mock() self.s.on_jids_blocked.connect(handle_block) self.s.on_jids_unblocked.connect(handle_unblock) self.s._blocklist = frozenset([TEST_JID1, TEST_JID2]) block = blocking_xso.UnblockCommand() iq = aioxmpp.IQ( type_=aioxmpp.IQType.SET, payload=block, ) run_coroutine(self.s.handle_unblock_push(iq)) self.assertEqual( handle_unblock.mock_calls, [unittest.mock.call(frozenset([TEST_JID1, TEST_JID2]))]) handle_block.assert_not_called()
def test_detect_absence_of_support_using_disco(self): response = aioxmpp.disco.xso.InfoQuery( features=set() ) self.disco_service.query_info.side_effect = None self.disco_service.query_info.return_value = response self.assertFalse( run_coroutine(self.c.supports_commands(TEST_PEER_JID)), ) self.disco_service.query_info.assert_called_with( TEST_PEER_JID, )
def test_connect_spawn_emits_always(self): signal = AdHocSignal() mock = CoroutineMock() @asyncio.coroutine def coro(*args, **kwargs): yield from mock(*args, **kwargs) signal.connect(coro, AdHocSignal.SPAWN_WITH_LOOP(None)) signal.fire("a", 1, b="c") signal.fire("x") self.assertSequenceEqual(mock.mock_calls, []) run_coroutine(asyncio.sleep(0)) run_coroutine(asyncio.sleep(0)) self.assertSequenceEqual(mock.mock_calls, [ unittest.mock.call("a", 1, b="c"), unittest.mock.call("x"), ])
def test_return_None_on_nxdomain(self): self.base.repeated_query.return_value = None self.assertIsNone( run_coroutine(network.lookup_tlsa( b"foo.test", 5222, )), ) self.base.repeated_query.assert_called_with( b"_5222._tcp.foo.test", dns.rdatatype.TLSA, require_ad=True, )
def test_query_info_cache_clears_on_disconnect(self): to = structs.JID.fromstr("[email protected]/res1") with unittest.mock.patch.object( self.s, "send_and_decode_info_query", new=CoroutineMock()) as send_and_decode: response1 = {} send_and_decode.return_value = response1 result1 = run_coroutine(self.s.query_info(to, node="foobar")) self.cc.on_stream_destroyed() response2 = {} send_and_decode.return_value = response2 result2 = run_coroutine(self.s.query_info(to, node="foobar")) self.assertIs(result1, response1) self.assertIs(result2, response2) self.assertEqual(2, len(send_and_decode.mock_calls))
def test_mount_node_produces_response(self): node = disco_service.StaticNode() node.register_identity("hierarchy", "leaf") self.s.mount_node("foo", node) self.request_iq.payload.node = "foo" response = run_coroutine(self.s.handle_info_request(self.request_iq)) self.assertSetEqual({ ("hierarchy", "leaf", None, None), }, set((item.category, item.type_, item.name, item.lang) for item in response.identities))
def test_send(self): arguments = [] @asyncio.coroutine def patched_send(stanza): fut.set_result(None) arguments.append(stanza) for i in range(5): fut = asyncio.Future() self.cc.send = patched_send self.handle.write(b"some data") run_coroutine(fut) total_content = b"" for i, iq in enumerate(arguments): self.assertEqual(iq.to, TEST_JID1) self.assertIsInstance(iq.payload, ibb_xso.Data) self.assertEqual(iq.payload.sid, self.handle.get_extra_info("sid")) self.assertEqual(iq.payload.seq, i) self.assertTrue(iq.payload.content) total_content += iq.payload.content self.assertEqual(total_content, b"some data" * 5)
def test__get_bookmarks(self): with unittest.mock.patch.object( self.private_xml, "get_private_xml", new=CoroutineMock()) as get_private_xml_mock: get_private_xml_mock.return_value.registered_payload.bookmarks = \ unittest.mock.sentinel.result res = run_coroutine(self.s._get_bookmarks()) self.assertIs(res, unittest.mock.sentinel.result) self.assertEqual(len(get_private_xml_mock.mock_calls), 1) (_, (arg, ), kwargs), = get_private_xml_mock.mock_calls self.assertEqual(len(kwargs), 0) self.assertIsInstance(arg, aioxmpp.bookmarks.Storage) self.assertEqual(len(arg.bookmarks), 0)
def test_reconfigure_resolver_after_first_timeout(self): def reconfigure(): self.tlr.set_flags(None) self.tlr.define_actions([ ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD), ), self.answer, ) ]) self.base.reconfigure_resolver.side_effect = reconfigure self.tlr.define_actions([ ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD), ), dns.resolver.Timeout(), ) ]) with self.tlr: result = run_coroutine(network.repeated_query( "äöü.example.com".encode("idna"), dns.rdatatype.A, )) self.assertSequenceEqual( self.base.mock_calls, [ unittest.mock.call.get_resolver(), unittest.mock.call.reconfigure_resolver(), unittest.mock.call.get_resolver(), ] ) self.assertIs( result, self.answer, )
def test_set_info_cache(self): to = structs.JID.fromstr("[email protected]/res1") response = disco_xso.ItemsQuery() self.s.set_info_cache(to, None, response) other_response = disco_xso.InfoQuery() self.cc.stream.send_iq_and_wait_for_reply.return_value = \ other_response result = run_coroutine(self.s.query_info(to, node=None)) self.assertIs(result, response) self.assertFalse(self.cc.stream.mock_calls)
def test_marker_append(self): self.page.channel.on_message.emit( { "timestamp": datetime(2018, 3, 8, 11, 16, 10).isoformat() + "Z", "from_self": False, "from_jid": "*****@*****.**", "display_name": "Romeo Montague", "color_full": "#123456", "color_weak": "#123", "attachments": [], "body": "<em>foo</em>", "message_uid": "message-1" } ) self.page.channel.on_marker.emit( { "timestamp": datetime(2018, 3, 8, 11, 16, 15).isoformat() + "Z", "from_self": False, "from_jid": "*****@*****.**", "display_name": "Juliet Capulet", "color_full": "#123456", "color_weak": "#123", "marked_message_uid": "message-1" } ) self.assertSubtreeEqual( etree.fromstring( '<div xmlns="http://www.w3.org/1999/xhtml" id="messages">' '<div class="message-block">' '<div class="avatar"><img/></div>' '<div class="from">Romeo Montague</div>' '<div class="message-block-messages">' '<div class="message">' '<div class="timestamp">3/8/2018, 11:16:10 AM</div>' '<div class="content"><div class="payload">' '<div class="body"><em>foo</em></div>' '<div/></div></div>' '</div>' '</div>' '<div class="clearfix"></div>' '</div>' '<div class="marker">' '<img/>' '<span>Juliet Capulet has read up to here.</span>' '</div>' '</div>' ), run_coroutine(self._obtain_html(), timeout=20), ignore_surplus_attr=True, )
def test_discard_bookmark_set_raises(self): bookmark = aioxmpp.bookmarks.URL("An URL", "http://foo.bar/") run_coroutine(self.s.add_bookmark(bookmark)) class TokenException(Exception): pass def set_bookmarks(*args, **kwargs): raise TokenException with contextlib.ExitStack() as e: e.enter_context(self.assertRaises(TokenException)) diff_emit_update = e.enter_context( unittest.mock.patch.object(self.s, "_diff_emit_update",) ) e.enter_context( unittest.mock.patch.object(self.s, "_set_bookmarks", set_bookmarks) ) run_coroutine(self.s.discard_bookmark(bookmark)) # check that _diff_emit_update is called self.assertEqual(len(diff_emit_update.mock_calls), 1)
def test_handle_roster_push_removes_from_roster(self): request = roster_xso.Query(items=[ roster_xso.Item(jid=self.user1, subscription="remove"), ], ver="foobarbaz") iq = stanza.IQ(type_=structs.IQType.SET) iq.payload = request self.assertIsNone(run_coroutine(self.s.handle_roster_push(iq))) self.assertNotIn(self.user1, self.s.items) self.assertIn(self.user2, self.s.items) self.assertEqual("foobarbaz", self.s.version)
def test_disable_avatar(self): # set the cache to indicate the server has PEP self.s._has_pep = True with unittest.mock.patch.object(self.pubsub, "publish", new=CoroutineMock()): run_coroutine(self.s.disable_avatar()) self.assertSequenceEqual(self.pubsub.publish.mock_calls, [ unittest.mock.call( None, namespaces.xep0084_metadata, unittest.mock.ANY, ), ]) _, args, _ = self.pubsub.publish.mock_calls[0] metadata = args[2] self.assertTrue(isinstance(metadata, avatar_xso.Metadata)) self.assertEqual(0, len(metadata.info)) self.assertEqual(0, len(metadata.pointer))
def test_ping_propagates_cancel_to_send(self): fut = asyncio.Future() # no CoroutineMock here, we fake the coroutine using a future self.cc.send = unittest.mock.Mock() self.cc.send.return_value = fut task = asyncio.ensure_future(ping_service.ping( self.cc, TEST_PEER, )) run_coroutine(asyncio.sleep(0)) self.cc.send.assert_called_once_with(unittest.mock.ANY) self.assertFalse(task.done()) task.cancel() with self.assertRaises(asyncio.CancelledError): run_coroutine(task) self.assertTrue(fut.cancelled())
def test_raise_ValueError_if_AD_not_present_with_require_ad(self): self.tlr.define_actions([ ( ( "xn--4ca0bs.example.com", dns.rdatatype.A, dns.rdataclass.IN, False, (dns.flags.RD | dns.flags.AD), ), self.answer, ) ]) with self.tlr: with self.assertRaisesRegex( ValueError, "DNSSEC validation not available"): run_coroutine(network.repeated_query( "äöü.example.com".encode("idna"), dns.rdatatype.A, require_ad=True, ))
def test_pinger_cancels_after_ping_timeout(self): interval = get_timeout(0.1) timeout = get_timeout(0.4) futures = [] def ping_func(*args, **kwargs): fut = asyncio.Future() futures.append(fut) return fut self.p.ping_interval = timedelta(seconds=interval) self.p.ping_timeout = timedelta(seconds=timeout) with contextlib.ExitStack() as stack: ping = stack.enter_context( unittest.mock.patch( "aioxmpp.ping.ping", new=unittest.mock.Mock(side_effect=ping_func, ), )) self.p.start() run_coroutine(asyncio.sleep(interval / 2)) # we check that, at any time, at most four futures # (timeout/interval) are not cancelled for i in range(10): self._require_task_running() ping.assert_called_once_with( self.cc, unittest.mock.sentinel.ping_address) ping.reset_mock() self.assertLessEqual( sum(not fut.done() for fut in futures), 4, ) run_coroutine(asyncio.sleep(interval))
def setUp(self): self.cc = make_connected_client() self.presence_dispatcher = aioxmpp.dispatcher.SimplePresenceDispatcher( self.cc) self.dependencies = { aioxmpp.dispatcher.SimplePresenceDispatcher: self.presence_dispatcher, } self.s = roster_service.RosterClient(self.cc, dependencies=self.dependencies) self.user1 = structs.JID.fromstr("*****@*****.**") self.user2 = structs.JID.fromstr("*****@*****.**") response = roster_xso.Query(items=[ roster_xso.Item(jid=self.user1, groups=[ roster_xso.Group(name="group1"), roster_xso.Group(name="group3"), ]), roster_xso.Item(jid=self.user2, name="some bar user", subscription="both", groups=[ roster_xso.Group(name="group1"), roster_xso.Group(name="group2"), ]) ], ver="foobar") self.cc.send.return_value = response run_coroutine(self.cc.before_stream_established()) self.cc.send.reset_mock() self.listener = make_listener(self.s)
def test_disable_avatar_synchronize_vcard_pep_raises(self): self.s.synchronize_vcard = True with contextlib.ExitStack() as e: e.enter_context(unittest.mock.patch.object(self.pep, "publish", new=CoroutineMock())) e.enter_context(unittest.mock.patch.object(self.presence_server, "resend_presence")) e.enter_context(unittest.mock.patch.object(self.vcard, "get_vcard", new=CoroutineMock())) e.enter_context(unittest.mock.patch.object(self.vcard, "set_vcard", new=CoroutineMock())) # do not do the vcard operations of pep is available but # fails self.pep.publish.side_effect = RuntimeError self.vcard.get_vcard.return_value = unittest.mock.Mock() with self.assertRaises(RuntimeError): run_coroutine(self.s.disable_avatar()) self.assertSequenceEqual( self.presence_server.resend_presence.mock_calls, [unittest.mock.call()] ) self.assertSequenceEqual( self.vcard.get_vcard.mock_calls, [unittest.mock.call(), unittest.mock.call().clear_photo_data()] ) self.assertSequenceEqual( self.vcard.set_vcard.mock_calls, [unittest.mock.call(unittest.mock.ANY)] )
def test_pinger_picks_up_on_timeout_change(self): interval = get_timeout(0.3) timeout = get_timeout(0.3) futures = [] def ping_func(*args, **kwargs): fut = asyncio.Future() futures.append(fut) return fut self.p.ping_interval = timedelta(seconds=interval) self.p.ping_timeout = timedelta(seconds=interval * 10) with contextlib.ExitStack() as stack: ping = stack.enter_context( unittest.mock.patch( "aioxmpp.ping.ping", new=unittest.mock.Mock(side_effect=ping_func, ), )) self.p.start() run_coroutine(asyncio.sleep(interval / 2)) self._require_task_running() ping.assert_called_once_with(self.cc, unittest.mock.sentinel.ping_address) ping.reset_mock() self.p.ping_timeout = timedelta(seconds=timeout) run_coroutine(asyncio.sleep(interval)) self._require_task_running() self.assertEqual(len(futures), 2) run_coroutine(asyncio.sleep(interval)) self._require_task_running() self.assertEqual(len(futures), 3) run_coroutine(asyncio.sleep(interval / 2)) self.assertFalse(futures[0].done()) self.assertTrue(futures[1].done()) self.assertTrue(futures[2].done())
def test_flag_message_as_error_with_message(self): self.page.channel.on_message.emit( { "timestamp": datetime(2018, 3, 8, 11, 16, 10).isoformat() + "Z", "from_self": False, "from_jid": "*****@*****.**", "display_name": "Romeo Montague", "color_full": "#123456", "color_weak": "#123", "attachments": [], "body": "<em>test</em>", "message_uid": "message-1" } ) self.page.channel.on_flag.emit( { "flagged_message_uid": "message-1", "flag": "ERROR", "message": "frobnitzed the bar" } ) self.assertSubtreeEqual( etree.fromstring( '<div xmlns="http://www.w3.org/1999/xhtml" id="messages">' '<div class="message-block">' '<div class="avatar"><img/></div>' '<div class="from">Romeo Montague</div>' '<div class="message-block-messages">' '<div class="message failed">' '<div class="timestamp">3/8/2018, 11:16:10 AM</div>' '<div class="content">' '<div class="payload">' '<div class="body"><em>test</em></div>' '<div class="flag">' '<img alt="(error)" title="failed to deliver: ' 'frobnitzed the bar" ' 'src="qrc:/icons/scalable/state-error.svg"/>' '</div>' '</div>' '</div>' '</div>' '</div>' '<div class="clearfix"></div>' '</div>' '</div>' ), run_coroutine(self._obtain_html(), timeout=20), ignore_surplus_attr=True, )
def test_process_none_response_to_versioned_request(self): self.cc.stream_features[...] = roster_xso.RosterVersioningFeature() self.cc.send.return_value = None cb = unittest.mock.Mock() cb.return_value = True self.s.on_initial_roster_received.connect(cb) run_coroutine(self.cc.before_stream_established()) call, = self.cc.send.mock_calls _, call_args, call_kwargs = call iq_request, = call_args self.assertEqual("foobar", iq_request.payload.ver) self.assertIn(self.user1, self.s.items) self.assertIn(self.user2, self.s.items) self.assertSequenceEqual([ unittest.mock.call(), ], cb.mock_calls)
def test_groups_are_cleaned_up_up_when_on_entry_removed_fires_on_push( self): fut = asyncio.Future() def handler(item): try: for group in item.groups: try: members = self.s.groups[group] except KeyError: members = set() self.assertNotIn(item, members) except Exception as exc: fut.set_exception(exc) else: fut.set_result(None) new_jid = structs.JID.fromstr("*****@*****.**") request = roster_xso.Query(items=[ roster_xso.Item( jid=self.user2, subscription="remove", ), ], ver="foobar") iq = stanza.IQ(type_=structs.IQType.SET) iq.payload = request self.s.on_entry_removed.connect(handler) run_coroutine(self.s.handle_roster_push(iq)) run_coroutine(fut)
def test_groups_are_set_up_when_on_entry_added_fires(self): fut = asyncio.Future() def handler(item): try: for group in item.groups: self.assertIn(group, self.s.groups) self.assertIn(item, self.s.groups[group]) except Exception as exc: fut.set_exception(exc) else: fut.set_result(None) new_jid = structs.JID.fromstr("*****@*****.**") request = roster_xso.Query(items=[ roster_xso.Item( jid=new_jid, subscription="none", groups={ roster_xso.Group(name="a"), roster_xso.Group(name="group1"), }, ), ], ver="foobar") iq = stanza.IQ(type_=structs.IQType.SET) iq.payload = request self.s.on_entry_added.connect(handler) run_coroutine(self.s.handle_roster_push(iq)) run_coroutine(fut)