diff options
author | louiz’ <louiz@louiz.org> | 2018-09-03 22:26:57 +0200 |
---|---|---|
committer | louiz’ <louiz@louiz.org> | 2018-09-03 22:26:57 +0200 |
commit | 193302b0de20df6adc090eaeaa84cfd286be724a (patch) | |
tree | b9e0e0f75b5cd74911a42a7fcd0f1477971391ff /tests | |
parent | 56651cb5c29cc50ddf3c62c37167fa0b9389bfde (diff) | |
parent | 28acbed948e1c281f9de6132164e42d0ed20c32f (diff) | |
download | biboumi-193302b0de20df6adc090eaeaa84cfd286be724a.tar.gz biboumi-193302b0de20df6adc090eaeaa84cfd286be724a.tar.bz2 biboumi-193302b0de20df6adc090eaeaa84cfd286be724a.tar.xz biboumi-193302b0de20df6adc090eaeaa84cfd286be724a.zip |
Merge branch 'master' into debian
Diffstat (limited to 'tests')
-rw-r--r-- | tests/database.cpp | 64 | ||||
-rw-r--r-- | tests/end_to_end/__main__.py | 578 | ||||
-rw-r--r-- | tests/jid.cpp | 2 | ||||
-rw-r--r-- | tests/network.cpp | 1 |
4 files changed, 476 insertions, 169 deletions
diff --git a/tests/database.cpp b/tests/database.cpp index 7ab6da8..070a460 100644 --- a/tests/database.cpp +++ b/tests/database.cpp @@ -7,6 +7,7 @@ #include <cstdlib> #include <database/database.hpp> +#include <database/save.hpp> #include <config/config.hpp> @@ -28,11 +29,11 @@ TEST_CASE("Database") { auto o = Database::get_irc_server_options("zouzou@example.com", "irc.example.com"); CHECK(Database::count(Database::irc_server_options) == 0); - o.save(Database::db); + save(o, *Database::db); CHECK(Database::count(Database::irc_server_options) == 1); o.col<Database::Realname>() = "Different realname"; CHECK(o.col<Database::Realname>() == "Different realname"); - o.save(Database::db); + save(o, *Database::db); CHECK(o.col<Database::Realname>() == "Different realname"); CHECK(Database::count(Database::irc_server_options) == 1); @@ -44,7 +45,7 @@ TEST_CASE("Database") // inserted CHECK(1 == Database::count(Database::irc_server_options)); - b.save(Database::db); + save(b, *Database::db); CHECK(2 == Database::count(Database::irc_server_options)); CHECK(b.col<Database::Pass>() == ""); @@ -58,11 +59,15 @@ TEST_CASE("Database") o.col<Database::EncodingIn>() = "ISO-8859-1"; CHECK(o.col<Database::RecordHistoryOptional>().is_set == false); o.col<Database::RecordHistoryOptional>().set_value(false); - o.save(Database::db); + save(o, *Database::db); auto b = Database::get_irc_channel_options("zouzou@example.com", "irc.example.com", "#foo"); CHECK(o.col<Database::EncodingIn>() == "ISO-8859-1"); CHECK(o.col<Database::RecordHistoryOptional>().is_set == true); CHECK(o.col<Database::RecordHistoryOptional>().value == false); + + o.clear(); + CHECK(o.col<Database::EncodingIn>() == ""); + CHECK(o.col<Database::Owner>() == "zouzou@example.com"); } SECTION("Channel options with server default") @@ -77,7 +82,7 @@ TEST_CASE("Database") GIVEN("An option defined for the channel but not the server") { c.col<Database::EncodingIn>() = "channelEncoding"; - c.save(Database::db); + save(c, *Database::db); WHEN("we fetch that option") { auto r = Database::get_irc_channel_options_with_server_default(owner, server, chan1); @@ -88,7 +93,7 @@ TEST_CASE("Database") GIVEN("An option defined for the server but not the channel") { s.col<Database::EncodingIn>() = "serverEncoding"; - s.save(Database::db); + save(s, *Database::db); WHEN("we fetch that option") { auto r = Database::get_irc_channel_options_with_server_default(owner, server, chan1); @@ -99,9 +104,9 @@ TEST_CASE("Database") GIVEN("An option defined for both the server and the channel") { s.col<Database::EncodingIn>() = "serverEncoding"; - s.save(Database::db); + save(s, *Database::db); c.col<Database::EncodingIn>() = "channelEncoding"; - c.save(Database::db); + save(c, *Database::db); WHEN("we fetch that option") { auto r = Database::get_irc_channel_options_with_server_default(owner, server, chan1); @@ -117,6 +122,49 @@ TEST_CASE("Database") } } + SECTION("Server options") + { + const std::string owner{"toto@example.com"}; + const std::string owner2{"toto2@example.com"}; + const std::string server{"irc.example.com"}; + + auto soptions = Database::get_irc_server_options(owner, server); + auto soptions2 = Database::get_irc_server_options(owner2, server); + + auto after_connection_commands = Database::get_after_connection_commands(soptions); + CHECK(after_connection_commands.empty()); + + save(soptions, *Database::db); + save(soptions2, *Database::db); + auto com = Database::after_connection_commands.row(); + com.col<Database::AfterConnectionCommand>() = "first"; + after_connection_commands.push_back(com); + com.col<Database::AfterConnectionCommand>() = "second"; + after_connection_commands.push_back(com); + Database::set_after_connection_commands(soptions, after_connection_commands); + + after_connection_commands.clear(); + com.col<Database::AfterConnectionCommand>() = "first"; + after_connection_commands.push_back(com); + com.col<Database::AfterConnectionCommand>() = "second"; + after_connection_commands.push_back(com); + Database::set_after_connection_commands(soptions2, after_connection_commands); + + after_connection_commands = Database::get_after_connection_commands(soptions); + CHECK(after_connection_commands.size() == 2); + after_connection_commands = Database::get_after_connection_commands(soptions2); + CHECK(after_connection_commands.size() == 2); + + after_connection_commands.clear(); + after_connection_commands.push_back(com); + Database::set_after_connection_commands(soptions, after_connection_commands); + + after_connection_commands = Database::get_after_connection_commands(soptions); + CHECK(after_connection_commands.size() == 1); + after_connection_commands = Database::get_after_connection_commands(soptions2); + CHECK(after_connection_commands.size() == 2); + } + Database::close(); } #endif diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index c4c149a..d57f375 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))) @@ -331,6 +333,8 @@ class BiboumiTest: except FileNotFoundError: pass + start_datetime = datetime.datetime.now() + # Start the XMPP component and biboumi biboumi = BiboumiRunner(self.scenario.name) xmpp = XMPPComponent(self.scenario, biboumi) @@ -342,13 +346,16 @@ class BiboumiTest: code = asyncio.get_event_loop().run_until_complete(biboumi.wait()) xmpp.biboumi = None self.scenario.steps.clear() + + delta = datetime.datetime.now() - start_datetime + failed = False if not xmpp.failed: if code != self.expected_code: xmpp.error("Wrong return code from biboumi's process: %d" % (code,)) failed = True else: - print("[32;1mSuccess![0m") + print("[32;1mSuccess![0m ({}s)".format(round(delta.total_seconds(), 2))) else: failed = True @@ -606,6 +613,23 @@ if __name__ == '__main__': ), partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"), ]), + Scenario("raw_names_command", + [ + handshake_sequence(), + 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"), + partial(expect_stanza, + "/presence/muc_user:x/muc_user:status[@code='110']" + ), + partial(expect_stanza, "/message/subject[not(text())]"), + partial(send_stanza, + "<message type='chat' from='{jid_one}/{resource_one}' to='{irc_server_one}'><body>NAMES</body></message>"), + partial(expect_stanza, "/message/body[text()='irc.localhost: = #foo @{nick_one} ']"), + partial(expect_stanza, "/message/body[text()='irc.localhost: * End of /NAMES list. ']"), + ]), Scenario("quit", [ handshake_sequence(), @@ -661,23 +685,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 +701,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 +745,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 +754,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", [ @@ -865,28 +896,35 @@ if __name__ == '__main__': handshake_sequence(), partial(send_stanza, "<iq type='get' id='idwhatever' from='{jid_one}/{resource_one}' to='{biboumi_host}'><query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands' /></iq>"), partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", - "/iq/disco_items:query/disco_items:item[3]")), + "/iq/disco_items:query/disco_items:item[@node='configure']", + "/iq/disco_items:query/disco_items:item[4]", + "!/iq/disco_items:query/disco_items:item[5]")), ]), Scenario("list_admin_adhoc", [ handshake_sequence(), partial(send_stanza, "<iq type='get' id='idwhatever' from='{jid_admin}/{resource_one}' to='{biboumi_host}'><query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands' /></iq>"), partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", - "/iq/disco_items:query/disco_items:item[5]")), + "/iq/disco_items:query/disco_items:item[6]", + "!/iq/disco_items:query/disco_items:item[7]")), ]), Scenario("list_adhoc_fixed_server", [ handshake_sequence(), partial(send_stanza, "<iq type='get' id='idwhatever' from='{jid_one}/{resource_one}' to='{biboumi_host}'><query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands' /></iq>"), partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", - "/iq/disco_items:query/disco_items:item[5]")), + "/iq/disco_items:query/disco_items:item[@node='global-configure']", + "/iq/disco_items:query/disco_items:item[@node='server-configure']", + "/iq/disco_items:query/disco_items:item[6]", + "!/iq/disco_items:query/disco_items:item[7]")), ], conf='fixed_server'), Scenario("list_admin_adhoc_fixed_server", [ handshake_sequence(), partial(send_stanza, "<iq type='get' id='idwhatever' from='{jid_admin}/{resource_one}' to='{biboumi_host}'><query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands' /></iq>"), partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", - "/iq/disco_items:query/disco_items:item[5]")), + "/iq/disco_items:query/disco_items:item[8]", + "!/iq/disco_items:query/disco_items:item[9]")), ], conf='fixed_server'), Scenario("list_adhoc_irc", [ @@ -895,20 +933,6 @@ if __name__ == '__main__': partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", "/iq/disco_items:query/disco_items:item[2]")), ]), - Scenario("list_adhoc_irc_fixed_server", - [ - handshake_sequence(), - partial(send_stanza, "<iq type='get' id='idwhatever' from='{jid_one}/{resource_one}' to='{biboumi_host}'><query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands' /></iq>"), - partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", - "/iq/disco_items:query/disco_items:item[4]")), - ], conf='fixed_server'), - Scenario("list_admin_adhoc_irc_fixed_server", - [ - handshake_sequence(), - partial(send_stanza, "<iq type='get' id='idwhatever' from='{jid_admin}/{resource_one}' to='{biboumi_host}'><query xmlns='http://jabber.org/protocol/disco#items' node='http://jabber.org/protocol/commands' /></iq>"), - partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", - "/iq/disco_items:query/disco_items:item[6]")), - ], conf='fixed_server'), Scenario("list_muc_user_adhoc", [ handshake_sequence(), @@ -1083,13 +1107,12 @@ if __name__ == '__main__': ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']",), ("/presence[@to='{jid_one}/{resource_two}'][@from='#foo%{irc_server_one}/{nick_two}']",), ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']", - "/presence/muc_user:x/muc_user:status[@code='110']",), + "/presence/muc_user:x/muc_user:status[@code='110']",), ("/presence[@to='{jid_two}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']",), + ("/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]",), ] ), - partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"), - # That second user sends a private message to the first one partial(send_stanza, "<message from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' type='chat'><body>RELLO</body></message>"), # Message is received with a server-wide JID, by the two resources behind nick_one @@ -1192,7 +1215,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 +1268,80 @@ 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']", + "/message[@id]/body[text()='hello']")), + + # even though we reflect the message to XMPP only + # when we send it to IRC, there’s still a race + # condition if the XMPP client receives the + # reflection (and the IRC server didn’t yet receive + # it), then the new user joins the room, and then + # finally the IRC server sends the message to “all + # participants of the channel”, including the new + # one, that was not supposed to be there when the + # message was sent in the first place by the first + # XMPP user. There’s nothing we can do about it until + # all servers support the echo-message IRCv3 + # extension… So, we just sleep a little bit before + # joining the room with the new user. + partial(sleep_for, 1), + + # 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>a\nb\nc</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()='a']",), + ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='b']",), + ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_one}/{resource_one}'][@type='groupchat']/body[text()='c']",), + + ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='a']",), + ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='b']",), + ("/message[@from='#foo%{irc_server_one}/{nick_one}'][@id][@to='{jid_two}/{resource_one}'][@type='groupchat']/body[text()='c']",), + ]) + ]), Scenario("channel_messages", [ handshake_sequence(), @@ -1276,8 +1374,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 +1394,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']"), @@ -1324,6 +1424,32 @@ if __name__ == '__main__': "/message[@from='{lower_nick_two}%{irc_server_one}'][@to='{jid_one}/{resource_one}']"), ] ), + Scenario("muc_message_from_unjoined_resource", + [ + handshake_sequence(), + 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"), + partial(expect_stanza, "/message/subject"), + + # Send a channel message + partial(send_stanza, "<message from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='groupchat'><body>coucou</body></message>"), + # Receive the message + partial(expect_stanza, + ("/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]"), + ), + + # Send a message from a resource that is not joined + partial(send_stanza, "<message from='{jid_one}/{resource_two}' to='#foo%{irc_server_one}' type='groupchat'><body>coucou</body></message>"), + partial(expect_stanza, ("/message[@type='error']/error[@type='modify']/stanza:text[text()='You are not a participant in this room.']", + "/message/error/stanza:not-acceptable" + )) + + ]), Scenario("encoded_channel_join", [ handshake_sequence(), @@ -1504,9 +1630,10 @@ if __name__ == '__main__': "<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/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",), - ("/presence/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",), - ("/presence/muc_user:x/muc_user:status[@code='110']",), + ("/presence[@to='{jid_one}/{resource_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",), + ("/presence[@to='{jid_two}/{resource_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']", + "/presence/muc_user:x/muc_user:status[@code='110']"), + ("/presence[@to='{jid_two}/{resource_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",), ("/message/subject",), ]), @@ -1522,9 +1649,10 @@ if __name__ == '__main__': partial(send_stanza, "<presence from='{jid_two}/{resource_one}' to='#bar%{irc_server_one}/{nick_two}' />"), partial(expect_unordered, [ - ("/presence/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",), - ("/presence/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",), - ("/presence/muc_user:x/muc_user:status[@code='110']",), + ("/presence[@to='{jid_one}/{resource_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']",), + ("/presence[@to='{jid_two}/{resource_one}']/muc_user:x/muc_user:item[@affiliation='none'][@role='participant']", + "/presence/muc_user:x/muc_user:status[@code='110']"), + ("/presence[@to='{jid_two}/{resource_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",), ("/message/subject",), ]), @@ -1639,7 +1767,7 @@ if __name__ == '__main__': partial(expect_stanza, "/presence/muc_user:x/muc_user:status[@code='110']"), partial(expect_stanza, "/message[@type='groupchat']/subject"), - # Second user joins, fprom two resources + # Second user joins, from two resources partial(send_stanza, "<presence from='{jid_two}/{resource_one}' to='#foo%{irc_server_one}/{nick_two}' />"), connection_sequence("irc.localhost", '{jid_two}/{resource_one}'), @@ -1648,7 +1776,7 @@ if __name__ == '__main__': ("/presence/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']",), ("/presence/muc_user:x/muc_user:status[@code='110']",), ("/message/subject",), - ]), + ]), partial(send_stanza, "<presence from='{jid_two}/{resource_two}' to='#foo%{irc_server_one}/{nick_two}' />"), @@ -1891,17 +2019,17 @@ if __name__ == '__main__': ("/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 + # Retrieve the whole archive, but limit the response to one elemet 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/mam:fin[@complete='true']/rsm:set")), + "!/iq/mam:fin[@complete='true']/rsm:set")), ]), Scenario("mam_with_timestamps", @@ -1964,11 +2092,24 @@ if __name__ == '__main__': ("/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(), + + # Disable the throttling because the test is based on timings + partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute' /></iq>"), + partial(expect_stanza, "/iq[@type='result']", + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))), + partial(send_stanza, "<iq type='set' id='id2' from='{jid_one}/{resource_one}' to='{irc_server_one}'>" + "<command xmlns='http://jabber.org/protocol/commands' node='configure' sessionid='{sessionid}' action='next'>" + "<x xmlns='jabber:x:data' type='submit'>" + "<field var='ports'><value>6667</value></field>" + "<field var='tls_ports'><value>6697</value><value>6670</value></field>" + "<field var='throttle_limit'><value>9999</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.']"), + + partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' />"), connection_sequence("irc.localhost", '{jid_one}/{resource_one}'), @@ -2000,9 +2141,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"), @@ -2010,6 +2152,8 @@ if __name__ == '__main__': partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='unavailable' />"), partial(expect_stanza, "/presence[@type='unavailable']"), + partial(sleep_for, 0.2), + # Rejoin #foo, with some history limit partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}'><x xmlns='http://jabber.org/protocol/muc'><history maxchars='0'/></x></presence>"), @@ -2020,6 +2164,8 @@ if __name__ == '__main__': partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' type='unavailable' />"), partial(expect_stanza, "/presence[@type='unavailable']"), + partial(sleep_for, 0.2), + # Rejoin #foo, with some history limit partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}'><x xmlns='http://jabber.org/protocol/muc'><history maxstanzas='3'/></x></presence>"), @@ -2080,8 +2226,6 @@ if __name__ == '__main__': partial(expect_stanza, "/presence[@type='unavailable']"), ]), - - Scenario("mam_on_fixed_server", [ handshake_sequence(), @@ -2118,6 +2262,20 @@ if __name__ == '__main__': Scenario("default_mam_limit", [ handshake_sequence(), + + # Disable the throttling, otherwise it’s way too long + partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute' /></iq>"), + partial(expect_stanza, "/iq[@type='result']", + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))), + partial(send_stanza, "<iq type='set' id='id2' from='{jid_one}/{resource_one}' to='{irc_server_one}'>" + "<command xmlns='http://jabber.org/protocol/commands' node='configure' sessionid='{sessionid}' action='next'>" + "<x xmlns='jabber:x:data' type='submit'>" + "<field var='ports'><value>6667</value></field>" + "<field var='tls_ports'><value>6697</value><value>6670</value></field>" + "<field var='throttle_limit'><value>9999</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.']"), + partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' />"), connection_sequence("irc.localhost", '{jid_one}/{resource_one}'), @@ -2138,11 +2296,9 @@ if __name__ == '__main__': ] * 150 + [ # 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" 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()='0']") ), ] + [ # followed by 98 more messages @@ -2151,17 +2307,93 @@ 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()='99']"), + 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/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()='100']") + ), + ] + 48 * [ + 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']",)), + + # Test if everything is fine even with weird max value: 0 + partial(send_stanza, "<iq to='#foo%{irc_server_one}' from='{jid_one}/{resource_one}' type='set' id='id5'><query xmlns='urn:xmpp:mam:2' queryid='qid5' ><set xmlns='http://jabber.org/protocol/rsm'><before></before><max>0</max></set></query></iq>"), + + partial(expect_stanza, + ("/iq[@type='result'][@id='id5'][@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}']", + "!/iq/mam:fin[@complete='true']",)), ]), Scenario("channel_history_on_fixed_server", [ @@ -2185,9 +2417,6 @@ if __name__ == '__main__': # Second user joins partial(send_stanza, "<presence from='{jid_one}/{resource_two}' to='#foo@{biboumi_host}/{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@{biboumi_host}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@jid='~nick@localhost'][@role='moderator']", "/presence/muc_user:x/muc_user:status[@code='110']") @@ -2220,9 +2449,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']") @@ -2373,6 +2599,20 @@ if __name__ == '__main__': Scenario("default_channel_list_limit", [ handshake_sequence(), + + # Disable the throttling, otherwise it’s way too long + partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute' /></iq>"), + partial(expect_stanza, "/iq[@type='result']", + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid"))), + partial(send_stanza, "<iq type='set' id='id2' from='{jid_one}/{resource_one}' to='{irc_server_one}'>" + "<command xmlns='http://jabber.org/protocol/commands' node='configure' sessionid='{sessionid}' action='next'>" + "<x xmlns='jabber:x:data' type='submit'>" + "<field var='ports'><value>6667</value></field>" + "<field var='tls_ports'><value>6697</value><value>6670</value></field>" + "<field var='throttle_limit'><value>9999</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.']"), + partial(send_stanza, "<presence from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}/{nick_one}' />"), connection_sequence("irc.localhost", '{jid_one}/{resource_one}'), @@ -2539,12 +2779,33 @@ 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']", "/iq/disco_info:query/disco_info:feature[@var='urn:xmpp:mam:2']", "/iq/disco_info:query/disco_info:feature[@var='jabber:iq:version']", + "!/iq/disco_info:query/dataform:x/dataform:field[@var='muc#roominfo_occupants']" + )), + + # Join the channel, and re-do the same query + 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())]"), + + partial(send_stanza, + "<iq from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}' id='2' 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/disco_info:query/dataform:x/dataform:field[@var='muc#roominfo_occupants']/dataform:value[text()='1']", + "/iq/disco_info:query/dataform:x/dataform:field[@var='FORM_TYPE'][@type='hidden']/dataform:value[text()='http://jabber.org/protocol/muc#roominfo']" )), ]), Scenario("fixed_muc_disco_info", @@ -2555,7 +2816,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']", @@ -2621,56 +2882,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(), @@ -2702,6 +2913,40 @@ if __name__ == '__main__': partial(send_stanza, "<iq type='set' id='id4' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' action='cancel' node='configure' sessionid='{sessionid}' /></iq>"), partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"), ]), + Scenario("global_configure_fixed", + [ + handshake_sequence(), + partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' node='global-configure' action='execute' /></iq>"), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='global-configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure some global default settings.']", + "/iq/commands:command/dataform:x[@type='form']/dataform:instructions[text()='Edit the form, to configure your global settings for the component.']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='max_history_length']/dataform:value[text()='20']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='record_history']/dataform:value[text()='true']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='persistent']/dataform:value[text()='false']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='global-configure']", "sessionid")) + ), + partial(send_stanza, "<iq type='set' id='id2' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' node='global-configure' sessionid='{sessionid}' action='next'><x xmlns='jabber:x:data' type='submit'><field var='record_history'><value>0</value></field><field var='max_history_length'><value>42</value></field></x></command></iq>"), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='global-configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"), + + partial(send_stanza, "<iq type='set' id='id3' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' node='global-configure' action='execute' /></iq>"), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='global-configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure some global default settings.']", + "/iq/commands:command/dataform:x[@type='form']/dataform:instructions[text()='Edit the form, to configure your global settings for the component.']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='max_history_length']/dataform:value[text()='42']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='record_history']/dataform:value[text()='false']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='boolean'][@var='persistent']/dataform:value[text()='false']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='global-configure']", "sessionid")) + ), + partial(send_stanza, "<iq type='set' id='id4' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' action='cancel' node='global-configure' sessionid='{sessionid}' /></iq>"), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='global-configure'][@status='canceled']"), + + partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='{biboumi_host}'><command xmlns='http://jabber.org/protocol/commands' node='server-configure' action='execute' /></iq>"), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='server-configure'][@sessionid][@status='executing']",)) + ], conf='fixed_server'), Scenario("global_configure_persistent_by_default", [ handshake_sequence(), @@ -2728,8 +2973,10 @@ if __name__ == '__main__': "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-multi'][@var='tls_ports']/dataform:value[text()='6697']", "/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-single'][@var='throttle_limit']", "/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']", @@ -2746,8 +2993,10 @@ 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='throttle_limit'><value>42</value></field>" "<field var='realname'><value>realname</value></field>" "<field var='encoding_out'><value>UTF-8</value></field>" "<field var='encoding_in'><value>latin-1</value></field>" @@ -2764,9 +3013,12 @@ 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='throttle_limit']/dataform:value[text()='42']", "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']/dataform:value[text()='latin-1']", "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']/dataform:value[text()='UTF-8']", "/iq/commands:command/commands:actions/commands:next", @@ -2785,9 +3037,10 @@ 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='throttle_limit'><value></value></field>" "<field var='encoding_out'><value></value></field>" "<field var='encoding_in'><value></value></field>" "</x></command></iq>"), @@ -2797,13 +3050,15 @@ if __name__ == '__main__': partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", "/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/dataform:field[@var='tls_ports']/dataform:value", "!/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", "!/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='encoding_out']/dataform:value", "/iq/commands:command/commands:actions/commands:next", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='throttle_limit']/dataform:value[text()='-1']", # An invalid value sets this field to -1, aka disabled ), after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) ), @@ -2814,11 +3069,12 @@ if __name__ == '__main__': Scenario("irc_channel_configure", [ handshake_sequence(), - partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute' /></iq>"), + partial(send_stanza, "<iq type='set' id='id1' from='{jid_one}/{resource_one}' to='#foo%{irc_server_one}'><command xmlns='http://jabber.org/protocol/commands' node='configure' action='execute'><dummy/></command></iq>"), partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']", "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']", "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='list-single'][@var='record_history']/dataform:value[text()='unset']", + "!/iq/commands:command/commands:dummy", ), after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) ), @@ -2910,6 +3166,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.']"), @@ -2919,7 +3176,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())]"), @@ -3122,6 +3379,7 @@ if __name__ == '__main__': print("You can check the files slixmpp_%s_output.txt and biboumi_%s_output.txt to help you debug." % (s.name, s.name)) failures += 1 + sys.stdout.flush() print("Waiting for irc server to exit…") irc.stop() diff --git a/tests/jid.cpp b/tests/jid.cpp index 480827b..592d6f3 100644 --- a/tests/jid.cpp +++ b/tests/jid.cpp @@ -21,8 +21,8 @@ TEST_CASE("jidprep") { // Jidprep const std::string badjid("~zigougou™@EpiK-7D9D1FDE.poez.io/Boujour/coucou/slt™"); - const std::string correctjid = jidprep(badjid); #ifdef LIBIDN_FOUND + const std::string correctjid = jidprep(badjid); CHECK(correctjid == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM"); // Check that the cache does not break things when we prep the same string // multiple times diff --git a/tests/network.cpp b/tests/network.cpp index 33cf023..a52eb6a 100644 --- a/tests/network.cpp +++ b/tests/network.cpp @@ -1,5 +1,6 @@ #include "catch.hpp" #include <network/tls_policy.hpp> +#include <sstream> #ifdef BOTAN_FOUND TEST_CASE("tls_policy") |