summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2012-02-08 11:25:20 +0100
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2012-02-08 11:31:19 +0100
commit2e543e74a65f9cb2da584f35d2348b6b57fabd78 (patch)
tree458b8bca73c3babcef4d01e9406badc46bd3cd46
parentdaa6d7252861dbb9c7951330d413975573d45b89 (diff)
Implement a call version of content-adding-removal
-rw-r--r--tests/twisted/jingle/call-content-adding-removal.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/tests/twisted/jingle/call-content-adding-removal.py b/tests/twisted/jingle/call-content-adding-removal.py
new file mode 100644
index 000000000..ded140dbf
--- /dev/null
+++ b/tests/twisted/jingle/call-content-adding-removal.py
@@ -0,0 +1,141 @@
+"""
+Test content adding and removal during the session. We start
+session with only one stream, then add one more, then remove
+the first one and lastly remove the second stream, which
+closes the session.
+"""
+
+from functools import partial
+from servicetest import call_async, assertEquals, assertLength, EventPattern
+from gabbletest import make_result_iq, sync_stream
+from jingletest2 import test_dialects, JingleProtocol015, JingleProtocol031
+from call_helper import CallTest, run_call_test
+import constants as cs
+import dbus
+
+class CallContentAddingRemovalTest(CallTest):
+
+ # A/V
+ initial_audio = True
+ initial_video = True
+
+ def pickup(self):
+ peer_removes_final_content = self.params['peer-removes-final-content']
+
+ # Remove video content before remote pick the call
+ self.video_content.Remove()
+ e = self.q.expect('dbus-signal', signal='ContentRemoved')
+ assertEquals(e.args[1][0], self.self_handle)
+ assertEquals(e.args[1][1], cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED)
+ assertEquals(e.args[1][2], '')
+
+ self.initial_video = False
+ self.video_content = None
+ self.video_content_name = None
+ self.video_stream = None
+
+ # ...but before the peer notices, they accept the call.
+ CallTest.pickup(self)
+
+ # Gabble sends content-remove for the video stream...
+ e = self.q.expect('stream-iq',
+ predicate=self.jp.action_predicate('content-remove'))
+
+ # Only now the remote end removes the video stream; if gabble mistakenly
+ # marked it as accepted on session acceptance, it'll crash right about
+ # now. If it's good, stream will be really removed, and
+ # we can proceed.
+ self.stream.send(make_result_iq(self.stream, e.stanza))
+
+ # Actually, we *do* want video!
+ content_path = self.chan.AddContent("video1", cs.CALL_MEDIA_TYPE_VIDEO,
+ dbus_interface=cs.CHANNEL_TYPE_CALL);
+ self.q.expect('dbus-signal', signal='ContentAdded')
+
+ self.store_content(content_path, initial=False)
+
+ md = self.jt2.get_call_video_md_dbus()
+ self.check_and_accept_offer(self.video_content, md)
+
+ candidates = self.jt2.get_call_remote_transports_dbus()
+ self.video_stream.AddCandidates(candidates,
+ dbus_interface=cs.CALL_STREAM_IFACE_MEDIA)
+
+ e = self.q.expect('stream-iq',
+ predicate=self.jp.action_predicate('content-add'))
+ c = e.query.firstChildElement()
+ assertEquals('initiator', c['creator'])
+
+ endpoints = self.video_stream.Get(cs.CALL_STREAM_IFACE_MEDIA,
+ "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE)
+ assertLength(1, endpoints)
+
+ endpoint = self.bus.get_object(self.conn.bus_name, endpoints[0])
+ self.enable_endpoint(endpoint)
+
+ # Now, the call draws to a close.
+ # We first remove the original stream
+ self.audio_content.Remove()
+ self.initial_audio = False
+ self.audio_content = None
+ self.audio_content_name = None
+ self.audio_stream = None
+
+ e = self.q.expect('stream-iq',
+ predicate=self.jp.action_predicate('content-remove'))
+ content_remove_ack = make_result_iq(self.stream, e.stanza)
+
+ if peer_removes_final_content:
+ # The peer removes the final countdo content. From a footnote (!) in
+ # XEP 0166:
+ # If the content-remove results in zero content definitions for the
+ # session, the entity that receives the content-remove SHOULD send
+ # a session-terminate action to the other party (since a session
+ # with no content definitions is void).
+ # So, Gabble should respond to the content-remove with a
+ # session-terminate.
+ node = self.jp.SetIq(self.jt2.peer, self.jt2.jid, [
+ self.jp.Jingle(self.jt2.sid, self.jt2.peer, 'content-remove', [
+ self.jp.Content(c['name'], c['creator'], c['senders']) ]) ])
+ self.stream.send(self.jp.xml(node))
+
+ else:
+ # The Telepathy client removes the second stream; Gabble should
+ # terminate the session rather than sending a content-remove.
+ self.video_content.Remove()
+ self.initial_video = False
+ self.video_content = None
+ self.video_content_name = None
+ self.video_stream = None
+
+ st, ended = self.q.expect_many(
+ EventPattern('stream-iq',
+ predicate=self.jp.action_predicate('session-terminate')),
+ # Gabble shouldn't wait for the peer to ack the terminate before
+ # considering the call finished.
+ EventPattern('dbus-signal', signal='CallStateChanged'))
+ assertEquals(ended.args[0], cs.CALL_STATE_ENDED)
+ print ended.args[2]
+
+ # Only now does the peer ack the content-remove. This serves as a
+ # regression test for contents outliving the session; if the content did
+ # did't die properly, this crashed Gabble.
+ self.stream.send(content_remove_ack)
+ sync_stream(self.q, self.stream)
+
+ # The peer can ack the terminate too, just for completeness.
+ self.stream.send(make_result_iq(self.stream, st.stanza))
+
+ def hangup(self):
+ pass
+
+if __name__ == '__main__':
+ dialects = [JingleProtocol015, JingleProtocol031]
+ test_dialects(
+ partial(run_call_test, klass=CallContentAddingRemovalTest,
+ incoming=False, params={'peer-removes-final-content': True}),
+ dialects)
+ test_dialects(
+ partial(run_call_test, klass=CallContentAddingRemovalTest,
+ incoming=False, params={'peer-removes-final-content': False}),
+ dialects)