diff options
author | David Laban <david.laban@collabora.co.uk> | 2010-12-07 18:09:33 +0000 |
---|---|---|
committer | David Laban <david.laban@collabora.co.uk> | 2011-01-26 17:16:33 +0000 |
commit | 8f241d940ecfcc366ce3dedb5b077d73d379965c (patch) | |
tree | 7cfb65f573d4f79c1df5404a5d8c61874a43581d | |
parent | 744205d25b59848c56902a4fdfd7134d575f8794 (diff) |
Complete outgoing-basics.py
sofiatest.py:
* add sip headers to Events for convenience
voip_test.py:VoipTestContext:
* add {get, check}_call_sdp()
* add accept() (secretly also records call-id)
outgoing_basics.py:
* Call NativeCandidatesPrepared() because RAWUDP requires it.
* Expect sip-* events rather than stream-iq ones.
-rw-r--r-- | tests/twisted/sofiatest.py | 17 | ||||
-rw-r--r-- | tests/twisted/voip/outgoing-basics.py | 61 | ||||
-rw-r--r-- | tests/twisted/voip/voip_test.py | 47 |
3 files changed, 70 insertions, 55 deletions
diff --git a/tests/twisted/sofiatest.py b/tests/twisted/sofiatest.py index f1b1174..a9ae28d 100644 --- a/tests/twisted/sofiatest.py +++ b/tests/twisted/sofiatest.py @@ -33,15 +33,24 @@ class SipProxy(sip.RegisterProxy): def handle_request(self, message, addr): if message.method == 'REGISTER': return sip.RegisterProxy.handle_request(self, message, addr) - if message.method == 'MESSAGE': - self.event_func(servicetest.Event('sip-message', + elif message.method == 'OPTIONS': + # FIXME: work out why sofiasip keeps sending s:REGISTRATION PROBE + return + else: + headers = {} + for key, values in message.headers.items(): + headers[key.replace('-', '_')] = values[0] + self.event_func(servicetest.Event('sip-%s' % message.method.lower(), uri=str(message.uri), headers=message.headers, body=message.body, - sip_message=message)) + sip_message=message, **headers)) def handle_response(self, message, addr): + headers = {} + for key, values in message.headers.items(): + headers[key.replace('-', '_')] = values[0] self.event_func(servicetest.Event('sip-response', code=message.code, headers=message.headers, body=message.body, - sip_message=message)) + sip_message=message, **headers)) def prepare_test(event_func, register_cb, params=None): actual_params = { diff --git a/tests/twisted/voip/outgoing-basics.py b/tests/twisted/voip/outgoing-basics.py index 5e4f9d3..297ecc8 100644 --- a/tests/twisted/voip/outgoing-basics.py +++ b/tests/twisted/voip/outgoing-basics.py @@ -191,6 +191,7 @@ def worker(q, bus, conn, sip_proxy, variant, peer): stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", context.get_remote_transports_dbus()) + stream_handler.NativeCandidatesPrepared() stream_handler.Ready(context.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) @@ -199,43 +200,17 @@ def worker(q, bus, conn, sip_proxy, variant, peer): assertEquals('none', sh_props['NATTraversal']) assertEquals(True, sh_props['CreatedLocally']) - return if variant == CREATE: - # When we actually send XML to the peer, they should pop up in remote + # When we actually send INVITE to the peer, they should pop up in remote # pending. - session_initiate, _ = q.expect_many( - EventPattern('stream-iq', iq_type='set', predicate=lambda e: - jp.match_jingle_action(e.query, 'session-initiate')), + invite_event, _ = q.expect_many( + EventPattern('sip-invite'), EventPattern('dbus-signal', signal='MembersChanged', args=["", [], [], [], [remote_handle], self_handle, cs.GC_REASON_INVITED]), ) else: - forbidden = [] - - if peer.split('/', 1)[0] in ( - 'publish@foo.com', 'publish-subscribe@foo.com'): - forbidden = [EventPattern('stream-presence')] - q.forbid_events(forbidden) - else: - # we're calling someone not on our roster, so we'll send directed - # presence first - presence = q.expect('stream-presence') - assert (xpath.queryForNodes('/presence/c', presence.stanza) - is not None) - assert (xpath.queryForNodes( - '/presence/x[@xmlns="vcard-temp:x:update"]', presence.stanza) - is not None) - - session_initiate = q.expect('stream-iq', - predicate=jp.action_predicate('session-initiate')) - - if forbidden: - q.unforbid_events(forbidden) - - context.parse_session_initiate(session_initiate.query) - sip_proxy.send(jp.xml(jp.ResultIq('sip:testacc@127.0.0.1', session_initiate.stanza, - []))) + invite_event = q.expect('sip-invite') # Check the Group interface's properties again. Regardless of the call # requesting API in use, the state should be the same here: @@ -245,19 +220,12 @@ def worker(q, bus, conn, sip_proxy, variant, peer): assertEquals([], group_props['LocalPendingMembers']) assertEquals([remote_handle], group_props['RemotePendingMembers']) - if jp.dialect == 'gtalk-v0.4': - node = jp.SetIq(context.peer, context.our_uri, [ - jp.Jingle(context.sid, context.peer, 'transport-accept', [ - jp.TransportGoogleP2P() ]) ]) - sip_proxy.send(jp.xml(node)) - - # FIXME: expect transport-info, then if we're gtalk3, send - # candidates, and check that gabble resends transport-info as - # candidates - context.accept() + context.check_call_sdp(invite_event.sip_message.body) + context.accept(invite_event.sip_message) + ack_cseq = "%s ACK" % invite_event.cseq.split()[0] q.expect_many( - EventPattern('stream-iq', iq_type='result'), + EventPattern('sip-ack', cseq=ack_cseq), # Call accepted EventPattern('dbus-signal', signal='MembersChanged', args=['', [remote_handle], [], [], [], remote_handle, @@ -268,20 +236,11 @@ def worker(q, bus, conn, sip_proxy, variant, peer): chan.Group.RemoveMembers([self_handle], 'closed') - # Make sure gabble sends proper terminate action - if jp.dialect.startswith('gtalk'): - terminate = EventPattern('stream-iq', predicate=lambda x: - xpath.queryForNodes("/iq/session[@type='terminate']", - x.stanza)) - else: - terminate = EventPattern('stream-iq', predicate=lambda x: - xpath.queryForNodes("/iq/jingle[@action='session-terminate']", - x.stanza)) mc_event, _, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('dbus-signal', signal='Close'), - terminate, + EventPattern('sip-bye', call_id=context.call_id), ) # Check that we're the actor assertEquals(self_handle, mc_event.args[5]) diff --git a/tests/twisted/voip/voip_test.py b/tests/twisted/voip/voip_test.py index 18239f1..9cfa3ee 100644 --- a/tests/twisted/voip/voip_test.py +++ b/tests/twisted/voip/voip_test.py @@ -1,6 +1,8 @@ import dbus +import twisted.protocols.sip + class VoipTestContext(object): # Default audio codecs for the remote end audio_codecs = [ ('GSM', 3, 8000, {}), @@ -23,6 +25,9 @@ class VoipTestContext(object): "username", "password" ) ] + _mline_template = 'm=audio %(port)s %(subtype)s/%(profile)s %(codec_ids)s' + _aline_template = 'a=rtpmap:%(codec_id)s %(name)s/%(rate)s' + def __init__(self, q, conn, bus, sip_proxy, our_uri, peer): self.bus = bus self.conn = conn @@ -83,3 +88,45 @@ class VoipTestContext(object): pref, transtype, user, pwd) in enumerate(self.remote_transports) ], signature='(usqa{sv})') + + def get_call_sdp(self): + (ip, port, protocol, subtype, profile, preference, + transport, username, password) = self.remote_transports[0] + + codec_id_list = [] + codec_list = [] + for name, codec_id, rate, _misc in self.audio_codecs: + codec_list.append('a=rtpmap:%(codec_id)s %(name)s/%(rate)s' % locals()) + codec_id_list.append(str(codec_id)) + codec_ids = ' '.join(codec_id_list) + codecs = '\r\n'.join(codec_list) + + sdp_string = ('v=0\r\n' + 'o=- 7047265765596858314 2813734028456100815 IN IP4 %(ip)s\r\n' + 's=-\r\n' + 't=0 0\r\n' + 'm=audio %(port)s RTP/AVP 3 8 0\r\n' + 'c=IN IP4 %(ip)s\r\n' + '%(codecs)s\r\n') % locals() + return sdp_string + + def check_call_sdp(self, sdp_string): + codec_id_list = [] + for name, codec_id, rate, _misc in self.audio_codecs: + assert self._aline_template % locals() in sdp_string + codec_id_list.append(str(codec_id)) + codec_ids = ' '.join(codec_id_list) + + (ip, port, protocol, subtype, profile, preference, + transport, username, password) = self.remote_transports[0] + assert self._mline_template % locals() in sdp_string + + def accept(self, invite_message): + self.call_id = invite_message.headers['call-id'][0] + response = self.sip_proxy.responseFromRequest(200, invite_message) + # Echo sofiasip's SDP back to it. It doesn't care. + response.addHeader('content-type', 'application/sdp') + response.body = invite_message.body + response.addHeader('content-length', '%d' % len(response.body)) + self.sip_proxy.deliverResponse(response) + return response |