summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Laban <david.laban@collabora.co.uk>2010-12-07 18:09:33 +0000
committerDavid Laban <david.laban@collabora.co.uk>2011-01-26 17:16:33 +0000
commit8f241d940ecfcc366ce3dedb5b077d73d379965c (patch)
tree7cfb65f573d4f79c1df5404a5d8c61874a43581d
parent744205d25b59848c56902a4fdfd7134d575f8794 (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.py17
-rw-r--r--tests/twisted/voip/outgoing-basics.py61
-rw-r--r--tests/twisted/voip/voip_test.py47
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