1 2""" 3Test handling of Error() call on stream handler. 4 5This tests a regression in which MembersChanged was emitted with reason other 6than GC_REASON_ERROR. 7""" 8 9from servicetest import EventPattern, assertEquals, make_channel_proxy 10from jingletest2 import JingleTest2, test_all_dialects 11import constants as cs 12 13from twisted.words.xish import xpath 14 15from config import VOIP_ENABLED 16 17if not VOIP_ENABLED: 18 print "NOTE: built with --disable-voip" 19 raise SystemExit(77) 20 21def _session_terminate_predicate(event, reason, msg, jp): 22 matches = jp.match_jingle_action(event.query, 'session-terminate') 23 24 if matches and jp.is_modern_jingle(): 25 reason = xpath.queryForNodes("/iq" 26 "/jingle[@action='session-terminate']" 27 "/reason/%s" % reason, 28 event.stanza) 29 reason_text = xpath.queryForString("/iq/jingle/reason/text", 30 event.stanza) 31 32 return bool(reason) and reason_text == msg 33 34 return matches 35 36def _test(jp, q, bus, conn, stream, 37 jingle_reason, group_change_reason, stream_error): 38 jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') 39 jt.prepare() 40 self_handle = conn.GetSelfHandle() 41 remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] 42 43 # Ring ring! 44 jt.incoming_call() 45 new_channel, new_session_handler = q.expect_many( 46 EventPattern('dbus-signal', signal='NewChannel', 47 predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), 48 EventPattern('dbus-signal', signal='NewSessionHandler')) 49 assertEquals(cs.CHANNEL_TYPE_STREAMED_MEDIA, new_channel.args[1]) 50 assertEquals(cs.HT_CONTACT, new_channel.args[2]) 51 assertEquals(remote_handle, new_channel.args[3]) 52 assertEquals('rtp', new_session_handler.args[1]) 53 54 channel_path = new_channel.args[0] 55 56 # Client calls Ready on new session handler. 57 session_handler = make_channel_proxy( 58 conn, new_session_handler.args[0], 'Media.SessionHandler') 59 session_handler.Ready() 60 61 # Client gets notified about a newly created stream... 62 new_stream_handler = q.expect('dbus-signal', signal='NewStreamHandler') 63 stream_id = new_stream_handler.args[1] 64 stream_handler = make_channel_proxy( 65 conn, new_stream_handler.args[0], 'Media.StreamHandler') 66 stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) 67 stream_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) 68 69 q.expect('dbus-signal', signal='SetRemoteCodecs') 70 71 msg = u"o noes" 72 73 # ...but something goes wrong. 74 stream_handler.Error(stream_error, msg) 75 76 q.expect("stream-iq", iq_type="set", 77 predicate=lambda x: _session_terminate_predicate(x, jingle_reason, 78 msg, jp)) 79 # Bye bye members. 80 mc = q.expect('dbus-signal', signal='MembersChanged', 81 interface=cs.CHANNEL_IFACE_GROUP, path=channel_path, 82 args=[msg, [], [self_handle, remote_handle], [], 83 [], self_handle, group_change_reason]) 84 85 q.expect('dbus-signal', signal='StreamError', 86 interface=cs.CHANNEL_TYPE_STREAMED_MEDIA, 87 args=[stream_id, stream_error, msg]) 88 89 # Bye bye stream 90 q.expect('dbus-signal', signal='Close') 91 q.expect('dbus-signal', signal='StreamRemoved') 92 93 # Bye bye channel. 94 q.expect('dbus-signal', signal='Closed') 95 q.expect('dbus-signal', signal='ChannelClosed') 96 97def test_connection_error(jp, q, bus, conn, stream): 98 _test(jp, q, bus, conn, stream, "connectivity-error", cs.GC_REASON_ERROR, 99 cs.MEDIA_STREAM_ERROR_NETWORK_ERROR) 100 101def test_codec_negotiation_fail(jp, q, bus, conn, stream): 102 _test(jp, q, bus, conn, stream, "failed-application", cs.GC_REASON_ERROR, 103 cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED) 104 105if __name__ == '__main__': 106 test_all_dialects(test_connection_error) 107 test_all_dialects(test_codec_negotiation_fail) 108