summaryrefslogtreecommitdiff
path: root/tests/end_to_end
diff options
context:
space:
mode:
Diffstat (limited to 'tests/end_to_end')
-rw-r--r--tests/end_to_end/__main__.py370
1 files changed, 241 insertions, 129 deletions
diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py
index 649e073..82321eb 100644
--- a/tests/end_to_end/__main__.py
+++ b/tests/end_to_end/__main__.py
@@ -152,7 +152,7 @@ def check_xpath(xpaths, xmpp, after, stanza):
xpath = xpath[1:]
matched = match(stanza, xpath)
if (expected and not matched) or (not expected and matched):
- raise StanzaError("Received stanza “%s” did not match expected xpath “%s”" % (stanza, real_xpath))
+ raise StanzaError("Received stanza\n%s\ndid not match expected xpath\n%s" % (stanza, real_xpath))
if after:
if isinstance(after, collections.Iterable):
for af in after:
@@ -270,11 +270,13 @@ def send_stanza(stanza, xmpp, biboumi):
def expect_stanza(xpaths, xmpp, biboumi, optional=False, after=None):
+ replacements = common_replacements
+ replacements.update(xmpp.saved_values)
check_func = check_xpath if not optional else check_xpath_optional
if isinstance(xpaths, str):
- xmpp.stanza_checker = partial(check_func, [xpaths.format_map(common_replacements)], xmpp, after)
+ xmpp.stanza_checker = partial(check_func, [xpaths.format_map(replacements)], xmpp, after)
elif isinstance(xpaths, tuple):
- xmpp.stanza_checker = partial(check_func, [xpath.format_map(common_replacements) for xpath in xpaths], xmpp, after)
+ xmpp.stanza_checker = partial(check_func, [xpath.format_map(replacements) for xpath in xpaths], xmpp, after)
else:
print("Warning, from argument type passed to expect_stanza: %s" % (type(xpaths)))
@@ -661,23 +663,6 @@ if __name__ == '__main__':
),
partial(expect_stanza, "/message[@from='#baz%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
]),
- Scenario("virtual_channel",
- [
- handshake_sequence(),
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- connection_middle_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
- connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_one}']"),
- ]),
Scenario("not_connected_error",
[
handshake_sequence(),
@@ -694,40 +679,39 @@ if __name__ == '__main__':
),
partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
]),
- Scenario("irc_server_disconnection",
+ Scenario("channel_join_with_two_users",
[
handshake_sequence(),
+ # First user joins
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- connection_middle_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
+ "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' />"),
+ connection_sequence("irc.localhost", '{jid_one}/{resource_one}'),
partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
+ "/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"),
+ partial(expect_stanza,
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@jid='~nick@localhost'][@role='moderator']",
+ "/presence/muc_user:x/muc_user:status[@code='110']")
),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
- connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
+ partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
+ # Second user joins
+ partial(send_stanza,
+ "<presence from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}/{nick_two}' />"),
+ connection_sequence("irc.localhost", '{jid_two}/{resource_one}'),
partial(expect_unordered, [
- ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='{nick_two}']",
- "/presence/muc_user:x/muc_user:status[@code='110']",
- "/presence/muc_user:x/muc_user:status[@code='303']"),
- ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant'][@jid='~bobby@localhost']",),
+ ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",),
+ ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']/muc_user:x/muc_user:item[@affiliation='none'][@jid='~bobby@localhost'][@role='participant']",
+ "/presence/muc_user:x/muc_user:status[@code='110']",),
+ ("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]",),
]),
-
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
- partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}']"),
]),
- Scenario("channel_join_with_two_users",
+ Scenario("channel_force_join",
[
handshake_sequence(),
# First user joins
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}'><x xmlns='http://jabber.org/protocol/muc'/></presence>"),
connection_sequence("irc.localhost", '{jid_one}/{resource_one}'),
partial(expect_stanza,
"/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"),
@@ -739,7 +723,7 @@ if __name__ == '__main__':
# Second user joins
partial(send_stanza,
- "<presence from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}/{nick_two}' />"),
+ "<presence from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}/{nick_two}'><x xmlns='http://jabber.org/protocol/muc'/></presence>"),
connection_sequence("irc.localhost", '{jid_two}/{resource_one}'),
partial(expect_unordered, [
("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant'][@jid='~bobby@localhost']",),
@@ -748,6 +732,31 @@ if __name__ == '__main__':
"/presence/muc_user:x/muc_user:status[@code='110']",),
("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]",),
]),
+
+ # Here we simulate a desynchronization of a client: The client thinks it’s
+ # disconnected from the room, but biboumi still thinks it’s in the room. The
+ # client thus sends a join presence, and biboumi should send everything
+ # (user list, history, etc) in response.
+ partial(send_stanza,
+ "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_three}'><x xmlns='http://jabber.org/protocol/muc'/></presence>"),
+
+ partial(expect_unordered, [
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant'][@jid='~bobby@localhost']",),
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
+ "/presence/muc_user:x/muc_user:status[@code='110']",),
+ ("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]",),
+ ]),
+ # And also, that was not the same nickname
+ partial(expect_unordered, [
+ ("/presence[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_two}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='Bernard']",
+ "/presence/muc_user:x/muc_user:status[@code='303']"),
+ ("/presence[@from='#foo%{irc_server_one}/{nick_three}'][@to='{jid_two}/{resource_one}']",),
+ ("/presence[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='Bernard']",
+ "/presence/muc_user:x/muc_user:status[@code='303']",
+ "/presence/muc_user:x/muc_user:status[@code='110']"),
+ ("/presence[@from='#foo%{irc_server_one}/{nick_three}'][@to='{jid_one}/{resource_one}']",
+ "/presence/muc_user:x/muc_user:status[@code='110']"),
+ ]),
]),
Scenario("channel_join_with_password",
[
@@ -1192,7 +1201,8 @@ if __name__ == '__main__':
"<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' type='unavailable' />"),
# Only user 1 receives the unavailable presence
partial(expect_stanza,
- "/presence[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:status[@code='110']"),
+ ("/presence[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:status[@code='110']",
+ "/presence/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']")),
# Second user sends a channel message
partial(send_stanza, "<message type='groupchat' from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}'><body>coucou</body></message>"),
@@ -1244,6 +1254,64 @@ if __name__ == '__main__':
partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='{irc_server_one}' type='chat'><body>NOTICE {nick_one} :[#foo] Hello in a notice.</body></message>"),
partial(expect_stanza, "/message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/body[text()='[notice] [#foo] Hello in a notice.']"),
]),
+ Scenario("multiline_message",
+ [
+ handshake_sequence(),
+ # First user joins
+ partial(send_stanza,
+ "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' />"),
+ connection_sequence("irc.localhost", '{jid_one}/{resource_one}'),
+ partial(expect_stanza,
+ "/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"),
+ partial(expect_stanza,
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
+ "/presence/muc_user:x/muc_user:status[@code='110']")
+ ),
+ partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
+
+ # Send a multi-line channel message
+ partial(send_stanza, "<message id='the-message-id' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='groupchat'><body>un\ndeux\ntrois</body></message>"),
+ # Receive multiple messages, in order
+ partial(expect_stanza,
+ "/message[@from='#foo%{irc_server_one}/{nick_one}'][@id='the-message-id'][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='un']"),
+ partial(expect_stanza,
+ "/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='deux']"),
+ partial(expect_stanza,
+ "/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='trois']"),
+
+ # Send a simple message, with no id
+ partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='groupchat'><body>hello</body></message>"),
+
+ # Expect a non-empty id as a result (should be a uuid)
+ partial(expect_stanza,
+ "!/message[@id='']/body[text()='hello']"),
+
+ # Second user joins
+ partial(send_stanza,
+ "<presence from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}/{nick_two}' />"),
+ connection_sequence("irc.localhost", '{jid_two}/{resource_one}'),
+ # Our presence, sent to the other user
+ partial(expect_unordered, [
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']/muc_user:x/muc_user:item[@affiliation='none'][@jid='~bobby@localhost'][@role='participant']",),
+ ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",),
+ ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']/muc_user:x/muc_user:item[@affiliation='none'][@jid='~bobby@localhost'][@role='participant']",
+ "/presence/muc_user:x/muc_user:status[@code='110']"),
+ ("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]",)
+ ]),
+
+ # Send a multi-line channel message
+ partial(send_stanza, "<message id='the-message-id' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='groupchat'><body>un\ndeux\ntrois</body></message>"),
+ # Receive multiple messages, for each user
+ partial(expect_unordered, [
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id='the-message-id'][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='un']",),
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='deux']",),
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='trois']",),
+
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='un']",),
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='deux']",),
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='trois']",),
+ ])
+ ]),
Scenario("channel_messages",
[
handshake_sequence(),
@@ -1276,8 +1344,10 @@ if __name__ == '__main__':
partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='groupchat'><body>coucou</body></message>"),
# Receive the message, forwarded to the two users
partial(expect_unordered, [
- ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='coucou']",),
- ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='coucou']",)
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='coucou']",
+ "/message/stable_id:stanza-id[@by='#foo%{irc_server_one}'][@id]"),
+ ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='coucou']",
+ "/message/stable_id:stanza-id[@by='#foo%{irc_server_one}'][@id]")
]),
# Send a private message, to a in-room JID
@@ -1294,27 +1364,27 @@ if __name__ == '__main__':
## Do the exact same thing, from a different chan,
# to check if the response comes from the right JID
- # Join the virtual channel
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#dummy%{irc_server_one}/{nick_one}' />"),
+ partial(expect_stanza, "/message"),
partial(expect_stanza,
"/presence/muc_user:x/muc_user:status[@code='110']"),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject"),
+ partial(expect_stanza, "/message[@from='#dummy%{irc_server_one}'][@type='groupchat']/subject"),
# Send a private message, to a in-room JID
- partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' type='chat'><body>re in private</body></message>"),
+ partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#dummy%{irc_server_one}/{nick_two}' type='chat'><body>re in private</body></message>"),
# Message is received with a server-wide JID
partial(expect_stanza, "/message[@from='{lower_nick_one}%{irc_server_one}'][@to='{jid_two}/{resource_one}'][@type='chat']/body[text()='re in private']"),
# Respond to the message, to the server-wide JID
partial(send_stanza, "<message from='{jid_two}/{resource_one}' to='{lower_nick_one}%{irc_server_one}' type='chat'><body>re</body></message>"),
# The response is received from the in-room JID
- partial(expect_stanza, "/message[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='re']"),
+ partial(expect_stanza, "/message[@from='#dummy%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}'][@type='chat']/body[text()='re']"),
# Now we leave the room, to check if the subsequent private messages are still received properly
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' type='unavailable' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#dummy%{irc_server_one}/{nick_one}' type='unavailable' />"),
partial(expect_stanza,
"/presence[@type='unavailable']/muc_user:x/muc_user:status[@code='110']"),
@@ -1861,7 +1931,8 @@ if __name__ == '__main__':
partial(expect_stanza,
("/iq[@type='result'][@id='id1'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
"/iq/mam:fin/rms:set/rsm:last",
- "/iq/mam:fin/rsm:set/rsm:first")),
+ "/iq/mam:fin/rsm:set/rsm:first",
+ "/iq/mam:fin[@complete='true']")),
# Retrieve an empty archive by specifying an early “end” date
partial(send_stanza, """<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id2'>
@@ -1873,7 +1944,8 @@ if __name__ == '__main__':
</query></iq>"""),
partial(expect_stanza,
- "/iq[@type='result'][@id='id2'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']"),
+ ("/iq[@type='result'][@id='id2'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin[@complete='true']/rsm:set",)),
# Retrieve an empty archive by specifying a late “start” date
# (note that this test will break in ~1000 years)
@@ -1886,18 +1958,20 @@ if __name__ == '__main__':
</query></iq>"""),
partial(expect_stanza,
- "/iq[@type='result'][@id='id3'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']"),
+ ("/iq[@type='result'][@id='id3'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin[@complete='true']/rsm:set")),
# Retrieve a limited archive
partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id4'><query xmlns='urn:xmpp:mam:2' queryid='qid4'><set xmlns='http://jabber.org/protocol/rsm'><max>1</max></set></query></iq>"),
partial(expect_stanza,
("/message/mam:result[@queryid='qid4']/forward:forwarded/delay:delay",
- "/message/mam:result[@queryid='qid4']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='coucou 2']")
+ "/message/mam:result[@queryid='qid4']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='coucou']")
),
partial(expect_stanza,
- "/iq[@type='result'][@id='id4'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']"),
+ ("/iq[@type='result'][@id='id4'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin[@complete='true']/rsm:set")),
]),
Scenario("mam_with_timestamps",
@@ -1957,10 +2031,9 @@ if __name__ == '__main__':
),
partial(expect_stanza,
- "/iq[@type='result'][@id='id8'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']"),
+ ("/iq[@type='result'][@id='id8'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin[@complete='true']/rsm:set")),
]),
-
-
Scenario("join_history_limits",
[
handshake_sequence(),
@@ -1995,9 +2068,10 @@ if __name__ == '__main__':
partial(expect_stanza, "/message[@type='groupchat']/body[text()='coucou 4']",
after = partial(save_current_timestamp_plus_delta, "second_timestamp", datetime.timedelta(seconds=1))),
- # join the virtual channel, to stay connected to the server even after leaving #foo
+ # join some other channel, to stay connected to the server even after leaving #foo
partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
+ "<presence from='{jid_one}/{resource_one}' to='#DUMMY%{irc_server_one}/{nick_one}' />"),
+ partial(expect_stanza, "/message"),
partial(expect_stanza, "/presence/muc_user:x/muc_user:status[@code='110']"),
partial(expect_stanza, "/message/subject"),
@@ -2075,8 +2149,6 @@ if __name__ == '__main__':
partial(expect_stanza, "/presence[@type='unavailable']"),
]),
-
-
Scenario("mam_on_fixed_server",
[
handshake_sequence(),
@@ -2134,10 +2206,10 @@ if __name__ == '__main__':
# Retrieve the archive, without any restriction
partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id1'><query xmlns='urn:xmpp:mam:2' queryid='qid1' /></iq>"),
# Since we should only receive the last 100 messages from the archive,
- # it should start with message "50"
+ # it should start with message "1"
partial(expect_stanza,
("/message/mam:result[@queryid='qid1']/forward:forwarded/delay:delay",
- "/message/mam:result[@queryid='qid1']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='50']")
+ "/message/mam:result[@queryid='qid1']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='1']")
),
] + [
# followed by 98 more messages
@@ -2146,14 +2218,87 @@ if __name__ == '__main__':
"/message/mam:result[@queryid='qid1']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body")
),
] * 98 + [
- # and finally the message "149"
+ # and finally the message "99"
partial(expect_stanza,
("/message/mam:result[@queryid='qid1']/forward:forwarded/delay:delay",
- "/message/mam:result[@queryid='qid1']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='149']")
+ "/message/mam:result[@queryid='qid1']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='100']"),
+ after = partial(save_value, "last_uuid", partial(extract_attribute, "/message/mam:result", "id"))
),
+ # And it should not be marked as complete
partial(expect_stanza,
- "/iq[@type='result'][@id='id1'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']"),
+ ("/iq[@type='result'][@id='id1'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin/rsm:set/rsm:last[text()='{last_uuid}']",
+ "!/iq//mam:fin[@complete='true']",
+ "/iq//mam:fin")),
+ # Retrieve the next page, using the “after” thingy
+ partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id2'><query xmlns='urn:xmpp:mam:2' queryid='qid2' ><set xmlns='http://jabber.org/protocol/rsm'><after>{last_uuid}</after></set></query></iq>"),
+
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid2']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid2']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='101']")
+ ),
+ ] + 47 * [
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid2']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid2']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body")
+ ),
+ ] + [
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid2']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid2']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='149']"),
+ after = partial(save_value, "last_uuid", partial(extract_attribute, "/message/mam:result", "id"))
+ ),
+ partial(expect_stanza,
+ ("/iq[@type='result'][@id='id2'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin/rsm:set/rsm:last[text()='{last_uuid}']",
+ "/iq//mam:fin[@complete='true']",
+ "/iq//mam:fin")),
+
+ # Send a request with a non-existing ID set as the “after” value.
+ partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id3'><query xmlns='urn:xmpp:mam:2' queryid='qid3' ><set xmlns='http://jabber.org/protocol/rsm'><after>DUMMY_ID</after></set></query></iq>"),
+ partial(expect_stanza, "/iq[@id='id3'][@type='error']/error[@type='cancel']/stanza:item-not-found"),
+
+ # Request the last page just BEFORE the last message in the archive
+ partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id3'><query xmlns='urn:xmpp:mam:2' queryid='qid3' ><set xmlns='http://jabber.org/protocol/rsm'><before></before></set></query></iq>"),
+
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid3']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid3']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='50']")
+ ),
+ ] + 98 * [
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid3']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid3']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body")
+ ),
+ ] + [
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid3']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid3']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='149']"),
+ after = partial(save_value, "last_uuid", partial(extract_attribute, "/message/mam:result", "id"))
+ ),
+ partial(expect_stanza,
+ ("/iq[@type='result'][@id='id3'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin/rsm:set/rsm:last[text()='{last_uuid}']",
+ "!/iq//mam:fin[@complete='true']",
+ "/iq//mam:fin")),
+
+ # Do the same thing, but with a limit value.
+ partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id4'><query xmlns='urn:xmpp:mam:2' queryid='qid4' ><set xmlns='http://jabber.org/protocol/rsm'><before>{last_uuid}</before><max>2</max></set></query></iq>"),
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid4']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid4']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='147']")
+ ),
+ partial(expect_stanza,
+ ("/message/mam:result[@queryid='qid4']/forward:forwarded/delay:delay",
+ "/message/mam:result[@queryid='qid4']/forward:forwarded/client:message[@from='#foo%{irc_server_one}/{nick_one}'][@type='groupchat']/client:body[text()='148']"),
+ after = partial(save_value, "last_uuid", partial(extract_attribute, "/message/mam:result", "id"))
+ ),
+ partial(expect_stanza,
+ ("/iq[@type='result'][@id='id4'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']",
+ "/iq/mam:fin/rsm:set/rsm:last[text()='{last_uuid}']",
+ "/iq/mam:fin[@complete='true']",
+ "/iq/mam:fin")),
]),
Scenario("channel_history_on_fixed_server",
[
@@ -2212,9 +2357,6 @@ if __name__ == '__main__':
# Second user joins
partial(send_stanza,
"<presence from='{jid_one}/{resource_two}' to='#foo%{irc_server_one}/{nick_one}' />"),
- # connection_sequence("irc.localhost", '{jid_one}/{resource_two}'),
- # partial(expect_stanza,
- # "/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"),
partial(expect_stanza,
("/presence[@to='{jid_one}/{resource_two}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@jid='~nick@localhost'][@role='moderator']",
"/presence/muc_user:x/muc_user:status[@code='110']")
@@ -2254,6 +2396,21 @@ if __name__ == '__main__':
"/iq/disco_items:query/disco_items:item[@jid='#bar%{irc_server_one}']"
))
]),
+ Scenario("channel_list_escaping",
+ [
+ handshake_sequence(),
+
+ partial(send_stanza,
+ "<presence from='{jid_one}/{resource_one}' to='#true\\2ffalse%{irc_server_one}/{nick_one}' />"),
+ connection_sequence("irc.localhost", '{jid_one}/{resource_one}'),
+ partial(expect_stanza,
+ "/message/body[text()='Mode #true/false [+nt] by {irc_host_one}']"),
+ partial(expect_stanza,
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#true\\2ffalse%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
+ "/presence/muc_user:x/muc_user:status[@code='110']")
+ ),
+ partial(expect_stanza, "/message[@from='#true\\2ffalse%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),
+ ]),
Scenario("channel_list_with_rsm",
[
handshake_sequence(),
@@ -2516,7 +2673,7 @@ if __name__ == '__main__':
"<iq from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' id='1' type='get'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>"),
partial(expect_stanza,
("/iq[@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}'][@type='result']/disco_info:query",
- "/iq[@type='result']/disco_info:query/disco_info:identity[@category='conference'][@type='irc'][@name='IRC channel #foo from server {irc_host_one} over biboumi']",
+ "/iq[@type='result']/disco_info:query/disco_info:identity[@category='conference'][@type='irc'][@name='#foo on {irc_host_one}']",
"/iq/disco_info:query/disco_info:feature[@var='jabber:iq:version']",
"/iq/disco_info:query/disco_info:feature[@var='http://jabber.org/protocol/commands']",
"/iq/disco_info:query/disco_info:feature[@var='urn:xmpp:ping']",
@@ -2532,7 +2689,7 @@ if __name__ == '__main__':
"<iq from='{jid_one}/{resource_one}' to='#foo@{biboumi_host}' id='1' type='get'><query xmlns='http://jabber.org/protocol/disco#info'/></iq>"),
partial(expect_stanza,
("/iq[@from='#foo@{biboumi_host}'][@to='{jid_one}/{resource_one}'][@type='result']/disco_info:query",
- "/iq[@type='result']/disco_info:query/disco_info:identity[@category='conference'][@type='irc'][@name='IRC channel #foo from server {irc_host_one} over biboumi']",
+ "/iq[@type='result']/disco_info:query/disco_info:identity[@category='conference'][@type='irc'][@name='#foo on {irc_host_one}']",
"/iq/disco_info:query/disco_info:feature[@var='jabber:iq:version']",
"/iq/disco_info:query/disco_info:feature[@var='http://jabber.org/protocol/commands']",
"/iq/disco_info:query/disco_info:feature[@var='urn:xmpp:ping']",
@@ -2598,56 +2755,6 @@ if __name__ == '__main__':
partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><x xmlns='http://jabber.org/protocol/muc#user'><invite to='bertrand@example.com'/></x></message>"),
partial(expect_stanza, "/message[@to='bertrand@example.com'][@from='#foo%{irc_server_one}']/muc_user:x/muc_user:invite[@from='{jid_one}/{resource_one}']"),
]),
- Scenario("virtual_channel_multisession",
- [
- handshake_sequence(),
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_one}' />"),
- connection_begin_sequence("irc.localhost", '{jid_one}/{resource_one}'),
- connection_middle_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
- connection_end_sequence("irc.localhost", '{jid_one}/{resource_one}'),
-
- partial(send_stanza,
- "<presence from='{jid_one}/{resource_two}' to='%{irc_server_one}/{nick_one}' />"),
-
- partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_two}'][@from='%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",
- "/presence/muc_user:x/muc_user:status[@code='110']")
- ),
- partial(expect_stanza, "/message[@to='{jid_one}/{resource_two}'][@from='%{irc_server_one}'][@type='groupchat']/subject[re:test(text(), '^This is a virtual channel.*$')]"),
-
-
- partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
-
- partial(expect_unordered, [
- ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_two}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='Bobby']",
- "/presence/muc_user:x/muc_user:status[@code='303']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_two}']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
-
- ("/presence[@from='%{irc_server_one}/{nick_one}'][@to='{jid_one}/{resource_one}'][@type='unavailable']/muc_user:x/muc_user:item[@nick='Bobby']",
- "/presence/muc_user:x/muc_user:status[@code='303']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ("/presence[@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']",
- "/presence/muc_user:x/muc_user:status[@code='110']"),
- ]),
-
-
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_one}' to='%{irc_server_one}/{nick_two}' />"),
- partial(expect_stanza, ("/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}'][@to='{jid_one}/{resource_one}']/muc_user:x/muc_user:status[@code='110']",
- "/presence/status[text()='Biboumi note: 1 resources are still in this channel.']",)
- ),
-
- partial(send_stanza, "<presence type='unavailable' from='{jid_one}/{resource_two}' to='%{irc_server_one}/{nick_two}' />"),
- partial(expect_stanza, "/presence[@type='unavailable'][@from='%{irc_server_one}/{nick_two}']"),
- ]),
Scenario("global_configure",
[
handshake_sequence(),
@@ -2706,7 +2813,8 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='verify_cert']/dataform:value[text()='true']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='fingerprint']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-private'][@var='pass']",
- "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='after_connect_command']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='after_connect_commands']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='nick']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='username']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='realname']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']",
@@ -2723,7 +2831,8 @@ if __name__ == '__main__':
"<field var='verify_cert'><value>1</value></field>"
"<field var='fingerprint'><value>12:12:12</value></field>"
"<field var='pass'><value>coucou</value></field>"
- "<field var='after_connect_command'><value>INVALID command</value></field>"
+ "<field var='after_connect_commands'><value>first command</value><value>second command</value></field>"
+ "<field var='nick'><value>my_nickname</value></field>"
"<field var='username'><value>username</value></field>"
"<field var='realname'><value>realname</value></field>"
"<field var='encoding_out'><value>UTF-8</value></field>"
@@ -2741,7 +2850,9 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='verify_cert']/dataform:value[text()='true']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='fingerprint']/dataform:value[text()='12:12:12']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-private'][@var='pass']/dataform:value[text()='coucou']",
- "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='after_connect_command']/dataform:value[text()='INVALID command']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='nick']/dataform:value[text()='my_nickname']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='after_connect_commands']/dataform:value[text()='first command']",
+ "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='after_connect_commands']/dataform:value[text()='second command']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='username']/dataform:value[text()='username']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='realname']/dataform:value[text()='realname']",
"/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']/dataform:value[text()='latin-1']",
@@ -2762,7 +2873,7 @@ if __name__ == '__main__':
"<command xmlns='http://jabber.org/protocol/commands' node='configure' sessionid='{sessionid}' action='next'>"
"<x xmlns='jabber:x:data' type='submit'>"
"<field var='pass'><value></value></field>"
- "<field var='after_connect_command'><value></value></field>"
+ "<field var='after_connect_commands'></field>"
"<field var='username'><value></value></field>"
"<field var='realname'><value></value></field>"
"<field var='encoding_out'><value></value></field>"
@@ -2775,7 +2886,7 @@ if __name__ == '__main__':
"/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure the IRC server irc.localhost']",
"/iq/commands:command/dataform:x[@type='form']/dataform:instructions[text()='Edit the form, to configure the settings of the IRC server irc.localhost']",
"!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='pass']/dataform:value",
- "!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='after_connect_command']/dataform:value",
+ "!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='after_connect_commands']/dataform:value",
"!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='username']/dataform:value",
"!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='realname']/dataform:value",
"!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='encoding_in']/dataform:value",
@@ -2887,6 +2998,7 @@ if __name__ == '__main__':
"<field var='ports' />"
"<field var='tls_ports'><value>7778</value></field>"
"<field var='verify_cert'><value>0</value></field>"
+ "<field var='nick'><value>my_special_nickname</value></field>"
"</x></command></iq>"),
partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"),
@@ -2896,7 +3008,7 @@ if __name__ == '__main__':
partial(expect_stanza,
"/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"),
partial(expect_stanza,
- ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
+ ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/my_special_nickname']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",
"/presence/muc_user:x/muc_user:status[@code='110']")
),
partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"),