summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-11-18 13:38:08 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-11-18 13:38:08 +0300
commitb8dcc911a3b1e3cc05074d9ac4bd8da80b431388 (patch)
tree8f77735d46adff599eccd0ae93b0ad4a5e52520e /test
parentFix IQ result processing (diff)
Make common tests working again
Diffstat (limited to 'test')
-rw-r--r--test/announce_tests.erl61
-rw-r--r--test/carbons_tests.erl202
-rw-r--r--test/csi_tests.erl147
-rw-r--r--test/ejabberd_SUITE.erl2059
-rw-r--r--test/example_tests.erl52
-rw-r--r--test/mam_tests.erl537
-rw-r--r--test/mix_tests.erl139
-rw-r--r--test/mod_legacy.erl8
-rw-r--r--test/muc_tests.erl754
-rw-r--r--test/privacy_tests.erl7
-rw-r--r--test/proxy65_tests.erl105
-rw-r--r--test/pubsub_tests.erl729
-rw-r--r--test/replaced_tests.erl57
-rw-r--r--test/roster_tests.erl6
-rw-r--r--test/sm_tests.erl99
-rw-r--r--test/suite.erl5
-rw-r--r--test/vcard_tests.erl125
17 files changed, 2711 insertions, 2381 deletions
diff --git a/test/announce_tests.erl b/test/announce_tests.erl
new file mode 100644
index 00000000..3eea5298
--- /dev/null
+++ b/test/announce_tests.erl
@@ -0,0 +1,61 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(announce_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [server_jid/1, send_recv/2, recv_message/1, disconnect/1,
+ send/2, wait_for_master/1, wait_for_slave/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {announce_single, [sequence], []}.
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {announce_master_slave, [sequence],
+ [master_slave_test(set_motd)]}.
+
+set_motd_master(Config) ->
+ ServerJID = server_jid(Config),
+ MotdJID = jid:replace_resource(ServerJID, <<"announce/motd">>),
+ Body = xmpp:mk_text(<<"motd">>),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send(Config, #message{to = MotdJID, body = Body}),
+ #message{from = ServerJID, body = Body} = recv_message(Config),
+ disconnect(Config).
+
+set_motd_slave(Config) ->
+ ServerJID = server_jid(Config),
+ Body = xmpp:mk_text(<<"motd">>),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ #message{from = ServerJID, body = Body} = recv_message(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("announce_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("announce_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("announce_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("announce_" ++ atom_to_list(T) ++ "_slave")]}.
diff --git a/test/carbons_tests.erl b/test/carbons_tests.erl
new file mode 100644
index 00000000..2780dab6
--- /dev/null
+++ b/test/carbons_tests.erl
@@ -0,0 +1,202 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(carbons_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [is_feature_advertised/2, disconnect/1, send_recv/2,
+ recv_presence/1, send/2, get_event/1, recv_message/1,
+ my_jid/1, wait_for_slave/1, wait_for_master/1,
+ put_event/2]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {carbons_single, [sequence],
+ [single_test(feature_enabled),
+ single_test(unsupported_iq)]}.
+
+feature_enabled(Config) ->
+ true = is_feature_advertised(Config, ?NS_CARBONS_2),
+ disconnect(Config).
+
+unsupported_iq(Config) ->
+ lists:foreach(
+ fun({Type, SubEl}) ->
+ #iq{type = error} =
+ send_recv(Config, #iq{type = Type, sub_els = [SubEl]})
+ end, [{Type, SubEl} ||
+ Type <- [get, set],
+ SubEl <- [#carbons_sent{forwarded = #forwarded{}},
+ #carbons_received{forwarded = #forwarded{}},
+ #carbons_private{}]] ++
+ [{get, SubEl} || SubEl <- [#carbons_enable{}, #carbons_disable{}]]),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {carbons_master_slave, [sequence],
+ [master_slave_test(send_recv),
+ master_slave_test(enable_disable)]}.
+
+send_recv_master(Config) ->
+ Peer = ?config(peer, Config),
+ prepare_master(Config),
+ ct:comment("Waiting for the peer to be ready"),
+ ready = get_event(Config),
+ send_messages(Config),
+ ct:comment("Waiting for the peer to disconnect"),
+ #presence{from = Peer, type = unavailable} = recv_presence(Config),
+ disconnect(Config).
+
+send_recv_slave(Config) ->
+ prepare_slave(Config),
+ ok = enable(Config),
+ put_event(Config, ready),
+ recv_carbons(Config),
+ disconnect(Config).
+
+enable_disable_master(Config) ->
+ prepare_master(Config),
+ ct:comment("Waiting for the peer to be ready"),
+ ready = get_event(Config),
+ send_messages(Config),
+ disconnect(Config).
+
+enable_disable_slave(Config) ->
+ Peer = ?config(peer, Config),
+ prepare_slave(Config),
+ ok = enable(Config),
+ ok = disable(Config),
+ put_event(Config, ready),
+ ct:comment("Waiting for the peer to disconnect"),
+ #presence{from = Peer, type = unavailable} = recv_presence(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("carbons_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("carbons_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("carbons_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("carbons_" ++ atom_to_list(T) ++ "_slave")]}.
+
+prepare_master(Config) ->
+ MyJID = my_jid(Config),
+ Peer = ?config(peer, Config),
+ #presence{from = MyJID} = send_recv(Config, #presence{priority = 10}),
+ wait_for_slave(Config),
+ ct:comment("Receiving initial presence from the peer"),
+ #presence{from = Peer} = recv_presence(Config),
+ Config.
+
+prepare_slave(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = enable(Config),
+ wait_for_master(Config),
+ #presence{from = MyJID} = send_recv(Config, #presence{priority = 5}),
+ ct:comment("Receiving initial presence from the peer"),
+ #presence{from = Peer} = recv_presence(Config),
+ Config.
+
+send_messages(Config) ->
+ Server = ?config(server, Config),
+ MyJID = my_jid(Config),
+ JID = jid:make(randoms:get_string(), Server),
+ lists:foreach(
+ fun({send, #message{type = Type} = Msg}) ->
+ I = send(Config, Msg#message{to = JID}),
+ if Type /= error ->
+ #message{id = I, type = error} = recv_message(Config);
+ true ->
+ ok
+ end;
+ ({recv, #message{} = Msg}) ->
+ ejabberd_router:route(
+ JID, MyJID, Msg#message{from = JID, to = MyJID}),
+ ct:comment("Receiving message ~s", [xmpp:pp(Msg)]),
+ #message{} = recv_message(Config)
+ end, message_iterator(Config)).
+
+recv_carbons(Config) ->
+ Peer = ?config(peer, Config),
+ BarePeer = jid:remove_resource(Peer),
+ MyJID = my_jid(Config),
+ lists:foreach(
+ fun({_, #message{sub_els = [#hint{type = 'no-copy'}]}}) ->
+ ok;
+ ({_, #message{sub_els = [#carbons_private{}]}}) ->
+ ok;
+ ({_, #message{sub_els = [#carbons_sent{}]}}) ->
+ ok;
+ ({_, #message{sub_els = [#carbons_received{}]}}) ->
+ ok;
+ ({_, #message{type = T}}) when T /= normal, T /= chat ->
+ ok;
+ ({Dir, #message{type = T, body = Body} = M})
+ when (T == chat) or (T == normal andalso Body /= []) ->
+ ct:comment("Receiving carbon ~s", [xmpp:pp(M)]),
+ #message{from = BarePeer, to = MyJID} = CarbonMsg =
+ recv_message(Config),
+ case Dir of
+ send ->
+ #carbons_sent{forwarded = #forwarded{xml_els = [El]}} =
+ xmpp:get_subtag(CarbonMsg, #carbons_sent{}),
+ #message{body = Body} = xmpp:decode(El);
+ recv ->
+ #carbons_received{forwarded = #forwarded{xml_els = [El]}}=
+ xmpp:get_subtag(CarbonMsg, #carbons_received{}),
+ #message{body = Body} = xmpp:decode(El)
+ end;
+ (_) ->
+ false
+ end, message_iterator(Config)).
+
+enable(Config) ->
+ case send_recv(
+ Config, #iq{type = set,
+ sub_els = [#carbons_enable{}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = Err ->
+ xmpp:get_error(Err)
+ end.
+
+disable(Config) ->
+ case send_recv(
+ Config, #iq{type = set,
+ sub_els = [#carbons_disable{}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = Err ->
+ xmpp:get_error(Err)
+ end.
+
+message_iterator(_Config) ->
+ [{Dir, #message{type = Type, body = Body, sub_els = Els}}
+ || Dir <- [send, recv],
+ Type <- [error, chat, normal, groupchat, headline],
+ Body <- [[], xmpp:mk_text(<<"body">>)],
+ Els <- [[],
+ [#hint{type = 'no-copy'}],
+ [#carbons_private{}],
+ [#carbons_sent{forwarded = #forwarded{}}],
+ [#carbons_received{forwarded = #forwarded{}}]]].
diff --git a/test/csi_tests.erl b/test/csi_tests.erl
new file mode 100644
index 00000000..9a96b8a5
--- /dev/null
+++ b/test/csi_tests.erl
@@ -0,0 +1,147 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(csi_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [disconnect/1, wait_for_slave/1, wait_for_master/1,
+ send/2, send_recv/2, recv_presence/1, recv_message/1,
+ server_jid/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {csi_single, [sequence],
+ [single_test(feature_enabled)]}.
+
+feature_enabled(Config) ->
+ true = ?config(csi, Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {csi_master_slave, [sequence],
+ [master_slave_test(all)]}.
+
+all_master(Config) ->
+ Peer = ?config(peer, Config),
+ Presence = #presence{to = Peer},
+ ChatState = #message{to = Peer, thread = <<"1">>,
+ sub_els = [#chatstate{type = active}]},
+ Message = ChatState#message{body = [#text{data = <<"body">>}]},
+ PepPayload = xmpp:encode(#presence{}),
+ PepOne = #message{
+ to = Peer,
+ sub_els =
+ [#ps_event{
+ items =
+ #ps_items{
+ node = <<"foo-1">>,
+ items =
+ [#ps_item{
+ id = <<"pep-1">>,
+ xml_els = [PepPayload]}]}}]},
+ PepTwo = #message{
+ to = Peer,
+ sub_els =
+ [#ps_event{
+ items =
+ #ps_items{
+ node = <<"foo-2">>,
+ items =
+ [#ps_item{
+ id = <<"pep-2">>,
+ xml_els = [PepPayload]}]}}]},
+ %% Wait for the slave to become inactive.
+ wait_for_slave(Config),
+ %% Should be queued (but see below):
+ send(Config, Presence),
+ %% Should replace the previous presence in the queue:
+ send(Config, Presence#presence{type = unavailable}),
+ %% The following two PEP stanzas should be queued (but see below):
+ send(Config, PepOne),
+ send(Config, PepTwo),
+ %% The following two PEP stanzas should replace the previous two:
+ send(Config, PepOne),
+ send(Config, PepTwo),
+ %% Should be queued (but see below):
+ send(Config, ChatState),
+ %% Should replace the previous chat state in the queue:
+ send(Config, ChatState#message{sub_els = [#chatstate{type = composing}]}),
+ %% Should be sent immediately, together with the queued stanzas:
+ send(Config, Message),
+ %% Wait for the slave to become active.
+ wait_for_slave(Config),
+ %% Should be delivered, as the client is active again:
+ send(Config, ChatState),
+ disconnect(Config).
+
+all_slave(Config) ->
+ Peer = ?config(peer, Config),
+ change_client_state(Config, inactive),
+ wait_for_master(Config),
+ #presence{from = Peer, type = unavailable, sub_els = [#delay{}]} =
+ recv_presence(Config),
+ #message{
+ from = Peer,
+ sub_els =
+ [#ps_event{
+ items =
+ #ps_items{
+ node = <<"foo-1">>,
+ items =
+ [#ps_item{
+ id = <<"pep-1">>}]}},
+ #delay{}]} = recv_message(Config),
+ #message{
+ from = Peer,
+ sub_els =
+ [#ps_event{
+ items =
+ #ps_items{
+ node = <<"foo-2">>,
+ items =
+ [#ps_item{
+ id = <<"pep-2">>}]}},
+ #delay{}]} = recv_message(Config),
+ #message{from = Peer, thread = <<"1">>,
+ sub_els = [#chatstate{type = composing},
+ #delay{}]} = recv_message(Config),
+ #message{from = Peer, thread = <<"1">>,
+ body = [#text{data = <<"body">>}],
+ sub_els = [#chatstate{type = active}]} = recv_message(Config),
+ change_client_state(Config, active),
+ wait_for_master(Config),
+ #message{from = Peer, thread = <<"1">>,
+ sub_els = [#chatstate{type = active}]} = recv_message(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("csi_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("csi_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("csi_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("csi_" ++ atom_to_list(T) ++ "_slave")]}.
+
+change_client_state(Config, NewState) ->
+ send(Config, #csi{type = NewState}),
+ send_recv(Config, #iq{type = get, to = server_jid(Config),
+ sub_els = [#ping{}]}).
diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl
index 121719cd..46711ad4 100644
--- a/test/ejabberd_SUITE.erl
+++ b/test/ejabberd_SUITE.erl
@@ -173,8 +173,13 @@ end_per_group(ldap, _Config) ->
ok;
end_per_group(extauth, _Config) ->
ok;
-end_per_group(riak, _Config) ->
- ok;
+end_per_group(riak, Config) ->
+ case ejabberd_riak:is_connected() of
+ true ->
+ clear_riak_tables(Config);
+ false ->
+ Config
+ end;
end_per_group(component, _Config) ->
ok;
end_per_group(s2s, _Config) ->
@@ -216,6 +221,8 @@ init_per_testcase(TestCase, OrigConfig) ->
IsCarbons = lists:prefix("carbons_", Test),
IsReplaced = lists:prefix("replaced_", Test),
User = if IsReplaced -> <<"test_single!#$%^*()`~+-;_=[]{}|\\">>;
+ IsCarbons and not (IsMaster or IsSlave) ->
+ <<"test_single!#$%^*()`~+-;_=[]{}|\\">>;
IsMaster or IsCarbons -> <<"test_master!#$%^*()`~+-;_=[]{}|\\">>;
IsSlave -> <<"test_slave!#$%^*()`~+-;_=[]{}|\\">>;
true -> <<"test_single!#$%^*()`~+-;_=[]{}|\\">>
@@ -344,46 +351,12 @@ no_db_tests() ->
s2s_optional,
s2s_required,
s2s_required_trusted]},
- {sm, [sequence],
- [sm,
- sm_resume,
- sm_resume_failed]},
+ sm_tests:single_cases(),
muc_tests:single_cases(),
muc_tests:master_slave_cases(),
- {test_proxy65, [parallel],
- [proxy65_master, proxy65_slave]},
- {replaced, [parallel],
- [replaced_master, replaced_slave]}].
-
-pubsub_single_tests() ->
- {pubsub_single, [sequence],
- [test_pubsub_features,
- test_pubsub_create,
- test_pubsub_configure,
- test_pubsub_delete,
- test_pubsub_get_affiliations,
- test_pubsub_get_subscriptions,
- test_pubsub_create_instant,
- test_pubsub_default,
- test_pubsub_create_configure,
- test_pubsub_publish,
- test_pubsub_auto_create,
- test_pubsub_get_items,
- test_pubsub_delete_item,
- test_pubsub_purge,
- test_pubsub_subscribe,
- test_pubsub_unsubscribe]}.
-
-pubsub_multiple_tests() ->
- {pubsub_multiple, [sequence],
- [{pubsub_publish, [parallel],
- [pubsub_publish_master, pubsub_publish_slave]},
- {pubsub_subscriptions, [parallel],
- [pubsub_subscriptions_master, pubsub_subscriptions_slave]},
- {pubsub_affiliations, [parallel],
- [pubsub_affiliations_master, pubsub_affiliations_slave]},
- {pubsub_authorize, [parallel],
- [pubsub_authorize_master, pubsub_authorize_slave]}]}.
+ proxy65_tests:single_cases(),
+ proxy65_tests:master_slave_cases(),
+ replaced_tests:master_slave_cases()].
db_tests(riak) ->
%% No support for mod_pubsub
@@ -397,18 +370,16 @@ db_tests(riak) ->
roster_tests:single_cases(),
private,
privacy_tests:single_cases(),
- vcard,
+ vcard_tests:single_cases(),
muc_tests:single_cases(),
- offline_tests:master_slave_cases(),
+ offline_tests:single_cases(),
test_unregister]},
muc_tests:master_slave_cases(),
privacy_tests:master_slave_cases(),
roster_tests:master_slave_cases(),
offline_tests:master_slave_cases(),
- {test_announce, [sequence],
- [announce_master, announce_slave]},
- {test_vcard_xupdate, [parallel],
- [vcard_xupdate_master, vcard_xupdate_slave]}];
+ vcard_tests:master_slave_cases(),
+ announce_tests:master_slave_cases()];
db_tests(DB) when DB == mnesia; DB == redis ->
[{single_user, [sequence],
[test_register,
@@ -420,32 +391,26 @@ db_tests(DB) when DB == mnesia; DB == redis ->
roster_tests:single_cases(),
private,
privacy_tests:single_cases(),
- vcard,
- pubsub_single_tests(),
+ vcard_tests:single_cases(),
+ pubsub_tests:single_cases(),
muc_tests:single_cases(),
offline_tests:single_cases(),
+ mam_tests:single_cases(),
+ mix_tests:single_cases(),
+ carbons_tests:single_cases(),
+ csi_tests:single_cases(),
test_unregister]},
muc_tests:master_slave_cases(),
privacy_tests:master_slave_cases(),
- pubsub_multiple_tests(),
+ pubsub_tests:master_slave_cases(),
roster_tests:master_slave_cases(),
offline_tests:master_slave_cases(),
- {test_mix, [parallel],
- [mix_master, mix_slave]},
- {test_old_mam, [parallel],
- [mam_old_master, mam_old_slave]},
- {test_new_mam, [parallel],
- [mam_new_master, mam_new_slave]},
- {test_carbons, [parallel],
- [carbons_master, carbons_slave]},
- {test_client_state, [parallel],
- [client_state_master, client_state_slave]},
- {test_muc_mam, [parallel],
- [muc_mam_master, muc_mam_slave]},
- {test_announce, [sequence],
- [announce_master, announce_slave]},
- {test_vcard_xupdate, [parallel],
- [vcard_xupdate_master, vcard_xupdate_slave]}];
+ mam_tests:master_slave_cases(),
+ mix_tests:master_slave_cases(),
+ vcard_tests:master_slave_cases(),
+ announce_tests:master_slave_cases(),
+ carbons_tests:master_slave_cases(),
+ csi_tests:master_slave_cases()];
db_tests(_) ->
%% No support for carboncopy
[{single_user, [sequence],
@@ -458,28 +423,22 @@ db_tests(_) ->
roster_tests:single_cases(),
private,
privacy_tests:single_cases(),
- vcard,
- pubsub_single_tests(),
+ vcard_tests:single_cases(),
+ pubsub_tests:single_cases(),
muc_tests:single_cases(),
offline_tests:single_cases(),
+ mam_tests:single_cases(),
+ mix_tests:single_cases(),
test_unregister]},
muc_tests:master_slave_cases(),
privacy_tests:master_slave_cases(),
- pubsub_multiple_tests(),
+ pubsub_tests:master_slave_cases(),
roster_tests:master_slave_cases(),
offline_tests:master_slave_cases(),
- {test_mix, [parallel],
- [mix_master, mix_slave]},
- {test_old_mam, [parallel],
- [mam_old_master, mam_old_slave]},
- {test_new_mam, [parallel],
- [mam_new_master, mam_new_slave]},
- {test_muc_mam, [parallel],
- [muc_mam_master, muc_mam_slave]},
- {test_announce, [sequence],
- [announce_master, announce_slave]},
- {test_vcard_xupdate, [parallel],
- [vcard_xupdate_master, vcard_xupdate_slave]}].
+ mam_tests:master_slave_cases(),
+ mix_tests:master_slave_cases(),
+ vcard_tests:master_slave_cases(),
+ announce_tests:master_slave_cases()].
ldap_tests() ->
[{ldap_tests, [sequence],
@@ -839,27 +798,6 @@ test_bind(Config) ->
test_open_session(Config) ->
disconnect(open_session(Config, true)).
-roster_feature_enabled(Config) ->
- roster_tests:feature_enabled(Config).
-roster_iq_set_many_items(Config) ->
- roster_tests:iq_set_many_items(Config).
-roster_iq_set_duplicated_groups(Config) ->
- roster_tests:iq_set_duplicated_groups(Config).
-roster_iq_set_ask(Config) ->
- roster_tests:iq_set_ask(Config).
-roster_iq_get_item(Config) ->
- roster_tests:iq_get_item(Config).
-roster_iq_unexpected_element(Config) ->
- roster_tests:iq_unexpected_element(Config).
-roster_set_item(Config) ->
- roster_tests:set_item(Config).
-roster_version(Config) ->
- roster_tests:version(Config).
-roster_subscribe_master(Config) ->
- roster_tests:subscribe_master(Config).
-roster_subscribe_slave(Config) ->
- roster_tests:subscribe_slave(Config).
-
codec_failure(Config) ->
JID = my_jid(Config),
#iq{type = error} =
@@ -969,74 +907,6 @@ disco(Config) ->
end, Items),
disconnect(Config).
-%% replaced_master(Config0) ->
-%% Config = bind(Config0),
-%% wait_for_slave(Config),
-%% ?recv1(#stream_error{reason = conflict}),
-%% ?recv1({xmlstreamend, <<"stream:stream">>}),
-%% close_socket(Config).
-
-%% replaced_slave(Config0) ->
-%% wait_for_master(Config0),
-%% Config = bind(Config0),
-%% disconnect(Config).
-
-replaced_master(Config) ->
- disconnect(Config).
-
-replaced_slave(Config) ->
- disconnect(Config).
-
-sm(Config) ->
- Server = ?config(server, Config),
- ServerJID = jid:make(<<"">>, Server, <<"">>),
- %% Send messages of type 'headline' so the server discards them silently
- Msg = #message{to = ServerJID, type = headline,
- body = [#text{data = <<"body">>}]},
- true = ?config(sm, Config),
- %% Enable the session management with resumption enabled
- send(Config, #sm_enable{resume = true, xmlns = ?NS_STREAM_MGMT_3}),
- #sm_enabled{id = ID, resume = true} = recv(Config),
- %% Initial request; 'h' should be 0.
- send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}),
- ?recv1(#sm_a{h = 0}),
- %% sending two messages and requesting again; 'h' should be 3.
- send(Config, Msg),
- send(Config, Msg),
- send(Config, Msg),
- send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}),
- ?recv1(#sm_a{h = 3}),
- close_socket(Config),
- {save_config, set_opt(sm_previd, ID, Config)}.
-
-sm_resume(Config) ->
- {sm, SMConfig} = ?config(saved_config, Config),
- ID = ?config(sm_previd, SMConfig),
- Server = ?config(server, Config),
- ServerJID = jid:make(<<"">>, Server, <<"">>),
- MyJID = my_jid(Config),
- Txt = #text{data = <<"body">>},
- Msg = #message{from = ServerJID, to = MyJID, body = [Txt]},
- %% Route message. The message should be queued by the C2S process.
- ejabberd_router:route(ServerJID, MyJID, Msg),
- send(Config, #sm_resume{previd = ID, h = 0, xmlns = ?NS_STREAM_MGMT_3}),
- ?recv1(#sm_resumed{previd = ID, h = 3}),
- #message{from = ServerJID, to = MyJID, body = [Txt]} = recv_message(Config),
- ?recv1(#sm_r{}),
- send(Config, #sm_a{h = 1, xmlns = ?NS_STREAM_MGMT_3}),
- %% Send another stanza to increment the server's 'h' for sm_resume_failed.
- send(Config, #presence{to = ServerJID}),
- close_socket(Config),
- {save_config, set_opt(sm_previd, ID, Config)}.
-
-sm_resume_failed(Config) ->
- {sm_resume, SMConfig} = ?config(saved_config, Config),
- ID = ?config(sm_previd, SMConfig),
- ct:sleep(5000), % Wait for session to time out.
- send(Config, #sm_resume{previd = ID, h = 1, xmlns = ?NS_STREAM_MGMT_3}),
- ?recv1(#sm_failed{reason = 'item-not-found', h = 4}),
- disconnect(Config).
-
private(Config) ->
Conference = #bookmark_conference{name = <<"Some name">>,
autojoin = true,
@@ -1071,137 +941,6 @@ last(Config) ->
to = server_jid(Config)}),
disconnect(Config).
-privacy_feature_enabled(Config) ->
- privacy_tests:feature_enabled(Config).
-privacy_set_get_list(Config) ->
- privacy_tests:set_get_list(Config).
-privacy_get_list_non_existent(Config) ->
- privacy_tests:get_list_non_existent(Config).
-privacy_set_default(Config) ->
- privacy_tests:set_default(Config).
-privacy_del_default(Config) ->
- privacy_tests:del_default(Config).
-privacy_set_default_non_existent(Config) ->
- privacy_tests:set_default_non_existent(Config).
-privacy_set_active(Config) ->
- privacy_tests:set_active(Config).
-privacy_del_active(Config) ->
- privacy_tests:del_active(Config).
-privacy_set_active_non_existent(Config) ->
- privacy_tests:set_active_non_existent(Config).
-privacy_remove_list(Config) ->
- privacy_tests:remove_list(Config).
-privacy_remove_active_list(Config) ->
- privacy_tests:remove_active_list(Config).
-privacy_remove_default_list(Config) ->
- privacy_tests:remove_default_list(Config).
-privacy_remove_list_non_existent(Config) ->
- privacy_tests:remove_list_non_existent(Config).
-privacy_allow_local_server(Config) ->
- privacy_tests:allow_local_server(Config).
-privacy_malformed_iq_query(Config) ->
- privacy_tests:malformed_iq_query(Config).
-privacy_malformed_get(Config) ->
- privacy_tests:malformed_get(Config).
-privacy_malformed_set(Config) ->
- privacy_tests:malformed_set(Config).
-privacy_malformed_type_value(Config) ->
- privacy_tests:malformed_type_value(Config).
-privacy_set_get_block(Config) ->
- privacy_tests:set_get_block(Config).
-
-privacy_deny_bare_jid_master(Config) ->
- privacy_tests:deny_bare_jid_master(Config).
-privacy_deny_bare_jid_slave(Config) ->
- privacy_tests:deny_bare_jid_slave(Config).
-privacy_deny_full_jid_master(Config) ->
- privacy_tests:deny_full_jid_master(Config).
-privacy_deny_full_jid_slave(Config) ->
- privacy_tests:deny_full_jid_slave(Config).
-privacy_deny_server_jid_master(Config) ->
- privacy_tests:deny_server_jid_master(Config).
-privacy_deny_server_jid_slave(Config) ->
- privacy_tests:deny_server_jid_slave(Config).
-privacy_deny_group_master(Config) ->
- privacy_tests:deny_group_master(Config).
-privacy_deny_group_slave(Config) ->
- privacy_tests:deny_group_slave(Config).
-privacy_deny_sub_both_master(Config) ->
- privacy_tests:deny_sub_both_master(Config).
-privacy_deny_sub_both_slave(Config) ->
- privacy_tests:deny_sub_both_slave(Config).
-privacy_deny_sub_from_master(Config) ->
- privacy_tests:deny_sub_from_master(Config).
-privacy_deny_sub_from_slave(Config) ->
- privacy_tests:deny_sub_from_slave(Config).
-privacy_deny_sub_to_master(Config) ->
- privacy_tests:deny_sub_to_master(Config).
-privacy_deny_sub_to_slave(Config) ->
- privacy_tests:deny_sub_to_slave(Config).
-privacy_deny_sub_none_master(Config) ->
- privacy_tests:deny_sub_none_master(Config).
-privacy_deny_sub_none_slave(Config) ->
- privacy_tests:deny_sub_none_slave(Config).
-privacy_deny_all_master(Config) ->
- privacy_tests:deny_all_master(Config).
-privacy_deny_all_slave(Config) ->
- privacy_tests:deny_all_slave(Config).
-privacy_deny_offline_master(Config) ->
- privacy_tests:deny_offline_master(Config).
-privacy_deny_offline_slave(Config) ->
- privacy_tests:deny_offline_slave(Config).
-privacy_block_master(Config) ->
- privacy_tests:block_master(Config).
-privacy_block_slave(Config) ->
- privacy_tests:block_slave(Config).
-privacy_unblock_master(Config) ->
- privacy_tests:unblock_master(Config).
-privacy_unblock_slave(Config) ->
- privacy_tests:unblock_slave(Config).
-privacy_unblock_all_master(Config) ->
- privacy_tests:unblock_all_master(Config).
-privacy_unblock_all_slave(Config) ->
- privacy_tests:unblock_all_slave(Config).
-
-vcard(Config) ->
- true = is_feature_advertised(Config, ?NS_VCARD),
- VCard =
- #vcard_temp{fn = <<"Peter Saint-Andre">>,
- n = #vcard_name{family = <<"Saint-Andre">>,
- given = <<"Peter">>},
- nickname = <<"stpeter">>,
- bday = <<"1966-08-06">>,
- adr = [#vcard_adr{work = true,
- extadd = <<"Suite 600">>,
- street = <<"1899 Wynkoop Street">>,
- locality = <<"Denver">>,
- region = <<"CO">>,
- pcode = <<"80202">>,
- ctry = <<"USA">>},
- #vcard_adr{home = true,
- locality = <<"Denver">>,
- region = <<"CO">>,
- pcode = <<"80209">>,
- ctry = <<"USA">>}],
- tel = [#vcard_tel{work = true,voice = true,
- number = <<"303-308-3282">>},
- #vcard_tel{home = true,voice = true,
- number = <<"303-555-1212">>}],
- email = [#vcard_email{internet = true,pref = true,
- userid = <<"stpeter@jabber.org">>}],
- jabberid = <<"stpeter@jabber.org">>,
- title = <<"Executive Director">>,role = <<"Patron Saint">>,
- org = #vcard_org{name = <<"XMPP Standards Foundation">>},
- url = <<"http://www.xmpp.org/xsf/people/stpeter.shtml">>,
- desc = <<"More information about me is located on my "
- "personal website: http://www.saint-andre.com/">>},
- #iq{type = result, sub_els = []} =
- send_recv(Config, #iq{type = set, sub_els = [VCard]}),
- %% TODO: check if VCard == VCard1.
- #iq{type = result, sub_els = [_VCard1]} =
- send_recv(Config, #iq{type = get, sub_els = [#vcard_temp{}]}),
- disconnect(Config).
-
vcard_get(Config) ->
true = is_feature_advertised(Config, ?NS_VCARD),
%% TODO: check if VCard corresponds to LDIF data from ejabberd.ldif
@@ -1216,40 +955,6 @@ ldap_shared_roster_get(Config) ->
send_recv(Config, #iq{type = get, sub_els = [#roster_query{}]}),
disconnect(Config).
-vcard_xupdate_master(Config) ->
- Img = <<137, "PNG\r\n", 26, $\n>>,
- ImgHash = p1_sha:sha(Img),
- MyJID = my_jid(Config),
- Peer = ?config(slave, Config),
- wait_for_slave(Config),
- #presence{from = MyJID, type = available} = send_recv(Config, #presence{}),
- #presence{from = Peer, type = available} = recv_presence(Config),
- VCard = #vcard_temp{photo = #vcard_photo{type = <<"image/png">>, binval = Img}},
- #iq{type = result, sub_els = []} =
- send_recv(Config, #iq{type = set, sub_els = [VCard]}),
- #presence{from = MyJID, type = available,
- sub_els = [#vcard_xupdate{hash = ImgHash}]} = recv_presence(Config),
- #iq{type = result, sub_els = []} =
- send_recv(Config, #iq{type = set, sub_els = [#vcard_temp{}]}),
- ?recv2(#presence{from = MyJID, type = available,
- sub_els = [#vcard_xupdate{hash = undefined}]},
- #presence{from = Peer, type = unavailable}),
- disconnect(Config).
-
-vcard_xupdate_slave(Config) ->
- Img = <<137, "PNG\r\n", 26, $\n>>,
- ImgHash = p1_sha:sha(Img),
- MyJID = my_jid(Config),
- Peer = ?config(master, Config),
- #presence{from = MyJID, type = available} = send_recv(Config, #presence{}),
- wait_for_master(Config),
- #presence{from = Peer, type = available} = recv_presence(Config),
- #presence{from = Peer, type = available,
- sub_els = [#vcard_xupdate{hash = ImgHash}]} = recv_presence(Config),
- #presence{from = Peer, type = available,
- sub_els = [#vcard_xupdate{hash = undefined}]} = recv_presence(Config),
- disconnect(Config).
-
stats(Config) ->
#iq{type = result, sub_els = [#stats{list = Stats}]} =
send_recv(Config, #iq{type = get, sub_els = [#stats{}],
@@ -1263,1637 +968,9 @@ stats(Config) ->
end, Stats),
disconnect(Config).
-test_pubsub_features(Config) ->
- PJID = pubsub_jid(Config),
- AllFeatures = sets:from_list(get_features(Config, PJID)),
- NeededFeatures = sets:from_list(
- [?NS_PUBSUB,
- ?PUBSUB("access-open"),
- ?PUBSUB("access-authorize"),
- ?PUBSUB("create-nodes"),
- ?PUBSUB("instant-nodes"),
- ?PUBSUB("config-node"),
- ?PUBSUB("retrieve-default"),
- ?PUBSUB("create-and-configure"),
- ?PUBSUB("publish"),
- ?PUBSUB("auto-create"),
- ?PUBSUB("retrieve-items"),
- ?PUBSUB("delete-items"),
- ?PUBSUB("subscribe"),
- ?PUBSUB("retrieve-affiliations"),
- ?PUBSUB("modify-affiliations"),
- ?PUBSUB("retrieve-subscriptions"),
- ?PUBSUB("manage-subscriptions"),
- ?PUBSUB("purge-nodes"),
- ?PUBSUB("delete-nodes")]),
- true = sets:is_subset(NeededFeatures, AllFeatures),
- disconnect(Config).
-
-test_pubsub_create(Config) ->
- Node = ?config(pubsub_node, Config),
- Node = create_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_create_instant(Config) ->
- Node = create_node(Config, <<>>),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_configure(Config) ->
- Node = ?config(pubsub_node, Config),
- NodeTitle = ?config(pubsub_node_title, Config),
- NodeConfig = get_node_config(Config, Node),
- MyNodeConfig = set_opts(NodeConfig,
- [{title, NodeTitle}]),
- set_node_config(Config, Node, MyNodeConfig),
- NewNodeConfig = get_node_config(Config, Node),
- NodeTitle = proplists:get_value(title, NewNodeConfig),
- disconnect(Config).
-
-test_pubsub_default(Config) ->
- get_default_node_config(Config),
- disconnect(Config).
-
-test_pubsub_create_configure(Config) ->
- NodeTitle = ?config(pubsub_node_title, Config),
- DefaultNodeConfig = get_default_node_config(Config),
- CustomNodeConfig = set_opts(DefaultNodeConfig,
- [{title, NodeTitle}]),
- Node = create_node(Config, <<>>, CustomNodeConfig),
- NodeConfig = get_node_config(Config, Node),
- NodeTitle = proplists:get_value(title, NodeConfig),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_publish(Config) ->
- Node = create_node(Config, <<>>),
- publish_item(Config, Node),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_auto_create(Config) ->
- Node = randoms:get_string(),
- publish_item(Config, Node),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_get_items(Config) ->
- Node = create_node(Config, <<>>),
- ItemsIn = [publish_item(Config, Node) || _ <- lists:seq(1, 5)],
- ItemsOut = get_items(Config, Node),
- true = [I || #ps_item{id = I} <- lists:sort(ItemsIn)]
- == [I || #ps_item{id = I} <- lists:sort(ItemsOut)],
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_delete_item(Config) ->
- Node = create_node(Config, <<>>),
- #ps_item{id = I} = publish_item(Config, Node),
- [#ps_item{id = I}] = get_items(Config, Node),
- delete_item(Config, Node, I),
- [] = get_items(Config, Node),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_subscribe(Config) ->
- Node = create_node(Config, <<>>),
- #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
- [#ps_subscription{node = Node}] = get_subscriptions(Config),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_unsubscribe(Config) ->
- Node = create_node(Config, <<>>),
- subscribe_node(Config, Node),
- [#ps_subscription{node = Node}] = get_subscriptions(Config),
- unsubscribe_node(Config, Node),
- [] = get_subscriptions(Config),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_get_affiliations(Config) ->
- Nodes = lists:sort([create_node(Config, <<>>) || _ <- lists:seq(1, 5)]),
- Affs = get_affiliations(Config),
- Nodes = lists:sort([Node || #ps_affiliation{node = Node,
- type = owner} <- Affs]),
- [delete_node(Config, Node) || Node <- Nodes],
- disconnect(Config).
-
-test_pubsub_get_subscriptions(Config) ->
- Nodes = lists:sort([create_node(Config, <<>>) || _ <- lists:seq(1, 5)]),
- [subscribe_node(Config, Node) || Node <- Nodes],
- Subs = get_subscriptions(Config),
- Nodes = lists:sort([Node || #ps_subscription{node = Node} <- Subs]),
- [delete_node(Config, Node) || Node <- Nodes],
- disconnect(Config).
-
-test_pubsub_purge(Config) ->
- Node = create_node(Config, <<>>),
- ItemsIn = [publish_item(Config, Node) || _ <- lists:seq(1, 5)],
- ItemsOut = get_items(Config, Node),
- true = [I || #ps_item{id = I} <- lists:sort(ItemsIn)]
- == [I || #ps_item{id = I} <- lists:sort(ItemsOut)],
- purge_node(Config, Node),
- [] = get_items(Config, Node),
- delete_node(Config, Node),
- disconnect(Config).
-
-test_pubsub_delete(Config) ->
- Node = ?config(pubsub_node, Config),
- delete_node(Config, Node),
- disconnect(Config).
-
-pubsub_publish_master(Config) ->
- Node = create_node(Config, <<>>),
- put_event(Config, Node),
- wait_for_slave(Config),
- #ps_item{id = ID} = publish_item(Config, Node),
- #ps_item{id = ID} = get_event(Config),
- delete_node(Config, Node),
- disconnect(Config).
-
-pubsub_publish_slave(Config) ->
- Node = get_event(Config),
- subscribe_node(Config, Node),
- wait_for_master(Config),
- #message{
- sub_els =
- [#ps_event{
- items = #ps_items{node = Node,
- items = [Item]}}]} = recv_message(Config),
- put_event(Config, Item),
- disconnect(Config).
-
-pubsub_subscriptions_master(Config) ->
- Peer = ?config(slave, Config),
- Node = ?config(pubsub_node, Config),
- Node = create_node(Config, Node),
- [] = get_subscriptions(Config, Node),
- wait_for_slave(Config),
- lists:foreach(
- fun(Type) ->
- ok = set_subscriptions(Config, Node, [{Peer, Type}]),
- #ps_item{} = publish_item(Config, Node),
- case get_subscriptions(Config, Node) of
- [] when Type == none; Type == pending ->
- ok;
- [#ps_subscription{jid = Peer, type = Type}] ->
- ok
- end
- end, [subscribed, unconfigured, pending, none]),
- delete_node(Config, Node),
- disconnect(Config).
-
-pubsub_subscriptions_slave(Config) ->
- wait_for_master(Config),
- MyJID = my_jid(Config),
- Node = ?config(pubsub_node, Config),
- lists:foreach(
- fun(subscribed = Type) ->
- ?recv2(#message{
- sub_els =
- [#ps_event{
- subscription = #ps_subscription{
- node = Node,
- jid = MyJID,
- type = Type}}]},
- #message{sub_els = [#ps_event{}]});
- (Type) ->
- #message{
- sub_els =
- [#ps_event{
- subscription = #ps_subscription{
- node = Node,
- jid = MyJID,
- type = Type}}]} =
- recv_message(Config)
- end, [subscribed, unconfigured, pending, none]),
- disconnect(Config).
-
-pubsub_affiliations_master(Config) ->
- Peer = ?config(slave, Config),
- BarePeer = jid:remove_resource(Peer),
- lists:foreach(
- fun(Aff) ->
- Node = <<(atom_to_binary(Aff, utf8))/binary,
- $-, (randoms:get_string())/binary>>,
- create_node(Config, Node, default_node_config(Config)),
- #ps_item{id = I} = publish_item(Config, Node),
- ok = set_affiliations(Config, Node, [{Peer, Aff}]),
- Affs = get_affiliations(Config, Node),
- case lists:keyfind(BarePeer, #ps_affiliation.jid, Affs) of
- false when Aff == none ->
- ok;
- #ps_affiliation{type = Aff} ->
- ok
- end,
- put_event(Config, {Aff, Node, I}),
- wait_for_slave(Config),
- delete_node(Config, Node)
- end, [outcast, none, member, publish_only, publisher, owner]),
- put_event(Config, disconnect),
- disconnect(Config).
-
-pubsub_affiliations_slave(Config) ->
- pubsub_affiliations_slave(Config, get_event(Config)).
-
-pubsub_affiliations_slave(Config, {outcast, Node, ItemID}) ->
- #stanza_error{reason = 'forbidden'} = subscribe_node(Config, Node),
- #stanza_error{} = unsubscribe_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_items(Config, Node),
- #stanza_error{reason = 'forbidden'} = publish_item(Config, Node),
- #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
- #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_node_config(Config, Node, default_node_config(Config)),
- #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
- #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_affiliations(Config, Node, [{?config(master, Config), outcast},
- {my_jid(Config), owner}]),
- #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
- wait_for_master(Config),
- pubsub_affiliations_slave(Config, get_event(Config));
-pubsub_affiliations_slave(Config, {none, Node, ItemID}) ->
- #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
- ok = unsubscribe_node(Config, Node),
- %% This violates the affiliation char from section 4.1
- [_|_] = get_items(Config, Node),
- #stanza_error{reason = 'forbidden'} = publish_item(Config, Node),
- #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
- #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_node_config(Config, Node, default_node_config(Config)),
- #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
- #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_affiliations(Config, Node, [{?config(master, Config), outcast},
- {my_jid(Config), owner}]),
- #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
- wait_for_master(Config),
- pubsub_affiliations_slave(Config, get_event(Config));
-pubsub_affiliations_slave(Config, {member, Node, ItemID}) ->
- #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
- ok = unsubscribe_node(Config, Node),
- [_|_] = get_items(Config, Node),
- #stanza_error{reason = 'forbidden'} = publish_item(Config, Node),
- #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
- #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_node_config(Config, Node, default_node_config(Config)),
- #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
- #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_affiliations(Config, Node, [{?config(master, Config), outcast},
- {my_jid(Config), owner}]),
- #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
- wait_for_master(Config),
- pubsub_affiliations_slave(Config, get_event(Config));
-pubsub_affiliations_slave(Config, {publish_only, Node, ItemID}) ->
- #stanza_error{reason = 'forbidden'} = subscribe_node(Config, Node),
- #stanza_error{} = unsubscribe_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_items(Config, Node),
- #ps_item{id = MyItemID} = publish_item(Config, Node),
- %% BUG: This should be fixed
- %% ?match(ok, delete_item(Config, Node, MyItemID)),
- #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
- #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_node_config(Config, Node, default_node_config(Config)),
- #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
- #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_affiliations(Config, Node, [{?config(master, Config), outcast},
- {my_jid(Config), owner}]),
- #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
- wait_for_master(Config),
- pubsub_affiliations_slave(Config, get_event(Config));
-pubsub_affiliations_slave(Config, {publisher, Node, ItemID}) ->
- #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
- ok = unsubscribe_node(Config, Node),
- [_|_] = get_items(Config, Node),
- #ps_item{id = MyItemID} = publish_item(Config, Node),
- ok = delete_item(Config, Node, MyItemID),
- %% BUG: this should be fixed
- %% #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
- #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
- #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_node_config(Config, Node, default_node_config(Config)),
- #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
- #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
- #stanza_error{reason = 'forbidden'} =
- set_affiliations(Config, Node, [{?config(master, Config), outcast},
- {my_jid(Config), owner}]),
- #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
- wait_for_master(Config),
- pubsub_affiliations_slave(Config, get_event(Config));
-pubsub_affiliations_slave(Config, {owner, Node, ItemID}) ->
- MyJID = my_jid(Config),
- Peer = ?config(master, Config),
- #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
- ok = unsubscribe_node(Config, Node),
- [_|_] = get_items(Config, Node),
- #ps_item{id = MyItemID} = publish_item(Config, Node),
- ok = delete_item(Config, Node, MyItemID),
- ok = delete_item(Config, Node, ItemID),
- ok = purge_node(Config, Node),
- [_|_] = get_node_config(Config, Node),
- ok = set_node_config(Config, Node, default_node_config(Config)),
- ok = set_subscriptions(Config, Node, []),
- [] = get_subscriptions(Config, Node),
- ok = set_affiliations(Config, Node, [{Peer, outcast}, {MyJID, owner}]),
- [_, _] = get_affiliations(Config, Node),
- ok = delete_node(Config, Node),
- wait_for_master(Config),
- pubsub_affiliations_slave(Config, get_event(Config));
-pubsub_affiliations_slave(Config, disconnect) ->
- disconnect(Config).
-
-pubsub_authorize_master(Config) ->
- send(Config, #presence{}),
- #presence{} = recv_presence(Config),
- Peer = ?config(slave, Config),
- PJID = pubsub_jid(Config),
- NodeConfig = set_opts(default_node_config(Config),
- [{access_model, authorize}]),
- Node = ?config(pubsub_node, Config),
- Node = create_node(Config, Node, NodeConfig),
- wait_for_slave(Config),
- #message{sub_els = [#xdata{fields = F1}]} = recv_message(Config),
- C1 = pubsub_subscribe_authorization:decode(F1),
- Node = proplists:get_value(node, C1),
- Peer = proplists:get_value(subscriber_jid, C1),
- %% Deny it at first
- Deny = #xdata{type = submit,
- fields = pubsub_subscribe_authorization:encode(
- [{node, Node},
- {subscriber_jid, Peer},
- {allow, false}])},
- send(Config, #message{to = PJID, sub_els = [Deny]}),
- %% We should not have any subscriptions
- [] = get_subscriptions(Config, Node),
- wait_for_slave(Config),
- #message{sub_els = [#xdata{fields = F2}]} = recv_message(Config),
- C2 = pubsub_subscribe_authorization:decode(F2),
- Node = proplists:get_value(node, C2),
- Peer = proplists:get_value(subscriber_jid, C2),
- %% Now we accept is as the peer is very insisting ;)
- Approve = #xdata{type = submit,
- fields = pubsub_subscribe_authorization:encode(
- [{node, Node},
- {subscriber_jid, Peer},
- {allow, true}])},
- send(Config, #message{to = PJID, sub_els = [Approve]}),
- wait_for_slave(Config),
- delete_node(Config, Node),
- disconnect(Config).
-
-pubsub_authorize_slave(Config) ->
- Node = ?config(pubsub_node, Config),
- MyJID = my_jid(Config),
- wait_for_master(Config),
- #ps_subscription{type = pending} = subscribe_node(Config, Node),
- %% We're denied at first
- #message{
- sub_els =
- [#ps_event{
- subscription = #ps_subscription{type = none,
- jid = MyJID}}]} =
- recv_message(Config),
- wait_for_master(Config),
- #ps_subscription{type = pending} = subscribe_node(Config, Node),
- %% Now much better!
- #message{
- sub_els =
- [#ps_event{
- subscription = #ps_subscription{type = subscribed,
- jid = MyJID}}]} =
- recv_message(Config),
- wait_for_master(Config),
- disconnect(Config).
-
-create_node(Config, Node) ->
- create_node(Config, Node, undefined).
-
-create_node(Config, Node, Options) ->
- PJID = pubsub_jid(Config),
- NodeConfig = if is_list(Options) ->
- #xdata{type = submit,
- fields = pubsub_node_config:encode(Options)};
- true ->
- undefined
- end,
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub{create = Node,
- configure = {<<>>, NodeConfig}}]}) of
- #iq{type = result, sub_els = [#pubsub{create = NewNode}]} ->
- NewNode;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-delete_node(Config, Node) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub_owner{delete = {Node, <<>>}}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-purge_node(Config, Node) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub_owner{purge = Node}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_default_node_config(Config) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub_owner{default = {<<>>, undefined}}]}) of
- #iq{type = result,
- sub_els = [#pubsub_owner{default = {<<>>, NodeConfig}}]} ->
- pubsub_node_config:decode(NodeConfig#xdata.fields);
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_node_config(Config, Node) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub_owner{configure = {Node, undefined}}]}) of
- #iq{type = result,
- sub_els = [#pubsub_owner{configure = {Node, NodeConfig}}]} ->
- pubsub_node_config:decode(NodeConfig#xdata.fields);
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-set_node_config(Config, Node, Options) ->
- PJID = pubsub_jid(Config),
- NodeConfig = #xdata{type = submit,
- fields = pubsub_node_config:encode(Options)},
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub_owner{configure =
- {Node, NodeConfig}}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-publish_item(Config, Node) ->
- PJID = pubsub_jid(Config),
- ItemID = randoms:get_string(),
- Item = #ps_item{id = ItemID, xml_els = [xmpp:encode(#presence{id = ItemID})]},
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub{publish = #ps_publish{
- node = Node,
- items = [Item]}}]}) of
- #iq{type = result,
- sub_els = [#pubsub{publish = #ps_publish{
- node = Node,
- items = [#ps_item{id = ItemID}]}}]} ->
- Item;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_items(Config, Node) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub{items = #ps_items{node = Node}}]}) of
- #iq{type = result,
- sub_els = [#pubsub{items = #ps_items{node = Node, items = Items}}]} ->
- Items;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-delete_item(Config, Node, I) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub{retract =
- #ps_retract{
- node = Node,
- items = [#ps_item{id = I}]}}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-subscribe_node(Config, Node) ->
- PJID = pubsub_jid(Config),
- MyJID = my_jid(Config),
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub{subscribe = #ps_subscribe{
- node = Node,
- jid = MyJID}}]}) of
- #iq{type = result,
- sub_els = [#pubsub{
- subscription = #ps_subscription{
- node = Node,
- jid = MyJID} = Sub}]} ->
- Sub;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-unsubscribe_node(Config, Node) ->
- PJID = pubsub_jid(Config),
- MyJID = my_jid(Config),
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub{
- unsubscribe = #ps_unsubscribe{
- node = Node,
- jid = MyJID}}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_affiliations(Config) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub{affiliations = {<<>>, []}}]}) of
- #iq{type = result,
- sub_els = [#pubsub{affiliations = {<<>>, Affs}}]} ->
- Affs;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_affiliations(Config, Node) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub_owner{affiliations = {Node, []}}]}) of
- #iq{type = result,
- sub_els = [#pubsub_owner{affiliations = {Node, Affs}}]} ->
- Affs;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-set_affiliations(Config, Node, JTs) ->
- PJID = pubsub_jid(Config),
- Affs = [#ps_affiliation{jid = J, type = T} || {J, T} <- JTs],
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub_owner{affiliations =
- {Node, Affs}}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_subscriptions(Config) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub{subscriptions = {<<>>, []}}]}) of
- #iq{type = result, sub_els = [#pubsub{subscriptions = {<<>>, Subs}}]} ->
- Subs;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-get_subscriptions(Config, Node) ->
- PJID = pubsub_jid(Config),
- case send_recv(Config,
- #iq{type = get, to = PJID,
- sub_els = [#pubsub_owner{subscriptions = {Node, []}}]}) of
- #iq{type = result,
- sub_els = [#pubsub_owner{subscriptions = {Node, Subs}}]} ->
- Subs;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-set_subscriptions(Config, Node, JTs) ->
- PJID = pubsub_jid(Config),
- Subs = [#ps_subscription{jid = J, type = T} || {J, T} <- JTs],
- case send_recv(Config,
- #iq{type = set, to = PJID,
- sub_els = [#pubsub_owner{subscriptions =
- {Node, Subs}}]}) of
- #iq{type = result, sub_els = []} ->
- ok;
- #iq{type = error} = IQ ->
- xmpp:get_subtag(IQ, #stanza_error{})
- end.
-
-default_node_config(Config) ->
- [{title, ?config(pubsub_node_title, Config)},
- {notify_delete, false},
- {send_last_published_item, never}].
-
-mix_master(Config) ->
- MIX = mix_jid(Config),
- Room = mix_room_jid(Config),
- MyJID = my_jid(Config),
- MyBareJID = jid:remove_resource(MyJID),
- true = is_feature_advertised(Config, ?NS_MIX_0, MIX),
- #iq{type = result,
- sub_els =
- [#disco_info{
- identities = [#identity{category = <<"conference">>,
- type = <<"text">>}],
- xdata = [#xdata{type = result, fields = XFields}]}]} =
- send_recv(Config, #iq{type = get, to = MIX, sub_els = [#disco_info{}]}),
- true = lists:any(
- fun(#xdata_field{var = <<"FORM_TYPE">>,
- values = [?NS_MIX_SERVICEINFO_0]}) -> true;
- (_) -> false
- end, XFields),
- %% Joining
- Nodes = [?NS_MIX_NODES_MESSAGES, ?NS_MIX_NODES_PRESENCE,
- ?NS_MIX_NODES_PARTICIPANTS, ?NS_MIX_NODES_SUBJECT,
- ?NS_MIX_NODES_CONFIG],
- #iq{type = result,
- sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]} =
- send_recv(Config, #iq{type = set, to = Room,
- sub_els = [#mix_join{subscribe = Nodes}]}),
- #message{from = Room,
- sub_els =
- [#ps_event{
- items = #ps_items{
- node = ?NS_MIX_NODES_PARTICIPANTS,
- items = [#ps_item{
- id = ParticipantID,
- xml_els = [PXML]}]}}]} =
- recv_message(Config),
- #mix_participant{jid = MyBareJID} = xmpp:decode(PXML),
- %% Coming online
- PresenceID = randoms:get_string(),
- Presence = xmpp:encode(#presence{}),
- #iq{type = result,
- sub_els =
- [#pubsub{
- publish = #ps_publish{
- node = ?NS_MIX_NODES_PRESENCE,
- items = [#ps_item{id = PresenceID}]}}]} =
- send_recv(
- Config,
- #iq{type = set, to = Room,
- sub_els =
- [#pubsub{
- publish = #ps_publish{
- node = ?NS_MIX_NODES_PRESENCE,
- items = [#ps_item{
- id = PresenceID,
- xml_els = [Presence]}]}}]}),
- #message{from = Room,
- sub_els =
- [#ps_event{
- items = #ps_items{
- node = ?NS_MIX_NODES_PRESENCE,
- items = [#ps_item{
- id = PresenceID,
- xml_els = [Presence]}]}}]} =
- recv_message(Config),
- %% Coming offline
- send(Config, #presence{type = unavailable, to = Room}),
- %% Receiving presence retract event
- #message{from = Room,
- sub_els = [#ps_event{
- items = #ps_items{
- node = ?NS_MIX_NODES_PRESENCE,
- retract = PresenceID}}]} =
- recv_message(Config),
- %% Leaving
- #iq{type = result, sub_els = []} =
- send_recv(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}),
- #message{from = Room,
- sub_els =
- [#ps_event{
- items = #ps_items{
- node = ?NS_MIX_NODES_PARTICIPANTS,
- retract = ParticipantID}}]} =
- recv_message(Config),
- put_event(Config, disconnect),
- disconnect(Config).
-
-mix_slave(Config) ->
- disconnect = get_event(Config),
- disconnect(Config).
-
-proxy65_master(Config) ->
- Proxy = proxy_jid(Config),
- MyJID = my_jid(Config),
- Peer = ?config(slave, Config),
- wait_for_slave(Config),
- send(Config, #presence{}),
- #presence{from = MyJID, type = available} = recv_presence(Config),
- true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy),
- #iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} =
- send_recv(
- Config,
- #iq{type = get, sub_els = [#bytestreams{}], to = Proxy}),
- SID = randoms:get_string(),
- Data = crypto:rand_bytes(1024),
- put_event(Config, {StreamHost, SID, Data}),
- Socks5 = socks5_connect(StreamHost, {SID, MyJID, Peer}),
- wait_for_slave(Config),
- #iq{type = result, sub_els = []} =
- send_recv(Config,
- #iq{type = set, to = Proxy,
- sub_els = [#bytestreams{activate = Peer, sid = SID}]}),
- socks5_send(Socks5, Data),
- %%?recv1(#presence{type = unavailable, from = Peer}),
- disconnect(Config).
-
-proxy65_slave(Config) ->
- MyJID = my_jid(Config),
- Peer = ?config(master, Config),
- send(Config, #presence{}),
- #presence{from = MyJID, type = available} = recv_presence(Config),
- wait_for_master(Config),
- {StreamHost, SID, Data} = get_event(Config),
- Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}),
- wait_for_master(Config),
- socks5_recv(Socks5, Data),
- disconnect(Config).
-
-send_messages_to_room(Config, Range) ->
- MyNick = ?config(master_nick, Config),
- Room = muc_room_jid(Config),
- MyNickJID = jid:replace_resource(Room, MyNick),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{from = MyNickJID, id = I,
- type = groupchat,
- body = [Text]} =
- send_recv(Config, #message{to = Room, body = [Text],
- type = groupchat})
- end, Range).
-
-retrieve_messages_from_room_via_mam(Config, Range) ->
- MyNick = ?config(master_nick, Config),
- Room = muc_room_jid(Config),
- MyNickJID = jid:replace_resource(Room, MyNick),
- MyJID = my_jid(Config),
- QID = randoms:get_string(),
- Count = length(Range),
- I = send(Config, #iq{type = set, to = Room,
- sub_els = [#mam_query{xmlns = ?NS_MAM_1, id = QID}]}),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{
- to = MyJID, from = Room,
- sub_els =
- [#mam_result{
- xmlns = ?NS_MAM_1,
- queryid = QID,
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els = [#message{
- from = MyNickJID,
- type = groupchat,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, Range),
- #iq{from = Room, id = I, type = result,
- sub_els = [#mam_fin{xmlns = ?NS_MAM_1,
- id = QID,
- rsm = #rsm_set{count = Count},
- complete = true}]} = recv_iq(Config).
-
-muc_mam_master(Config) ->
- MyNick = ?config(master_nick, Config),
- Room = muc_room_jid(Config),
- MyNickJID = jid:replace_resource(Room, MyNick),
- %% Joining
- ok = muc_tests:muc_join_new(Config),
- %% MAM feature should not be advertised at this point,
- %% because MAM is not enabled so far
- false = is_feature_advertised(Config, ?NS_MAM_1, Room),
- %% Fill in some history
- send_messages_to_room(Config, lists:seq(1, 21)),
- %% We now should be able to retrieve those via MAM, even though
- %% MAM is disabled. However, only last 20 messages should be received.
- retrieve_messages_from_room_via_mam(Config, lists:seq(2, 21)),
- %% Now enable MAM for the conference
- %% Retrieve config first
- #iq{type = result, sub_els = [#muc_owner{config = #xdata{} = RoomCfg}]} =
- send_recv(Config, #iq{type = get, sub_els = [#muc_owner{}],
- to = Room}),
- %% Find the MAM field in the config and enable it
- NewFields = lists:flatmap(
- fun(#xdata_field{var = <<"mam">> = Var}) ->
- [#xdata_field{var = Var, values = [<<"1">>]}];
- (_) ->
- []
- end, RoomCfg#xdata.fields),
- NewRoomCfg = #xdata{type = submit, fields = NewFields},
- #iq{type = result, sub_els = []} =
- send_recv(Config, #iq{type = set, to = Room,
- sub_els = [#muc_owner{config = NewRoomCfg}]}),
- #message{from = Room, type = groupchat,
- sub_els = [#muc_user{status_codes = [104]}]} = recv_message(Config),
- %% Check if MAM has been enabled
- true = is_feature_advertised(Config, ?NS_MAM_1, Room),
- %% We now sending some messages again
- send_messages_to_room(Config, lists:seq(1, 5)),
- %% And retrieve them via MAM again.
- retrieve_messages_from_room_via_mam(Config, lists:seq(1, 5)),
- put_event(Config, disconnect),
- disconnect(Config).
-
-muc_mam_slave(Config) ->
- disconnect = get_event(Config),
- disconnect(Config).
-
-%% OK, I know this is retarded, but I didn't find a better way to
-%% split the test cases into different modules
-muc_service_presence_error(Config) ->
- muc_tests:muc_service_presence_error(Config).
-muc_service_message_error(Config) ->
- muc_tests:muc_service_message_error(Config).
-muc_service_unknown_ns_iq_error(Config) ->
- muc_tests:muc_service_unknown_ns_iq_error(Config).
-muc_service_iq_set_error(Config) ->
- muc_tests:muc_service_iq_set_error(Config).
-muc_service_improper_iq_error(Config) ->
- muc_tests:muc_service_improper_iq_error(Config).
-muc_service_features(Config) ->
- muc_tests:muc_service_features(Config).
-muc_service_disco_info_node_error(Config) ->
- muc_tests:muc_service_disco_info_node_error(Config).
-muc_service_disco_items(Config) ->
- muc_tests:muc_service_disco_items(Config).
-muc_service_vcard(Config) ->
- muc_tests:muc_service_vcard(Config).
-muc_service_unique(Config) ->
- muc_tests:muc_service_unique(Config).
-muc_service_subscriptions(Config) ->
- muc_tests:muc_service_subscriptions(Config).
-muc_configure_non_existent(Config) ->
- muc_tests:muc_configure_non_existent(Config).
-muc_cancel_configure_non_existent(Config) ->
- muc_tests:muc_cancel_configure_non_existent(Config).
-
-muc_register_master(Config) ->
- muc_tests:muc_register_master(Config).
-muc_register_slave(Config) ->
- muc_tests:muc_register_slave(Config).
-muc_join_conflict_master(Config) ->
- muc_tests:muc_join_conflict_master(Config).
-muc_join_conflict_slave(Config) ->
- muc_tests:muc_join_conflict_slave(Config).
-muc_groupchat_msg_master(Config) ->
- muc_tests:muc_groupchat_msg_master(Config).
-muc_groupchat_msg_slave(Config) ->
- muc_tests:muc_groupchat_msg_slave(Config).
-muc_private_msg_master(Config) ->
- muc_tests:muc_private_msg_master(Config).
-muc_private_msg_slave(Config) ->
- muc_tests:muc_private_msg_slave(Config).
-muc_set_subject_master(Config) ->
- muc_tests:muc_set_subject_master(Config).
-muc_set_subject_slave(Config) ->
- muc_tests:muc_set_subject_slave(Config).
-muc_history_master(Config) ->
- muc_tests:muc_history_master(Config).
-muc_history_slave(Config) ->
- muc_tests:muc_history_slave(Config).
-muc_invite_master(Config) ->
- muc_tests:muc_invite_master(Config).
-muc_invite_slave(Config) ->
- muc_tests:muc_invite_slave(Config).
-muc_invite_members_only_master(Config) ->
- muc_tests:muc_invite_members_only_master(Config).
-muc_invite_members_only_slave(Config) ->
- muc_tests:muc_invite_members_only_slave(Config).
-muc_invite_password_protected_master(Config) ->
- muc_tests:muc_invite_password_protected_master(Config).
-muc_invite_password_protected_slave(Config) ->
- muc_tests:muc_invite_password_protected_slave(Config).
-muc_voice_request_master(Config) ->
- muc_tests:muc_voice_request_master(Config).
-muc_voice_request_slave(Config) ->
- muc_tests:muc_voice_request_slave(Config).
-muc_change_role_master(Config) ->
- muc_tests:muc_change_role_master(Config).
-muc_change_role_slave(Config) ->
- muc_tests:muc_change_role_slave(Config).
-muc_kick_master(Config) ->
- muc_tests:muc_kick_master(Config).
-muc_kick_slave(Config) ->
- muc_tests:muc_kick_slave(Config).
-muc_change_affiliation_master(Config) ->
- muc_tests:muc_change_affiliation_master(Config).
-muc_change_affiliation_slave(Config) ->
- muc_tests:muc_change_affiliation_slave(Config).
-muc_destroy_master(Config) ->
- muc_tests:muc_destroy_master(Config).
-muc_destroy_slave(Config) ->
- muc_tests:muc_destroy_slave(Config).
-muc_vcard_master(Config) ->
- muc_tests:muc_vcard_master(Config).
-muc_vcard_slave(Config) ->
- muc_tests:muc_vcard_slave(Config).
-muc_nick_change_master(Config) ->
- muc_tests:muc_nick_change_master(Config).
-muc_nick_change_slave(Config) ->
- muc_tests:muc_nick_change_slave(Config).
-muc_config_title_desc_master(Config) ->
- muc_tests:muc_config_title_desc_master(Config).
-muc_config_title_desc_slave(Config) ->
- muc_tests:muc_config_title_desc_slave(Config).
-muc_config_public_list_master(Config) ->
- muc_tests:muc_config_public_list_master(Config).
-muc_config_public_list_slave(Config) ->
- muc_tests:muc_config_public_list_slave(Config).
-muc_config_password_master(Config) ->
- muc_tests:muc_config_password_master(Config).
-muc_config_password_slave(Config) ->
- muc_tests:muc_config_password_slave(Config).
-muc_config_whois_master(Config) ->
- muc_tests:muc_config_whois_master(Config).
-muc_config_whois_slave(Config) ->
- muc_tests:muc_config_whois_slave(Config).
-muc_config_members_only_master(Config) ->
- muc_tests:muc_config_members_only_master(Config).
-muc_config_members_only_slave(Config) ->
- muc_tests:muc_config_members_only_slave(Config).
-muc_config_moderated_master(Config) ->
- muc_tests:muc_config_moderated_master(Config).
-muc_config_moderated_slave(Config) ->
- muc_tests:muc_config_moderated_slave(Config).
-muc_config_private_messages_master(Config) ->
- muc_tests:muc_config_private_messages_master(Config).
-muc_config_private_messages_slave(Config) ->
- muc_tests:muc_config_private_messages_slave(Config).
-muc_config_query_master(Config) ->
- muc_tests:muc_config_query_master(Config).
-muc_config_query_slave(Config) ->
- muc_tests:muc_config_query_slave(Config).
-muc_config_allow_invites_master(Config) ->
- muc_tests:muc_config_allow_invites_master(Config).
-muc_config_allow_invites_slave(Config) ->
- muc_tests:muc_config_allow_invites_slave(Config).
-muc_config_visitor_status_master(Config) ->
- muc_tests:muc_config_visitor_status_master(Config).
-muc_config_visitor_status_slave(Config) ->
- muc_tests:muc_config_visitor_status_slave(Config).
-muc_config_allow_voice_requests_master(Config) ->
- muc_tests:muc_config_allow_voice_requests_master(Config).
-muc_config_allow_voice_requests_slave(Config) ->
- muc_tests:muc_config_allow_voice_requests_slave(Config).
-muc_config_voice_request_interval_master(Config) ->
- muc_tests:muc_config_voice_request_interval_master(Config).
-muc_config_voice_request_interval_slave(Config) ->
- muc_tests:muc_config_voice_request_interval_slave(Config).
-muc_config_visitor_nickchange_master(Config) ->
- muc_tests:muc_config_visitor_nickchange_master(Config).
-muc_config_visitor_nickchange_slave(Config) ->
- muc_tests:muc_config_visitor_nickchange_slave(Config).
-
-offline_feature_enabled(Config) ->
- offline_tests:feature_enabled(Config).
-offline_check_identity(Config) ->
- offline_tests:check_identity(Config).
-offline_send_non_existent(Config) ->
- offline_tests:send_non_existent(Config).
-offline_view_non_existent(Config) ->
- offline_tests:view_non_existent(Config).
-offline_remove_non_existent(Config) ->
- offline_tests:remove_non_existent(Config).
-offline_view_non_integer(Config) ->
- offline_tests:view_non_integer(Config).
-offline_remove_non_integer(Config) ->
- offline_tests:remove_non_integer(Config).
-offline_malformed_iq(Config) ->
- offline_tests:malformed_iq(Config).
-offline_wrong_user(Config) ->
- offline_tests:wrong_user(Config).
-offline_unsupported_iq(Config) ->
- offline_tests:unsupported_iq(Config).
-offline_flex_master(Config) ->
- offline_tests:flex_master(Config).
-offline_flex_slave(Config) ->
- offline_tests:flex_slave(Config).
-offline_send_all_master(Config) ->
- offline_tests:send_all_master(Config).
-offline_send_all_slave(Config) ->
- offline_tests:send_all_slave(Config).
-
-announce_master(Config) ->
- MyJID = my_jid(Config),
- ServerJID = server_jid(Config),
- MotdJID = jid:replace_resource(ServerJID, <<"announce/motd">>),
- MotdText = #text{data = <<"motd">>},
- #presence{from = MyJID} = send_recv(Config, #presence{}),
- %% Set message of the day
- send(Config, #message{to = MotdJID, body = [MotdText]}),
- %% Receive this message back
- #message{from = ServerJID, body = [MotdText]} = recv_message(Config),
- disconnect(Config).
-
-announce_slave(Config) ->
- MyJID = my_jid(Config),
- ServerJID = server_jid(Config),
- MotdDelJID = jid:replace_resource(ServerJID, <<"announce/motd/delete">>),
- MotdText = #text{data = <<"motd">>},
- #presence{from = MyJID} = send_recv(Config, #presence{}),
- #message{from = ServerJID, body = [MotdText]} = recv_message(Config),
- %% Delete message of the day
- send(Config, #message{to = MotdDelJID}),
- disconnect(Config).
-
-carbons_master(Config) ->
- MyJID = my_jid(Config),
- MyBareJID = jid:remove_resource(MyJID),
- Peer = ?config(slave, Config),
- Txt = #text{data = <<"body">>},
- true = is_feature_advertised(Config, ?NS_CARBONS_2),
- #presence{from = MyJID} = send_recv(Config, #presence{priority = 10}),
- wait_for_slave(Config),
- #presence{from = Peer} = recv_presence(Config),
- %% Enable carbons
- #iq{type = result, sub_els = []} =
- send_recv(Config,
- #iq{type = set,
- sub_els = [#carbons_enable{}]}),
- %% Send a message to bare and full JID
- send(Config, #message{to = MyBareJID, type = chat, body = [Txt]}),
- send(Config, #message{to = MyJID, type = chat, body = [Txt]}),
- send(Config, #message{to = MyBareJID, type = chat, body = [Txt],
- sub_els = [#carbons_private{}]}),
- send(Config, #message{to = MyJID, type = chat, body = [Txt],
- sub_els = [#carbons_private{}]}),
- %% Receive the messages back
- ?recv4(#message{from = MyJID, to = MyBareJID, type = chat,
- body = [Txt], sub_els = []},
- #message{from = MyJID, to = MyJID, type = chat,
- body = [Txt], sub_els = []},
- #message{from = MyJID, to = MyBareJID, type = chat,
- body = [Txt], sub_els = [#carbons_private{}]},
- #message{from = MyJID, to = MyJID, type = chat,
- body = [Txt], sub_els = [#carbons_private{}]}),
- %% Disable carbons
- #iq{type = result, sub_els = []} =
- send_recv(Config,
- #iq{type = set,
- sub_els = [#carbons_disable{}]}),
- wait_for_slave(Config),
- %% Repeat the same and leave
- send(Config, #message{to = MyBareJID, type = chat, body = [Txt]}),
- send(Config, #message{to = MyJID, type = chat, body = [Txt]}),
- send(Config, #message{to = MyBareJID, type = chat, body = [Txt],
- sub_els = [#carbons_private{}]}),
- send(Config, #message{to = MyJID, type = chat, body = [Txt],
- sub_els = [#carbons_private{}]}),
- ?recv4(#message{from = MyJID, to = MyBareJID, type = chat,
- body = [Txt], sub_els = []},
- #message{from = MyJID, to = MyJID, type = chat,
- body = [Txt], sub_els = []},
- #message{from = MyJID, to = MyBareJID, type = chat,
- body = [Txt], sub_els = [#carbons_private{}]},
- #message{from = MyJID, to = MyJID, type = chat,
- body = [Txt], sub_els = [#carbons_private{}]}),
- disconnect(Config).
-
-carbons_slave(Config) ->
- MyJID = my_jid(Config),
- MyBareJID = jid:remove_resource(MyJID),
- Peer = ?config(master, Config),
- Txt = #text{data = <<"body">>},
- wait_for_master(Config),
- #presence{from = MyJID} = send_recv(Config, #presence{priority = 5}),
- #presence{from = Peer} = recv_presence(Config),
- %% Enable carbons
- #iq{type = result, sub_els = []} =
- send_recv(Config,
- #iq{type = set,
- sub_els = [#carbons_enable{}]}),
- %% Receive messages sent by the peer
- ?recv4(
- #message{from = MyBareJID, to = MyJID, type = chat,
- sub_els =
- [#carbons_sent{
- forwarded = #forwarded{
- sub_els =
- [#message{from = Peer,
- to = MyBareJID,
- type = chat,
- body = [Txt]}]}}]},
- #message{from = MyBareJID, to = MyJID, type = chat,
- sub_els =
- [#carbons_sent{
- forwarded = #forwarded{
- sub_els =
- [#message{from = Peer,
- to = Peer,
- type = chat,
- body = [Txt]}]}}]},
- #message{from = MyBareJID, to = MyJID, type = chat,
- sub_els =
- [#carbons_received{
- forwarded = #forwarded{
- sub_els =
- [#message{from = Peer,
- to = MyBareJID,
- type = chat,
- body = [Txt]}]}}]},
- #message{from = MyBareJID, to = MyJID, type = chat,
- sub_els =
- [#carbons_received{
- forwarded = #forwarded{
- sub_els =
- [#message{from = Peer,
- to = Peer,
- type = chat,
- body = [Txt]}]}}]}),
- %% Disable carbons
- #iq{type = result, sub_els = []} =
- send_recv(Config,
- #iq{type = set,
- sub_els = [#carbons_disable{}]}),
- wait_for_master(Config),
- %% Now we should receive nothing but presence unavailable from the peer
- #presence{from = Peer, type = unavailable} = recv_presence(Config),
- disconnect(Config).
-
-mam_old_master(Config) ->
- mam_master(Config, ?NS_MAM_TMP).
-
-mam_new_master(Config) ->
- mam_master(Config, ?NS_MAM_0).
-
-mam_master(Config, NS) ->
- true = is_feature_advertised(Config, NS),
- MyJID = my_jid(Config),
- BareMyJID = jid:remove_resource(MyJID),
- Peer = ?config(slave, Config),
- #presence{} = send_recv(Config, #presence{}),
- wait_for_slave(Config),
- #presence{from = Peer} = recv_presence(Config),
- #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = roster}]} =
- send_recv(Config,
- #iq{type = set,
- sub_els = [#mam_prefs{xmlns = NS,
- default = roster,
- never = [MyJID]}]}),
- if NS == ?NS_MAM_TMP ->
- %% NOTE: The server should strip fake archived tags,
- %% i.e. the sub_els received should be [].
- FakeArchived = #mam_archived{id = randoms:get_string(),
- by = server_jid(Config)},
- #message{body = [#text{data = <<"a">>}], sub_els = []} =
- send_recv(Config, #message{to = MyJID,
- sub_els = [FakeArchived],
- body = [#text{data = <<"a">>}]}),
- #message{body = [#text{data = <<"b">>}], sub_els = []} =
- send_recv(Config, #message{to = BareMyJID,
- sub_els = [FakeArchived],
- body = [#text{data = <<"b">>}]});
- true ->
- ok
- end,
- wait_for_slave(Config),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- send(Config, #message{to = Peer, body = [Text]})
- end, lists:seq(1, 5)),
- #presence{type = unavailable, from = Peer} = recv_presence(Config),
- mam_query_all(Config, NS),
- mam_query_with(Config, Peer, NS),
- %% mam_query_with(Config, jid:remove_resource(Peer)),
- mam_query_rsm(Config, NS),
- #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} =
- send_recv(Config, #iq{type = set,
- sub_els = [#mam_prefs{xmlns = NS,
- default = never}]}),
- disconnect(Config).
-
-mam_old_slave(Config) ->
- mam_slave(Config, ?NS_MAM_TMP).
-
-mam_new_slave(Config) ->
- mam_slave(Config, ?NS_MAM_0).
-
-mam_slave(Config, NS) ->
- Peer = ?config(master, Config),
- MyJID = my_jid(Config),
- ServerJID = server_jid(Config),
- wait_for_master(Config),
- #presence{from = MyJID} = send_recv(Config, #presence{}),
- #presence{from = Peer} = recv_presence(Config),
- #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = always}]} =
- send_recv(Config,
- #iq{type = set,
- sub_els = [#mam_prefs{xmlns = NS, default = always}]}),
- wait_for_master(Config),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- Msg = #message{from = Peer, body = [Text]} = recv_message(Config),
- #mam_archived{by = ServerJID} =
- xmpp:get_subtag(Msg, #mam_archived{}),
- #stanza_id{by = ServerJID} =
- xmpp:get_subtag(Msg, #stanza_id{})
- end, lists:seq(1, 5)),
- #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} =
- send_recv(Config, #iq{type = set,
- sub_els = [#mam_prefs{xmlns = NS, default = never}]}),
- disconnect(Config).
-
-mam_query_all(Config, NS) ->
- QID = randoms:get_string(),
- MyJID = my_jid(Config),
- Peer = ?config(slave, Config),
- Type = case NS of
- ?NS_MAM_TMP -> get;
- _ -> set
- end,
- I = send(Config, #iq{type = Type, sub_els = [#mam_query{xmlns = NS, id = QID}]}),
- maybe_recv_iq_result(Config, NS, I),
- Iter = if NS == ?NS_MAM_TMP -> lists:seq(1, 5);
- true -> lists:seq(1, 5) ++ lists:seq(1, 5)
- end,
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{to = MyJID,
- sub_els =
- [#mam_result{
- queryid = QID,
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els =
- [#message{
- from = MyJID, to = Peer,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, Iter),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I,
- sub_els = [#mam_query{xmlns = NS, id = QID}]} = recv_iq(Config);
- true ->
- #message{sub_els = [#mam_fin{complete = true, id = QID}]} =
- recv_message(Config)
- end.
-
-mam_query_with(Config, JID, NS) ->
- MyJID = my_jid(Config),
- Peer = ?config(slave, Config),
- {Query, Type} = if NS == ?NS_MAM_TMP ->
- {#mam_query{xmlns = NS, with = JID}, get};
- true ->
- Fs = [#xdata_field{var = <<"jid">>,
- values = [jid:to_string(JID)]}],
- {#mam_query{xmlns = NS,
- xdata = #xdata{type = submit, fields = Fs}}, set}
- end,
- I = send(Config, #iq{type = Type, sub_els = [Query]}),
- Iter = if NS == ?NS_MAM_TMP -> lists:seq(1, 5);
- true -> lists:seq(1, 5) ++ lists:seq(1, 5)
- end,
- maybe_recv_iq_result(Config, NS, I),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{to = MyJID,
- sub_els =
- [#mam_result{
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els =
- [#message{
- from = MyJID, to = Peer,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, Iter),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I,
- sub_els = [#mam_query{xmlns = NS}]} = recv_iq(Config);
- true ->
- #message{sub_els = [#mam_fin{complete = true}]} =
- recv_message(Config)
- end.
-
-maybe_recv_iq_result(Config, ?NS_MAM_0, I1) ->
- #iq{type = result, id = I1} = recv_iq(Config);
-maybe_recv_iq_result(_, _, _) ->
- ok.
-
-mam_query_rsm(Config, NS) ->
- MyJID = my_jid(Config),
- Peer = ?config(slave, Config),
- Type = case NS of
- ?NS_MAM_TMP -> get;
- _ -> set
- end,
- %% Get the first 3 items out of 5
- I1 = send(Config,
- #iq{type = Type,
- sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 3}}]}),
- maybe_recv_iq_result(Config, NS, I1),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{to = MyJID,
- sub_els =
- [#mam_result{
- xmlns = NS,
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els =
- [#message{
- from = MyJID, to = Peer,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, lists:seq(1, 3)),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I1,
- sub_els = [#mam_query{xmlns = NS,
- rsm = #rsm_set{last = Last,
- count = 5}}]} =
- recv_iq(Config);
- true ->
- #message{sub_els = [#mam_fin{
- complete = false,
- rsm = #rsm_set{last = Last,
- count = 10}}]} =
- recv_message(Config)
- end,
- %% Get the next items starting from the `Last`.
- %% Limit the response to 2 items.
- I2 = send(Config,
- #iq{type = Type,
- sub_els = [#mam_query{xmlns = NS,
- rsm = #rsm_set{max = 2,
- 'after' = Last}}]}),
- maybe_recv_iq_result(Config, NS, I2),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{to = MyJID,
- sub_els =
- [#mam_result{
- xmlns = NS,
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els =
- [#message{
- from = MyJID, to = Peer,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, lists:seq(4, 5)),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I2,
- sub_els = [#mam_query{
- xmlns = NS,
- rsm = #rsm_set{
- count = 5,
- first = #rsm_first{data = First}}}]} =
- recv_iq(Config);
- true ->
- #message{
- sub_els = [#mam_fin{
- complete = false,
- rsm = #rsm_set{
- count = 10,
- first = #rsm_first{data = First}}}]} =
- recv_message(Config)
- end,
- %% Paging back. Should receive 3 elements: 1, 2, 3.
- I3 = send(Config,
- #iq{type = Type,
- sub_els = [#mam_query{xmlns = NS,
- rsm = #rsm_set{max = 3,
- before = First}}]}),
- maybe_recv_iq_result(Config, NS, I3),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{to = MyJID,
- sub_els =
- [#mam_result{
- xmlns = NS,
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els =
- [#message{
- from = MyJID, to = Peer,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, lists:seq(1, 3)),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I3,
- sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{count = 5}}]} =
- recv_iq(Config);
- true ->
- #message{
- sub_els = [#mam_fin{complete = true,
- rsm = #rsm_set{count = 10}}]} =
- recv_message(Config)
- end,
- %% Getting the item count. Should be 5 (or 10).
- I4 = send(Config,
- #iq{type = Type,
- sub_els = [#mam_query{xmlns = NS,
- rsm = #rsm_set{max = 0}}]}),
- maybe_recv_iq_result(Config, NS, I4),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I4,
- sub_els = [#mam_query{
- xmlns = NS,
- rsm = #rsm_set{count = 5,
- first = undefined,
- last = undefined}}]} =
- recv_iq(Config);
- true ->
- #message{
- sub_els = [#mam_fin{
- complete = false,
- rsm = #rsm_set{count = 10,
- first = undefined,
- last = undefined}}]} =
- recv_message(Config)
- end,
- %% Should receive 2 last messages
- I5 = send(Config,
- #iq{type = Type,
- sub_els = [#mam_query{xmlns = NS,
- rsm = #rsm_set{max = 2,
- before = <<"">>}}]}),
- maybe_recv_iq_result(Config, NS, I5),
- lists:foreach(
- fun(N) ->
- Text = #text{data = integer_to_binary(N)},
- #message{to = MyJID,
- sub_els =
- [#mam_result{
- xmlns = NS,
- sub_els =
- [#forwarded{
- delay = #delay{},
- sub_els =
- [#message{
- from = MyJID, to = Peer,
- body = [Text]}]}]}]} =
- recv_message(Config)
- end, lists:seq(4, 5)),
- if NS == ?NS_MAM_TMP ->
- #iq{type = result, id = I5,
- sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{count = 5}}]} =
- recv_iq(Config);
- true ->
- #message{
- sub_els = [#mam_fin{complete = false,
- rsm = #rsm_set{count = 10}}]} =
- recv_message(Config)
- end.
-
-client_state_master(Config) ->
- true = ?config(csi, Config),
- Peer = ?config(slave, Config),
- Presence = #presence{to = Peer},
- ChatState = #message{to = Peer, thread = <<"1">>,
- sub_els = [#chatstate{type = active}]},
- Message = ChatState#message{body = [#text{data = <<"body">>}]},
- PepPayload = xmpp:encode(#presence{}),
- PepOne = #message{
- to = Peer,
- sub_els =
- [#ps_event{
- items =
- #ps_items{
- node = <<"foo-1">>,
- items =
- [#ps_item{
- id = <<"pep-1">>,
- xml_els = [PepPayload]}]}}]},
- PepTwo = #message{
- to = Peer,
- sub_els =
- [#ps_event{
- items =
- #ps_items{
- node = <<"foo-2">>,
- items =
- [#ps_item{
- id = <<"pep-2">>,
- xml_els = [PepPayload]}]}}]},
- %% Wait for the slave to become inactive.
- wait_for_slave(Config),
- %% Should be queued (but see below):
- send(Config, Presence),
- %% Should replace the previous presence in the queue:
- send(Config, Presence#presence{type = unavailable}),
- %% The following two PEP stanzas should be queued (but see below):
- send(Config, PepOne),
- send(Config, PepTwo),
- %% The following two PEP stanzas should replace the previous two:
- send(Config, PepOne),
- send(Config, PepTwo),
- %% Should be queued (but see below):
- send(Config, ChatState),
- %% Should replace the previous chat state in the queue:
- send(Config, ChatState#message{sub_els = [#chatstate{type = composing}]}),
- %% Should be sent immediately, together with the queued stanzas:
- send(Config, Message),
- %% Wait for the slave to become active.
- wait_for_slave(Config),
- %% Should be delivered, as the client is active again:
- send(Config, ChatState),
- disconnect(Config).
-
-client_state_slave(Config) ->
- Peer = ?config(master, Config),
- change_client_state(Config, inactive),
- wait_for_master(Config),
- #presence{from = Peer, type = unavailable, sub_els = [#delay{}]} =
- recv_presence(Config),
- #message{
- from = Peer,
- sub_els =
- [#ps_event{
- items =
- #ps_items{
- node = <<"foo-1">>,
- items =
- [#ps_item{
- id = <<"pep-1">>}]}},
- #delay{}]} = recv_message(Config),
- #message{
- from = Peer,
- sub_els =
- [#ps_event{
- items =
- #ps_items{
- node = <<"foo-2">>,
- items =
- [#ps_item{
- id = <<"pep-2">>}]}},
- #delay{}]} = recv_message(Config),
- #message{from = Peer, thread = <<"1">>,
- sub_els = [#chatstate{type = composing},
- #delay{}]} = recv_message(Config),
- #message{from = Peer, thread = <<"1">>,
- body = [#text{data = <<"body">>}],
- sub_els = [#chatstate{type = active}]} = recv_message(Config),
- change_client_state(Config, active),
- wait_for_master(Config),
- #message{from = Peer, thread = <<"1">>,
- sub_els = [#chatstate{type = active}]} = recv_message(Config),
- disconnect(Config).
-
%%%===================================================================
%%% Aux functions
%%%===================================================================
-change_client_state(Config, NewState) ->
- send(Config, #csi{type = NewState}),
- send_recv(Config, #iq{type = get, to = server_jid(Config),
- sub_els = [#ping{}]}).
-
bookmark_conference() ->
#bookmark_conference{name = <<"Some name">>,
autojoin = true,
@@ -2902,34 +979,22 @@ bookmark_conference() ->
<<"some.conference.org">>,
<<>>)}.
-socks5_connect(#streamhost{host = Host, port = Port},
- {SID, JID1, JID2}) ->
- Hash = p1_sha:sha([SID, jid:to_string(JID1), jid:to_string(JID2)]),
- {ok, Sock} = gen_tcp:connect(binary_to_list(Host), Port,
- [binary, {active, false}]),
- Init = <<?VERSION_5, 1, ?AUTH_ANONYMOUS>>,
- InitAck = <<?VERSION_5, ?AUTH_ANONYMOUS>>,
- Req = <<?VERSION_5, ?CMD_CONNECT, 0,
- ?ATYP_DOMAINNAME, 40, Hash:40/binary, 0, 0>>,
- Resp = <<?VERSION_5, ?SUCCESS, 0, ?ATYP_DOMAINNAME,
- 40, Hash:40/binary, 0, 0>>,
- gen_tcp:send(Sock, Init),
- {ok, InitAck} = gen_tcp:recv(Sock, size(InitAck)),
- gen_tcp:send(Sock, Req),
- {ok, Resp} = gen_tcp:recv(Sock, size(Resp)),
- Sock.
-
-socks5_send(Sock, Data) ->
- ok = gen_tcp:send(Sock, Data).
-
-socks5_recv(Sock, Data) ->
- {ok, Data} = gen_tcp:recv(Sock, size(Data)).
-
-set_opts(Config, Options) ->
- lists:foldl(
- fun({Opt, Val}, Acc) ->
- lists:keystore(Opt, 1, Acc, {Opt, Val})
- end, Config, Options).
+'$handle_undefined_function'(F, [Config]) when is_list(Config) ->
+ case re:split(atom_to_list(F), "_", [{return, list}, {parts, 2}]) of
+ [M, T] ->
+ Module = list_to_atom(M ++ "_tests"),
+ Function = list_to_atom(T),
+ case erlang:function_exported(Module, Function, 1) of
+ true ->
+ Module:Function(Config);
+ false ->
+ erlang:error({undef, F})
+ end;
+ _ ->
+ erlang:error({undef, F})
+ end;
+'$handle_undefined_function'(_, _) ->
+ erlang:error(undef).
%%%===================================================================
%%% SQL stuff
@@ -3011,12 +1076,12 @@ split(Data) ->
clear_riak_tables(Config) ->
User = ?config(user, Config),
Server = ?config(server, Config),
- Room = muc_room_jid(Config),
- {URoom, SRoom, _} = jid:tolower(Room),
+ Master = <<"test_master!#$%^*()`~+-;_=[]{}|\\">>,
+ Slave = <<"test_slave!#$%^*()`~+-;_=[]{}|\\">>,
ejabberd_auth:remove_user(User, Server),
- ejabberd_auth:remove_user(<<"test_slave">>, Server),
- ejabberd_auth:remove_user(<<"test_master">>, Server),
- mod_muc:forget_room(Server, URoom, SRoom),
- ejabberd_riak:delete(muc_registered, {{<<"test_slave">>, Server}, SRoom}),
- ejabberd_riak:delete(muc_registered, {{<<"test_master">>, Server}, SRoom}),
+ ejabberd_auth:remove_user(Master, Server),
+ ejabberd_auth:remove_user(Slave, Server),
+ ejabberd_riak:delete(muc_room),
+ ejabberd_riak:delete(muc_registered),
+ timer:sleep(timer:seconds(5)),
Config.
diff --git a/test/example_tests.erl b/test/example_tests.erl
new file mode 100644
index 00000000..d7965376
--- /dev/null
+++ b/test/example_tests.erl
@@ -0,0 +1,52 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(example_tests).
+
+%% API
+-compile(export_all).
+-import(suite, []).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {example_single, [sequence],
+ [single_test(foo)]}.
+
+foo(Config) ->
+ Config.
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {example_master_slave, [sequence],
+ [master_slave_test(foo)]}.
+
+foo_master(Config) ->
+ Config.
+
+foo_slave(Config) ->
+ Config.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("example_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("example_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("example_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("example_" ++ atom_to_list(T) ++ "_slave")]}.
diff --git a/test/mam_tests.erl b/test/mam_tests.erl
new file mode 100644
index 00000000..9154ea24
--- /dev/null
+++ b/test/mam_tests.erl
@@ -0,0 +1,537 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 14 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mam_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [get_features/1, disconnect/1, my_jid/1, send_recv/2,
+ wait_for_slave/1, server_jid/1, send/2, get_features/2,
+ wait_for_master/1, recv_message/1, recv_iq/1, muc_room_jid/1,
+ muc_jid/1, is_feature_advertised/3, get_event/1, put_event/2]).
+
+-include("suite.hrl").
+-define(VERSIONS, [?NS_MAM_TMP, ?NS_MAM_0, ?NS_MAM_1]).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {mam_single, [sequence],
+ [single_test(feature_enabled),
+ single_test(get_set_prefs),
+ single_test(get_form),
+ single_test(fake_by)]}.
+
+feature_enabled(Config) ->
+ BareMyJID = jid:remove_resource(my_jid(Config)),
+ RequiredFeatures = sets:from_list(?VERSIONS),
+ ServerFeatures = sets:from_list(get_features(Config)),
+ UserFeatures = sets:from_list(get_features(Config, BareMyJID)),
+ MUCFeatures = get_features(Config, muc_jid(Config)),
+ ct:comment("Checking if all MAM server features are enabled"),
+ true = sets:is_subset(RequiredFeatures, ServerFeatures),
+ ct:comment("Checking if all MAM user features are enabled"),
+ true = sets:is_subset(RequiredFeatures, UserFeatures),
+ ct:comment("Checking if all MAM conference service features are enabled"),
+ true = lists:member(?NS_MAM_1, MUCFeatures),
+ clean(disconnect(Config)).
+
+fake_by(Config) ->
+ BareServerJID = server_jid(Config),
+ FullServerJID = jid:replace_resource(BareServerJID, randoms:get_string()),
+ FullMyJID = my_jid(Config),
+ BareMyJID = jid:remove_resource(FullMyJID),
+ Fakes = lists:flatmap(
+ fun(JID) ->
+ [#mam_archived{id = randoms:get_string(), by = JID},
+ #stanza_id{id = randoms:get_string(), by = JID}]
+ end, [BareServerJID, FullServerJID, BareMyJID, FullMyJID]),
+ Body = xmpp:mk_text(<<"body">>),
+ ForeignJID = jid:make(randoms:get_string()),
+ Archived = #mam_archived{id = randoms:get_string(), by = ForeignJID},
+ StanzaID = #stanza_id{id = randoms:get_string(), by = ForeignJID},
+ #message{body = Body, sub_els = SubEls} =
+ send_recv(Config, #message{to = FullMyJID,
+ body = Body,
+ sub_els = [Archived, StanzaID|Fakes]}),
+ ct:comment("Checking if only foreign tags present"),
+ [ForeignJID, ForeignJID] = lists:flatmap(
+ fun(#mam_archived{by = By}) -> [By];
+ (#stanza_id{by = By}) -> [By];
+ (_) -> []
+ end, SubEls),
+ clean(disconnect(Config)).
+
+get_set_prefs(Config) ->
+ Range = [{JID, #mam_prefs{xmlns = NS,
+ default = Default,
+ always = Always,
+ never = Never}} ||
+ JID <- [undefined, server_jid(Config)],
+ NS <- ?VERSIONS,
+ Default <- [always, never, roster],
+ Always <- [[], [jid:from_string(<<"foo@bar.baz">>)]],
+ Never <- [[], [jid:from_string(<<"baz@bar.foo">>)]]],
+ lists:foreach(
+ fun({To, Prefs}) ->
+ NS = Prefs#mam_prefs.xmlns,
+ #iq{type = result, sub_els = [Prefs]} =
+ send_recv(Config, #iq{type = set, to = To,
+ sub_els = [Prefs]}),
+ #iq{type = result, sub_els = [Prefs]} =
+ send_recv(Config, #iq{type = get, to = To,
+ sub_els = [#mam_prefs{xmlns = NS}]})
+ end, Range),
+ clean(disconnect(Config)).
+
+get_form(Config) ->
+ ServerJID = server_jid(Config),
+ Range = [{JID, NS} || JID <- [undefined, ServerJID],
+ NS <- ?VERSIONS -- [?NS_MAM_TMP]],
+ lists:foreach(
+ fun({To, NS}) ->
+ #iq{type = result,
+ sub_els = [#mam_query{xmlns = NS,
+ xdata = #xdata{} = X}]} =
+ send_recv(Config, #iq{type = get, to = To,
+ sub_els = [#mam_query{xmlns = NS}]}),
+ [NS] = xmpp_util:get_xdata_values(<<"FORM_TYPE">>, X),
+ true = xmpp_util:has_xdata_var(<<"with">>, X),
+ true = xmpp_util:has_xdata_var(<<"start">>, X),
+ true = xmpp_util:has_xdata_var(<<"end">>, X)
+ end, Range),
+ clean(disconnect(Config)).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {mam_master_slave, [sequence],
+ [master_slave_test(archived_and_stanza_id),
+ master_slave_test(query_all),
+ master_slave_test(query_with),
+ master_slave_test(query_rsm_max),
+ master_slave_test(query_rsm_after),
+ master_slave_test(query_rsm_before),
+ master_slave_test(muc)]}.
+
+archived_and_stanza_id_master(Config) ->
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send_messages(Config, lists:seq(1, 5)),
+ clean(disconnect(Config)).
+
+archived_and_stanza_id_slave(Config) ->
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ recv_messages(Config, lists:seq(1, 5)),
+ clean(disconnect(Config)).
+
+query_all_master(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send_messages(Config, lists:seq(1, 5)),
+ query_all(Config, MyJID, Peer),
+ clean(disconnect(Config)).
+
+query_all_slave(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ recv_messages(Config, lists:seq(1, 5)),
+ query_all(Config, Peer, MyJID),
+ clean(disconnect(Config)).
+
+query_with_master(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send_messages(Config, lists:seq(1, 5)),
+ query_with(Config, MyJID, Peer),
+ clean(disconnect(Config)).
+
+query_with_slave(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ recv_messages(Config, lists:seq(1, 5)),
+ query_with(Config, Peer, MyJID),
+ clean(disconnect(Config)).
+
+query_rsm_max_master(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send_messages(Config, lists:seq(1, 5)),
+ query_rsm_max(Config, MyJID, Peer),
+ clean(disconnect(Config)).
+
+query_rsm_max_slave(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ recv_messages(Config, lists:seq(1, 5)),
+ query_rsm_max(Config, Peer, MyJID),
+ clean(disconnect(Config)).
+
+query_rsm_after_master(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send_messages(Config, lists:seq(1, 5)),
+ query_rsm_after(Config, MyJID, Peer),
+ clean(disconnect(Config)).
+
+query_rsm_after_slave(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ recv_messages(Config, lists:seq(1, 5)),
+ query_rsm_after(Config, Peer, MyJID),
+ clean(disconnect(Config)).
+
+query_rsm_before_master(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_slave(Config),
+ send_messages(Config, lists:seq(1, 5)),
+ query_rsm_before(Config, MyJID, Peer),
+ clean(disconnect(Config)).
+
+query_rsm_before_slave(Config) ->
+ Peer = ?config(peer, Config),
+ MyJID = my_jid(Config),
+ ok = set_default(Config, always),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ recv_messages(Config, lists:seq(1, 5)),
+ query_rsm_before(Config, Peer, MyJID),
+ clean(disconnect(Config)).
+
+muc_master(Config) ->
+ Room = muc_room_jid(Config),
+ %% Joining
+ ok = muc_tests:join_new(Config),
+ %% MAM feature should not be advertised at this point,
+ %% because MAM is not enabled so far
+ false = is_feature_advertised(Config, ?NS_MAM_1, Room),
+ %% Fill in some history
+ send_messages_to_room(Config, lists:seq(1, 21)),
+ %% We now should be able to retrieve those via MAM, even though
+ %% MAM is disabled. However, only last 20 messages should be received.
+ recv_messages_from_room(Config, lists:seq(2, 21)),
+ %% Now enable MAM for the conference
+ %% Retrieve config first
+ #iq{type = result, sub_els = [#muc_owner{config = #xdata{} = RoomCfg}]} =
+ send_recv(Config, #iq{type = get, sub_els = [#muc_owner{}],
+ to = Room}),
+ %% Find the MAM field in the config and enable it
+ NewFields = lists:flatmap(
+ fun(#xdata_field{var = <<"mam">> = Var}) ->
+ [#xdata_field{var = Var, values = [<<"1">>]}];
+ (_) ->
+ []
+ end, RoomCfg#xdata.fields),
+ NewRoomCfg = #xdata{type = submit, fields = NewFields},
+ #iq{type = result, sub_els = []} =
+ send_recv(Config, #iq{type = set, to = Room,
+ sub_els = [#muc_owner{config = NewRoomCfg}]}),
+ #message{from = Room, type = groupchat,
+ sub_els = [#muc_user{status_codes = [104]}]} = recv_message(Config),
+ %% Check if MAM has been enabled
+ true = is_feature_advertised(Config, ?NS_MAM_1, Room),
+ %% We now sending some messages again
+ send_messages_to_room(Config, lists:seq(1, 5)),
+ %% And retrieve them via MAM again.
+ recv_messages_from_room(Config, lists:seq(1, 5)),
+ put_event(Config, disconnect),
+ clean(disconnect(Config)).
+
+muc_slave(Config) ->
+ disconnect = get_event(Config),
+ clean(disconnect(Config)).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("mam_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("mam_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("mam_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("mam_" ++ atom_to_list(T) ++ "_slave")]}.
+
+clean(Config) ->
+ {U, S, _} = jid:tolower(my_jid(Config)),
+ mod_mam:remove_user(U, S),
+ Config.
+
+set_default(Config, Default) ->
+ lists:foreach(
+ fun(NS) ->
+ ct:comment("Setting default preferences of '~s' to '~s'",
+ [NS, Default]),
+ #iq{type = result,
+ sub_els = [#mam_prefs{xmlns = NS, default = Default}]} =
+ send_recv(Config, #iq{type = set,
+ sub_els = [#mam_prefs{xmlns = NS,
+ default = Default}]})
+ end, ?VERSIONS).
+
+send_messages(Config, Range) ->
+ Peer = ?config(peer, Config),
+ lists:foreach(
+ fun(N) ->
+ Body = xmpp:mk_text(integer_to_binary(N)),
+ send(Config, #message{to = Peer, body = Body})
+ end, Range).
+
+recv_messages(Config, Range) ->
+ Peer = ?config(peer, Config),
+ lists:foreach(
+ fun(N) ->
+ Body = xmpp:mk_text(integer_to_binary(N)),
+ #message{from = Peer, body = Body} = Msg =
+ recv_message(Config),
+ #mam_archived{by = BareMyJID} =
+ xmpp:get_subtag(Msg, #mam_archived{}),
+ #stanza_id{by = BareMyJID} =
+ xmpp:get_subtag(Msg, #stanza_id{})
+ end, Range).
+
+recv_archived_messages(Config, From, To, QID, Range) ->
+ MyJID = my_jid(Config),
+ lists:foreach(
+ fun(N) ->
+ ct:comment("Retreiving ~pth message in range ~p",
+ [N, Range]),
+ Body = xmpp:mk_text(integer_to_binary(N)),
+ #message{to = MyJID,
+ sub_els =
+ [#mam_result{
+ queryid = QID,
+ sub_els =
+ [#forwarded{
+ delay = #delay{},
+ xml_els = [El]}]}]} = recv_message(Config),
+ #message{from = From, to = To,
+ body = Body} = xmpp:decode(El)
+ end, Range).
+
+maybe_recv_iq_result(Config, ?NS_MAM_0, I) ->
+ #iq{type = result, id = I} = recv_iq(Config);
+maybe_recv_iq_result(_, _, _) ->
+ ok.
+
+query_iq_type(?NS_MAM_TMP) -> get;
+query_iq_type(_) -> set.
+
+send_query(Config, #mam_query{xmlns = NS} = Query) ->
+ Type = query_iq_type(NS),
+ I = send(Config, #iq{type = Type, sub_els = [Query]}),
+ maybe_recv_iq_result(Config, NS, I),
+ I.
+
+recv_fin(Config, I, QueryID, ?NS_MAM_1 = NS, IsComplete) ->
+ ct:comment("Receiving fin iq for namespace '~s'", [NS]),
+ #iq{type = result, id = I,
+ sub_els = [#mam_fin{xmlns = NS,
+ id = QueryID,
+ complete = Complete,
+ rsm = RSM}]} = recv_iq(Config),
+ ct:comment("Checking if complete is ~s", [IsComplete]),
+ Complete = IsComplete,
+ RSM;
+recv_fin(Config, I, QueryID, ?NS_MAM_TMP = NS, _IsComplete) ->
+ ct:comment("Receiving fin iq for namespace '~s'", [NS]),
+ #iq{type = result, id = I,
+ sub_els = [#mam_query{xmlns = NS,
+ rsm = RSM,
+ id = QueryID}]} = recv_iq(Config),
+ RSM;
+recv_fin(Config, _, QueryID, ?NS_MAM_0 = NS, IsComplete) ->
+ ct:comment("Receiving fin message for namespace '~s'", [NS]),
+ #message{} = FinMsg = recv_message(Config),
+ #mam_fin{xmlns = NS,
+ id = QueryID,
+ complete = Complete,
+ rsm = RSM} = xmpp:get_subtag(FinMsg, #mam_fin{xmlns = NS}),
+ ct:comment("Checking if complete is ~s", [IsComplete]),
+ Complete = IsComplete,
+ RSM.
+
+send_messages_to_room(Config, Range) ->
+ MyNick = ?config(master_nick, Config),
+ Room = muc_room_jid(Config),
+ MyNickJID = jid:replace_resource(Room, MyNick),
+ lists:foreach(
+ fun(N) ->
+ Body = xmpp:mk_text(integer_to_binary(N)),
+ #message{from = MyNickJID,
+ type = groupchat,
+ body = Body} =
+ send_recv(Config, #message{to = Room, body = Body,
+ type = groupchat})
+ end, Range).
+
+recv_messages_from_room(Config, Range) ->
+ MyNick = ?config(master_nick, Config),
+ Room = muc_room_jid(Config),
+ MyNickJID = jid:replace_resource(Room, MyNick),
+ MyJID = my_jid(Config),
+ QID = randoms:get_string(),
+ Count = length(Range),
+ I = send(Config, #iq{type = set, to = Room,
+ sub_els = [#mam_query{xmlns = ?NS_MAM_1, id = QID}]}),
+ lists:foreach(
+ fun(N) ->
+ Body = xmpp:mk_text(integer_to_binary(N)),
+ #message{
+ to = MyJID, from = Room,
+ sub_els =
+ [#mam_result{
+ xmlns = ?NS_MAM_1,
+ queryid = QID,
+ sub_els =
+ [#forwarded{
+ delay = #delay{},
+ xml_els = [El]}]}]} = recv_message(Config),
+ #message{from = MyNickJID,
+ type = groupchat,
+ body = Body} = xmpp:decode(El)
+ end, Range),
+ #iq{from = Room, id = I, type = result,
+ sub_els = [#mam_fin{xmlns = ?NS_MAM_1,
+ id = QID,
+ rsm = #rsm_set{count = Count},
+ complete = true}]} = recv_iq(Config).
+
+query_all(Config, From, To) ->
+ lists:foreach(
+ fun(NS) ->
+ query_all(Config, From, To, NS)
+ end, ?VERSIONS).
+
+query_all(Config, From, To, NS) ->
+ QID = randoms:get_string(),
+ Range = lists:seq(1, 5),
+ ID = send_query(Config, #mam_query{xmlns = NS, id = QID}),
+ recv_archived_messages(Config, From, To, QID, Range),
+ #rsm_set{count = 5} = recv_fin(Config, ID, QID, NS, _Complete = true).
+
+query_with(Config, From, To) ->
+ lists:foreach(
+ fun(NS) ->
+ query_with(Config, From, To, NS)
+ end, ?VERSIONS).
+
+query_with(Config, From, To, NS) ->
+ Peer = ?config(peer, Config),
+ BarePeer = jid:remove_resource(Peer),
+ QID = randoms:get_string(),
+ Range = lists:seq(1, 5),
+ lists:foreach(
+ fun(JID) ->
+ ct:comment("Sending query with jid ~s", [jid:to_string(JID)]),
+ Query = if NS == ?NS_MAM_TMP ->
+ #mam_query{xmlns = NS, with = JID, id = QID};
+ true ->
+ Fs = mam_query:encode([{with, JID}]),
+ #mam_query{xmlns = NS, id = QID,
+ xdata = #xdata{type = submit,
+ fields = Fs}}
+ end,
+ ID = send_query(Config, Query),
+ recv_archived_messages(Config, From, To, QID, Range),
+ #rsm_set{count = 5} = recv_fin(Config, ID, QID, NS, true)
+ end, [Peer, BarePeer]).
+
+query_rsm_max(Config, From, To) ->
+ lists:foreach(
+ fun(NS) ->
+ query_rsm_max(Config, From, To, NS)
+ end, ?VERSIONS).
+
+query_rsm_max(Config, From, To, NS) ->
+ lists:foreach(
+ fun(Max) ->
+ QID = randoms:get_string(),
+ Range = lists:sublist(lists:seq(1, Max), 5),
+ Query = #mam_query{xmlns = NS, id = QID, rsm = #rsm_set{max = Max}},
+ ID = send_query(Config, Query),
+ recv_archived_messages(Config, From, To, QID, Range),
+ IsComplete = Max >= 5,
+ #rsm_set{count = 5} = recv_fin(Config, ID, QID, NS, IsComplete)
+ end, lists:seq(0, 6)).
+
+query_rsm_after(Config, From, To) ->
+ lists:foreach(
+ fun(NS) ->
+ query_rsm_after(Config, From, To, NS)
+ end, ?VERSIONS).
+
+query_rsm_after(Config, From, To, NS) ->
+ lists:foldl(
+ fun(Range, #rsm_first{data = After}) ->
+ ct:comment("Retrieving ~p messages after '~s'",
+ [length(Range), After]),
+ QID = randoms:get_string(),
+ Query = #mam_query{xmlns = NS, id = QID,
+ rsm = #rsm_set{'after' = After}},
+ ID = send_query(Config, Query),
+ recv_archived_messages(Config, From, To, QID, Range),
+ #rsm_set{count = 5, first = First} =
+ recv_fin(Config, ID, QID, NS, true),
+ First
+ end, #rsm_first{}, [lists:seq(N, 5) || N <- lists:seq(1, 6)]).
+
+query_rsm_before(Config, From, To) ->
+ lists:foreach(
+ fun(NS) ->
+ query_rsm_before(Config, From, To, NS)
+ end, ?VERSIONS).
+
+query_rsm_before(Config, From, To, NS) ->
+ lists:foldl(
+ fun(Range, Before) ->
+ ct:comment("Retrieving ~p messages before '~s'",
+ [length(Range), Before]),
+ QID = randoms:get_string(),
+ Query = #mam_query{xmlns = NS, id = QID,
+ rsm = #rsm_set{before = Before}},
+ ID = send_query(Config, Query),
+ recv_archived_messages(Config, From, To, QID, Range),
+ #rsm_set{count = 5, last = Last} =
+ recv_fin(Config, ID, QID, NS, true),
+ Last
+ end, <<"">>, lists:reverse([lists:seq(1, N) || N <- lists:seq(0, 5)])).
diff --git a/test/mix_tests.erl b/test/mix_tests.erl
new file mode 100644
index 00000000..56b1b35d
--- /dev/null
+++ b/test/mix_tests.erl
@@ -0,0 +1,139 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mix_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [mix_jid/1, mix_room_jid/1, my_jid/1, is_feature_advertised/3,
+ disconnect/1, send_recv/2, recv_message/1, send/2,
+ put_event/2, get_event/1]).
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {mix_single, [sequence],
+ [single_test(feature_enabled)]}.
+
+feature_enabled(Config) ->
+ MIX = mix_jid(Config),
+ ct:comment("Checking if ~s is set", [?NS_MIX_0]),
+ true = is_feature_advertised(Config, ?NS_MIX_0, MIX),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {mix_master_slave, [sequence],
+ [master_slave_test(all)]}.
+
+all_master(Config) ->
+ MIX = mix_jid(Config),
+ Room = mix_room_jid(Config),
+ MyJID = my_jid(Config),
+ MyBareJID = jid:remove_resource(MyJID),
+ #iq{type = result,
+ sub_els =
+ [#disco_info{
+ identities = [#identity{category = <<"conference">>,
+ type = <<"text">>}],
+ xdata = [#xdata{type = result, fields = XFields}]}]} =
+ send_recv(Config, #iq{type = get, to = MIX, sub_els = [#disco_info{}]}),
+ true = lists:any(
+ fun(#xdata_field{var = <<"FORM_TYPE">>,
+ values = [?NS_MIX_SERVICEINFO_0]}) -> true;
+ (_) -> false
+ end, XFields),
+ %% Joining
+ Nodes = [?NS_MIX_NODES_MESSAGES, ?NS_MIX_NODES_PRESENCE,
+ ?NS_MIX_NODES_PARTICIPANTS, ?NS_MIX_NODES_SUBJECT,
+ ?NS_MIX_NODES_CONFIG],
+ #iq{type = result,
+ sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]} =
+ send_recv(Config, #iq{type = set, to = Room,
+ sub_els = [#mix_join{subscribe = Nodes}]}),
+ #message{from = Room,
+ sub_els =
+ [#ps_event{
+ items = #ps_items{
+ node = ?NS_MIX_NODES_PARTICIPANTS,
+ items = [#ps_item{
+ id = ParticipantID,
+ xml_els = [PXML]}]}}]} =
+ recv_message(Config),
+ #mix_participant{jid = MyBareJID} = xmpp:decode(PXML),
+ %% Coming online
+ PresenceID = randoms:get_string(),
+ Presence = xmpp:encode(#presence{}),
+ #iq{type = result,
+ sub_els =
+ [#pubsub{
+ publish = #ps_publish{
+ node = ?NS_MIX_NODES_PRESENCE,
+ items = [#ps_item{id = PresenceID}]}}]} =
+ send_recv(
+ Config,
+ #iq{type = set, to = Room,
+ sub_els =
+ [#pubsub{
+ publish = #ps_publish{
+ node = ?NS_MIX_NODES_PRESENCE,
+ items = [#ps_item{
+ id = PresenceID,
+ xml_els = [Presence]}]}}]}),
+ #message{from = Room,
+ sub_els =
+ [#ps_event{
+ items = #ps_items{
+ node = ?NS_MIX_NODES_PRESENCE,
+ items = [#ps_item{
+ id = PresenceID,
+ xml_els = [Presence]}]}}]} =
+ recv_message(Config),
+ %% Coming offline
+ send(Config, #presence{type = unavailable, to = Room}),
+ %% Receiving presence retract event
+ #message{from = Room,
+ sub_els = [#ps_event{
+ items = #ps_items{
+ node = ?NS_MIX_NODES_PRESENCE,
+ retract = PresenceID}}]} =
+ recv_message(Config),
+ %% Leaving
+ #iq{type = result, sub_els = []} =
+ send_recv(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}),
+ #message{from = Room,
+ sub_els =
+ [#ps_event{
+ items = #ps_items{
+ node = ?NS_MIX_NODES_PARTICIPANTS,
+ retract = ParticipantID}}]} =
+ recv_message(Config),
+ put_event(Config, disconnect),
+ disconnect(Config).
+
+all_slave(Config) ->
+ disconnect = get_event(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("mix_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("mix_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("mix_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("mix_" ++ atom_to_list(T) ++ "_slave")]}.
diff --git a/test/mod_legacy.erl b/test/mod_legacy.erl
index 6024acfe..dba97755 100644
--- a/test/mod_legacy.erl
+++ b/test/mod_legacy.erl
@@ -10,7 +10,7 @@
-behaviour(gen_mod).
%% API
--export([start/2, stop/1, process_iq/3]).
+-export([start/2, stop/1, mod_opt_type/1, depends/2, process_iq/3]).
-include("jlib.hrl").
%%%===================================================================
@@ -25,6 +25,12 @@ start(Host, Opts) ->
stop(Host) ->
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?MODULE).
+mod_opt_type(_) ->
+ [].
+
+depends(_, _) ->
+ [].
+
%%%===================================================================
%%% Internal functions
%%%===================================================================
diff --git a/test/muc_tests.erl b/test/muc_tests.erl
index 709a82a2..d8e6dd8f 100644
--- a/test/muc_tests.erl
+++ b/test/muc_tests.erl
@@ -11,10 +11,10 @@
%% API
-compile(export_all).
-import(suite, [recv_presence/1, send_recv/2, my_jid/1, muc_room_jid/1,
- send/2, recv_message/1, recv_iq/1, recv/1, muc_jid/1,
+ send/2, recv_message/1, recv_iq/1, muc_jid/1,
alt_room_jid/1, wait_for_slave/1, wait_for_master/1,
disconnect/1, put_event/2, get_event/1, peer_muc_jid/1,
- my_muc_jid/1, get_features/2, flush/1, set_opt/3]).
+ my_muc_jid/1, get_features/2, set_opt/3]).
-include("suite.hrl").
-include("jid.hrl").
@@ -26,21 +26,21 @@
%%%===================================================================
single_cases() ->
{muc_single, [sequence],
- [muc_service_presence_error,
- muc_service_message_error,
- muc_service_unknown_ns_iq_error,
- muc_service_iq_set_error,
- muc_service_improper_iq_error,
- muc_service_features,
- muc_service_disco_info_node_error,
- muc_service_disco_items,
- muc_service_unique,
- muc_service_vcard,
- muc_configure_non_existent,
- muc_cancel_configure_non_existent,
- muc_service_subscriptions]}.
-
-muc_service_presence_error(Config) ->
+ [single_test(service_presence_error),
+ single_test(service_message_error),
+ single_test(service_unknown_ns_iq_error),
+ single_test(service_iq_set_error),
+ single_test(service_improper_iq_error),
+ single_test(service_features),
+ single_test(service_disco_info_node_error),
+ single_test(service_disco_items),
+ single_test(service_unique),
+ single_test(service_vcard),
+ single_test(configure_non_existent),
+ single_test(cancel_configure_non_existent),
+ single_test(service_subscriptions)]}.
+
+service_presence_error(Config) ->
Service = muc_jid(Config),
ServiceResource = jid:replace_resource(Service, randoms:get_string()),
lists:foreach(
@@ -56,7 +56,7 @@ muc_service_presence_error(Config) ->
end, [Service, ServiceResource]),
disconnect(Config).
-muc_service_message_error(Config) ->
+service_message_error(Config) ->
Service = muc_jid(Config),
send(Config, #message{type = error, to = Service}),
lists:foreach(
@@ -75,7 +75,7 @@ muc_service_message_error(Config) ->
end, [chat, normal, headline, groupchat]),
disconnect(Config).
-muc_service_unknown_ns_iq_error(Config) ->
+service_unknown_ns_iq_error(Config) ->
Service = muc_jid(Config),
ServiceResource = jid:replace_resource(Service, randoms:get_string()),
lists:foreach(
@@ -93,7 +93,7 @@ muc_service_unknown_ns_iq_error(Config) ->
end, [Service, ServiceResource]),
disconnect(Config).
-muc_service_iq_set_error(Config) ->
+service_iq_set_error(Config) ->
Service = muc_jid(Config),
lists:foreach(
fun(SubEl) ->
@@ -108,7 +108,7 @@ muc_service_iq_set_error(Config) ->
#muc_unique{}, #muc_subscriptions{}]),
disconnect(Config).
-muc_service_improper_iq_error(Config) ->
+service_improper_iq_error(Config) ->
Service = muc_jid(Config),
lists:foreach(
fun(SubEl) ->
@@ -127,7 +127,7 @@ muc_service_improper_iq_error(Config) ->
#vcard_email{}, #muc_subscribe{nick = ?config(nick, Config)}]),
disconnect(Config).
-muc_service_features(Config) ->
+service_features(Config) ->
ServerHost = ?config(server_host, Config),
MUC = muc_jid(Config),
Features = sets:from_list(get_features(Config, MUC)),
@@ -144,7 +144,7 @@ muc_service_features(Config) ->
true = sets:is_subset(RequiredFeatures, Features),
disconnect(Config).
-muc_service_disco_info_node_error(Config) ->
+service_disco_info_node_error(Config) ->
MUC = muc_jid(Config),
Node = randoms:get_string(),
#iq{type = error} = Err =
@@ -153,7 +153,7 @@ muc_service_disco_info_node_error(Config) ->
#stanza_error{reason = 'item-not-found'} = xmpp:get_error(Err),
disconnect(Config).
-muc_service_disco_items(Config) ->
+service_disco_items(Config) ->
#jid{server = Service} = muc_jid(Config),
Rooms = lists:sort(
lists:map(
@@ -163,25 +163,25 @@ muc_service_disco_items(Config) ->
end, lists:seq(1, 5))),
lists:foreach(
fun(Room) ->
- ok = muc_join_new(Config, Room)
+ ok = join_new(Config, Room)
end, Rooms),
- Items = muc_disco_items(Config),
+ Items = disco_items(Config),
Rooms = [J || #disco_item{jid = J} <- Items],
lists:foreach(
fun(Room) ->
- ok = muc_leave(Config, Room)
+ ok = leave(Config, Room)
end, Rooms),
- [] = muc_disco_items(Config),
+ [] = disco_items(Config),
disconnect(Config).
-muc_service_vcard(Config) ->
+service_vcard(Config) ->
MUC = muc_jid(Config),
ct:comment("Retreiving vCard from ~s", [jid:to_string(MUC)]),
#iq{type = result, sub_els = [#vcard_temp{}]} =
send_recv(Config, #iq{type = get, to = MUC, sub_els = [#vcard_temp{}]}),
disconnect(Config).
-muc_service_unique(Config) ->
+service_unique(Config) ->
MUC = muc_jid(Config),
ct:comment("Requesting muc unique from ~s", [jid:to_string(MUC)]),
#iq{type = result, sub_els = [#muc_unique{name = Name}]} =
@@ -190,11 +190,11 @@ muc_service_unique(Config) ->
<<_, _/binary>> = Name,
disconnect(Config).
-muc_configure_non_existent(Config) ->
- [_|_] = muc_get_config(Config),
+configure_non_existent(Config) ->
+ [_|_] = get_config(Config),
disconnect(Config).
-muc_cancel_configure_non_existent(Config) ->
+cancel_configure_non_existent(Config) ->
Room = muc_room_jid(Config),
#iq{type = result, sub_els = []} =
send_recv(Config,
@@ -202,7 +202,7 @@ muc_cancel_configure_non_existent(Config) ->
sub_els = [#muc_owner{config = #xdata{type = cancel}}]}),
disconnect(Config).
-muc_service_subscriptions(Config) ->
+service_subscriptions(Config) ->
MUC = #jid{server = Service} = muc_jid(Config),
Rooms = lists:sort(
lists:map(
@@ -212,9 +212,9 @@ muc_service_subscriptions(Config) ->
end, lists:seq(1, 5))),
lists:foreach(
fun(Room) ->
- ok = muc_join_new(Config, Room),
- [104] = muc_set_config(Config, [{allow_subscription, true}], Room),
- [] = muc_subscribe(Config, [], Room)
+ ok = join_new(Config, Room),
+ [104] = set_config(Config, [{allow_subscription, true}], Room),
+ [] = subscribe(Config, [], Room)
end, Rooms),
#iq{type = result, sub_els = [#muc_subscriptions{list = JIDs}]} =
send_recv(Config, #iq{type = get, to = MUC,
@@ -222,8 +222,8 @@ muc_service_subscriptions(Config) ->
Rooms = lists:sort(JIDs),
lists:foreach(
fun(Room) ->
- ok = muc_unsubscribe(Config, Room),
- ok = muc_leave(Config, Room)
+ ok = unsubscribe(Config, Room),
+ ok = leave(Config, Room)
end, Rooms),
disconnect(Config).
@@ -232,61 +232,61 @@ muc_service_subscriptions(Config) ->
%%%===================================================================
master_slave_cases() ->
{muc_master_slave, [sequence],
- [master_slave_test(muc_register),
- master_slave_test(muc_groupchat_msg),
- master_slave_test(muc_private_msg),
- master_slave_test(muc_set_subject),
- master_slave_test(muc_history),
- master_slave_test(muc_invite),
- master_slave_test(muc_invite_members_only),
- master_slave_test(muc_invite_password_protected),
- master_slave_test(muc_voice_request),
- master_slave_test(muc_change_role),
- master_slave_test(muc_kick),
- master_slave_test(muc_change_affiliation),
- master_slave_test(muc_destroy),
- master_slave_test(muc_vcard),
- master_slave_test(muc_nick_change),
- master_slave_test(muc_config_title_desc),
- master_slave_test(muc_config_public_list),
- master_slave_test(muc_config_password),
- master_slave_test(muc_config_whois),
- master_slave_test(muc_config_members_only),
- master_slave_test(muc_config_moderated),
- master_slave_test(muc_config_private_messages),
- master_slave_test(muc_config_query),
- master_slave_test(muc_config_allow_invites),
- master_slave_test(muc_config_visitor_status),
- master_slave_test(muc_config_allow_voice_requests),
- master_slave_test(muc_config_voice_request_interval),
- master_slave_test(muc_config_visitor_nickchange),
- master_slave_test(muc_join_conflict)]}.
-
-muc_join_conflict_master(Config) ->
- ok = muc_join_new(Config),
+ [master_slave_test(register),
+ master_slave_test(groupchat_msg),
+ master_slave_test(private_msg),
+ master_slave_test(set_subject),
+ master_slave_test(history),
+ master_slave_test(invite),
+ master_slave_test(invite_members_only),
+ master_slave_test(invite_password_protected),
+ master_slave_test(voice_request),
+ master_slave_test(change_role),
+ master_slave_test(kick),
+ master_slave_test(change_affiliation),
+ master_slave_test(destroy),
+ master_slave_test(vcard),
+ master_slave_test(nick_change),
+ master_slave_test(config_title_desc),
+ master_slave_test(config_public_list),
+ master_slave_test(config_password),
+ master_slave_test(config_whois),
+ master_slave_test(config_members_only),
+ master_slave_test(config_moderated),
+ master_slave_test(config_private_messages),
+ master_slave_test(config_query),
+ master_slave_test(config_allow_invites),
+ master_slave_test(config_visitor_status),
+ master_slave_test(config_allow_voice_requests),
+ master_slave_test(config_voice_request_interval),
+ master_slave_test(config_visitor_nickchange),
+ master_slave_test(join_conflict)]}.
+
+join_conflict_master(Config) ->
+ ok = join_new(Config),
put_event(Config, join),
ct:comment("Waiting for 'leave' command from the slave"),
leave = get_event(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_join_conflict_slave(Config) ->
+join_conflict_slave(Config) ->
NewConfig = set_opt(nick, ?config(peer_nick, Config), Config),
ct:comment("Waiting for 'join' command from the master"),
join = get_event(Config),
ct:comment("Fail trying to join the room with conflicting nick"),
- #stanza_error{reason = 'conflict'} = muc_join(NewConfig),
+ #stanza_error{reason = 'conflict'} = join(NewConfig),
put_event(Config, leave),
disconnect(NewConfig).
-muc_groupchat_msg_master(Config) ->
+groupchat_msg_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
lists:foreach(
fun(I) ->
Body = xmpp:mk_text(integer_to_binary(I)),
@@ -299,29 +299,29 @@ muc_groupchat_msg_master(Config) ->
role = none,
affiliation = none}]} =
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_groupchat_msg_slave(Config) ->
+groupchat_msg_slave(Config) ->
Room = muc_room_jid(Config),
PeerNick = ?config(master_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
lists:foreach(
fun(I) ->
Body = xmpp:mk_text(integer_to_binary(I)),
#message{type = groupchat, from = PeerNickJID,
body = Body} = recv_message(Config)
end, lists:seq(1, 5)),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_private_msg_master(Config) ->
+private_msg_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
lists:foreach(
fun(I) ->
Body = xmpp:mk_text(integer_to_binary(I)),
@@ -336,31 +336,31 @@ muc_private_msg_master(Config) ->
send(Config, #message{type = chat, to = PeerNickJID}),
#message{from = PeerNickJID, type = error} = ErrMsg = recv_message(Config),
#stanza_error{reason = 'item-not-found'} = xmpp:get_error(ErrMsg),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_private_msg_slave(Config) ->
+private_msg_slave(Config) ->
Room = muc_room_jid(Config),
PeerNick = ?config(master_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
lists:foreach(
fun(I) ->
Body = xmpp:mk_text(integer_to_binary(I)),
#message{type = chat, from = PeerNickJID,
body = Body} = recv_message(Config)
end, lists:seq(1, 5)),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_set_subject_master(Config) ->
+set_subject_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
Subject1 = xmpp:mk_text(?config(room_subject, Config)),
Subject2 = xmpp:mk_text(<<"new-", (?config(room_subject, Config))/binary>>),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
ct:comment("Setting 1st subject"),
send(Config, #message{type = groupchat, to = Room,
subject = Subject1}),
@@ -380,30 +380,30 @@ muc_set_subject_master(Config) ->
#message{type = groupchat, from = PeerNickJID,
subject = Subject1} = recv_message(Config),
ct:comment("Disallow subject change"),
- [104] = muc_set_config(Config, [{changesubject, false}]),
+ [104] = set_config(Config, [{changesubject, false}]),
ct:comment("Waiting for the slave to leave"),
#muc_user{items = [#muc_item{jid = PeerJID,
role = none,
affiliation = none}]} =
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_set_subject_slave(Config) ->
+set_subject_slave(Config) ->
Room = muc_room_jid(Config),
MyNickJID = my_muc_jid(Config),
PeerNick = ?config(master_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
Subject1 = xmpp:mk_text(?config(room_subject, Config)),
Subject2 = xmpp:mk_text(<<"new-", (?config(room_subject, Config))/binary>>),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
ct:comment("Receiving 1st subject set by the master"),
#message{type = groupchat, from = PeerNickJID,
subject = Subject1} = recv_message(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
ct:comment("Waiting for 'join' command from the master"),
join = get_event(Config),
- {[], SubjMsg2, _} = muc_join(Config),
+ {[], SubjMsg2, _} = join(Config),
ct:comment("Checking if the master has set 2nd subject during our absence"),
#message{type = groupchat, from = PeerNickJID,
subject = Subject2} = SubjMsg2,
@@ -412,15 +412,15 @@ muc_set_subject_slave(Config) ->
#message{type = groupchat, from = MyNickJID,
subject = Subject1} = recv_message(Config),
ct:comment("Waiting for the master to disallow subject change"),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Fail trying to change the subject"),
send(Config, #message{to = Room, type = groupchat, subject = Subject2}),
#message{from = Room, type = error} = ErrMsg = recv_message(Config),
#stanza_error{reason = 'forbidden'} = xmpp:get_error(ErrMsg),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_history_master(Config) ->
+history_master(Config) ->
Room = muc_room_jid(Config),
ServerHost = ?config(server_host, Config),
MyNick = ?config(nick, Config),
@@ -429,7 +429,7 @@ muc_history_master(Config) ->
Size = gen_mod:get_module_opt(ServerHost, mod_muc, history_size,
fun(I) when is_integer(I), I>=0 -> I end,
20),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
ct:comment("Putting ~p+1 messages in the history", [Size]),
%% Only Size messages will be stored
lists:foreach(
@@ -448,10 +448,10 @@ muc_history_master(Config) ->
available, unavailable,
available, unavailable,
available, unavailable]),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_history_slave(Config) ->
+history_slave(Config) ->
Room = muc_room_jid(Config),
PeerNick = ?config(peer_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
@@ -461,45 +461,45 @@ muc_history_slave(Config) ->
20),
ct:comment("Waiting for 'join' command from the master"),
join = get_event(Config),
- {History, _, _} = muc_join(Config),
+ {History, _, _} = join(Config),
ct:comment("Checking ordering of history events"),
BodyList = [binary_to_integer(xmpp:get_text(Body))
|| #message{type = groupchat, from = From,
body = Body} <- History,
From == PeerNickJID],
BodyList = lists:seq(1, Size),
- ok = muc_leave(Config),
+ ok = leave(Config),
%% If the client wishes to receive no history, it MUST set the 'maxchars'
%% attribute to a value of "0" (zero)
%% (http://xmpp.org/extensions/xep-0045.html#enter-managehistory)
ct:comment("Checking if maxchars=0 yields to no history"),
- {[], _, _} = muc_join(Config, #muc{history = #muc_history{maxchars = 0}}),
- ok = muc_leave(Config),
+ {[], _, _} = join(Config, #muc{history = #muc_history{maxchars = 0}}),
+ ok = leave(Config),
ct:comment("Receiving only 10 last stanzas"),
- {History10, _, _} = muc_join(Config,
+ {History10, _, _} = join(Config,
#muc{history = #muc_history{maxstanzas = 10}}),
BodyList10 = [binary_to_integer(xmpp:get_text(Body))
|| #message{type = groupchat, from = From,
body = Body} <- History10,
From == PeerNickJID],
BodyList10 = lists:nthtail(Size-10, lists:seq(1, Size)),
- ok = muc_leave(Config),
+ ok = leave(Config),
#delay{stamp = TS} = xmpp:get_subtag(hd(History), #delay{}),
ct:comment("Receiving all history without the very first element"),
- {HistoryWithoutFirst, _, _} = muc_join(Config,
+ {HistoryWithoutFirst, _, _} = join(Config,
#muc{history = #muc_history{since = TS}}),
BodyListWithoutFirst = [binary_to_integer(xmpp:get_text(Body))
|| #message{type = groupchat, from = From,
body = Body} <- HistoryWithoutFirst,
From == PeerNickJID],
BodyListWithoutFirst = lists:nthtail(1, lists:seq(1, Size)),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_invite_master(Config) ->
+invite_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(peer, Config),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
wait_for_slave(Config),
%% Inviting the peer
send(Config, #message{to = Room, type = normal,
@@ -510,10 +510,10 @@ muc_invite_master(Config) ->
#message{from = Room} = DeclineMsg = recv_message(Config),
#muc_user{decline = #muc_decline{from = PeerJID}} =
xmpp:get_subtag(DeclineMsg, #muc_user{}),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_invite_slave(Config) ->
+invite_slave(Config) ->
Room = muc_room_jid(Config),
wait_for_master(Config),
PeerJID = ?config(master, Config),
@@ -527,12 +527,12 @@ muc_invite_slave(Config) ->
decline = #muc_decline{to = PeerJID}}]}),
disconnect(Config).
-muc_invite_members_only_master(Config) ->
+invite_members_only_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
%% Setting the room to members-only
- [_|_] = muc_set_config(Config, [{membersonly, true}]),
+ [_|_] = set_config(Config, [{membersonly, true}]),
wait_for_slave(Config),
%% Inviting the peer
send(Config, #message{to = Room, type = normal,
@@ -543,22 +543,22 @@ muc_invite_members_only_master(Config) ->
#message{from = Room, type = normal} = AffMsg = recv_message(Config),
#muc_user{items = [#muc_item{jid = PeerJID, affiliation = member}]} =
xmpp:get_subtag(AffMsg, #muc_user{}),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_invite_members_only_slave(Config) ->
+invite_members_only_slave(Config) ->
Room = muc_room_jid(Config),
wait_for_master(Config),
%% Receiving invitation
#message{from = Room, type = normal} = recv_message(Config),
disconnect(Config).
-muc_invite_password_protected_master(Config) ->
+invite_password_protected_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
Password = randoms:get_string(),
- ok = muc_join_new(Config),
- [104] = muc_set_config(Config, [{passwordprotectedroom, true},
+ ok = join_new(Config),
+ [104] = set_config(Config, [{passwordprotectedroom, true},
{roomsecret, Password}]),
put_event(Config, Password),
%% Inviting the peer
@@ -567,10 +567,10 @@ muc_invite_password_protected_master(Config) ->
[#muc_user{
invites =
[#muc_invite{to = PeerJID}]}]}),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_invite_password_protected_slave(Config) ->
+invite_password_protected_slave(Config) ->
Room = muc_room_jid(Config),
Password = get_event(Config),
%% Receiving invitation
@@ -578,13 +578,13 @@ muc_invite_password_protected_slave(Config) ->
#muc_user{password = Password} = xmpp:get_subtag(Msg, #muc_user{}),
disconnect(Config).
-muc_voice_request_master(Config) ->
+voice_request_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_join_new(Config),
- [104] = muc_set_config(Config, [{members_by_default, false}]),
+ ok = join_new(Config),
+ [104] = set_config(Config, [{members_by_default, false}]),
wait_for_slave(Config),
#muc_user{
items = [#muc_item{role = visitor,
@@ -610,16 +610,16 @@ muc_voice_request_master(Config) ->
recv_muc_presence(Config, PeerNickJID, available),
ct:comment("Waiting for the slave to leave"),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_voice_request_slave(Config) ->
+voice_request_slave(Config) ->
Room = muc_room_jid(Config),
MyJID = my_jid(Config),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
wait_for_master(Config),
- {[], _, _} = muc_join(Config, visitor),
+ {[], _, _} = join(Config, visitor),
ct:comment("Requesting voice"),
Fs = muc_request:encode([{role, participant}]),
X = #xdata{type = submit, fields = Fs},
@@ -630,17 +630,17 @@ muc_voice_request_slave(Config) ->
jid = MyJID,
affiliation = none}]} =
recv_muc_presence(Config, MyNickJID, available),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_change_role_master(Config) ->
+change_role_master(Config) ->
Room = muc_room_jid(Config),
MyJID = my_jid(Config),
MyNick = ?config(nick, Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
ct:comment("Waiting for the slave to join"),
wait_for_slave(Config),
#muc_user{items = [#muc_item{role = participant,
@@ -650,7 +650,7 @@ muc_change_role_master(Config) ->
lists:foreach(
fun(Role) ->
ct:comment("Checking if the slave is not in the roles list"),
- case muc_get_role(Config, Role) of
+ case get_role(Config, Role) of
[#muc_item{jid = MyJID, affiliation = owner,
role = moderator, nick = MyNick}] when Role == moderator ->
ok;
@@ -659,7 +659,7 @@ muc_change_role_master(Config) ->
end,
Reason = randoms:get_string(),
put_event(Config, {Role, Reason}),
- ok = muc_set_role(Config, Role, Reason),
+ ok = set_role(Config, Role, Reason),
ct:comment("Receiving role change to ~s", [Role]),
#muc_user{
items = [#muc_item{role = Role,
@@ -667,19 +667,19 @@ muc_change_role_master(Config) ->
reason = Reason}]} =
recv_muc_presence(Config, PeerNickJID, available),
[#muc_item{role = Role, affiliation = none,
- nick = PeerNick}|_] = muc_get_role(Config, Role)
+ nick = PeerNick}|_] = get_role(Config, Role)
end, [visitor, participant, moderator]),
put_event(Config, disconnect),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_change_role_slave(Config) ->
+change_role_slave(Config) ->
wait_for_master(Config),
- {[], _, _} = muc_join(Config),
- muc_change_role_slave(Config, get_event(Config)).
+ {[], _, _} = join(Config),
+ change_role_slave(Config, get_event(Config)).
-muc_change_role_slave(Config, {Role, Reason}) ->
+change_role_slave(Config, {Role, Reason}) ->
Room = muc_room_jid(Config),
MyNick = ?config(slave_nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
@@ -690,12 +690,12 @@ muc_change_role_slave(Config, {Role, Reason}) ->
reason = Reason}]} =
recv_muc_presence(Config, MyNickJID, available),
true = lists:member(110, Codes),
- muc_change_role_slave(Config, get_event(Config));
-muc_change_role_slave(Config, disconnect) ->
- ok = muc_leave(Config),
+ change_role_slave(Config, get_event(Config));
+change_role_slave(Config, disconnect) ->
+ ok = leave(Config),
disconnect(Config).
-muc_change_affiliation_master(Config) ->
+change_affiliation_master(Config) ->
Room = muc_room_jid(Config),
MyJID = my_jid(Config),
MyBareJID = jid:remove_resource(MyJID),
@@ -704,7 +704,7 @@ muc_change_affiliation_master(Config) ->
PeerBareJID = jid:remove_resource(PeerJID),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
ct:comment("Waiting for the slave to join"),
wait_for_slave(Config),
#muc_user{items = [#muc_item{role = participant,
@@ -714,7 +714,7 @@ muc_change_affiliation_master(Config) ->
lists:foreach(
fun({Aff, Role, Status}) ->
ct:comment("Checking if slave is not in affiliation list"),
- case muc_get_affiliation(Config, Aff) of
+ case get_affiliation(Config, Aff) of
[#muc_item{jid = MyBareJID,
affiliation = owner}] when Aff == owner ->
ok;
@@ -723,7 +723,7 @@ muc_change_affiliation_master(Config) ->
end,
Reason = randoms:get_string(),
put_event(Config, {Aff, Role, Status, Reason}),
- ok = muc_set_affiliation(Config, Aff, Reason),
+ ok = set_affiliation(Config, Aff, Reason),
ct:comment("Receiving affiliation change to ~s", [Aff]),
#muc_user{
items = [#muc_item{role = Role,
@@ -737,7 +737,7 @@ muc_change_affiliation_master(Config) ->
true ->
ok
end,
- Affs = muc_get_affiliation(Config, Aff),
+ Affs = get_affiliation(Config, Aff),
ct:comment("Checking if the affiliation was correctly set"),
case lists:keyfind(PeerBareJID, #muc_item.jid, Affs) of
false when Aff == none ->
@@ -748,15 +748,15 @@ muc_change_affiliation_master(Config) ->
end, [{member, participant, available}, {none, participant, available},
{admin, moderator, available}, {owner, moderator, available},
{outcast, none, unavailable}]),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_change_affiliation_slave(Config) ->
+change_affiliation_slave(Config) ->
wait_for_master(Config),
- {[], _, _} = muc_join(Config),
- muc_change_affiliation_slave(Config, get_event(Config)).
+ {[], _, _} = join(Config),
+ change_affiliation_slave(Config, get_event(Config)).
-muc_change_affiliation_slave(Config, {Aff, Role, Status, Reason}) ->
+change_affiliation_slave(Config, {Aff, Role, Status, Reason}) ->
Room = muc_room_jid(Config),
PeerNick = ?config(master_nick, Config),
MyNick = ?config(nick, Config),
@@ -776,17 +776,17 @@ muc_change_affiliation_slave(Config, {Aff, Role, Status, Reason}) ->
#muc_actor{nick = PeerNick} = Actor,
disconnect(Config);
true ->
- muc_change_affiliation_slave(Config, get_event(Config))
+ change_affiliation_slave(Config, get_event(Config))
end.
-muc_kick_master(Config) ->
+kick_master(Config) ->
Room = muc_room_jid(Config),
MyNick = ?config(nick, Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
Reason = <<"Testing">>,
- ok = muc_join_new(Config),
+ ok = join_new(Config),
ct:comment("Waiting for the slave to join"),
wait_for_slave(Config),
#muc_user{items = [#muc_item{role = participant,
@@ -794,9 +794,9 @@ muc_kick_master(Config) ->
affiliation = none}]} =
recv_muc_presence(Config, PeerNickJID, available),
[#muc_item{role = participant, affiliation = none,
- nick = PeerNick}|_] = muc_get_role(Config, participant),
+ nick = PeerNick}|_] = get_role(Config, participant),
ct:comment("Kicking slave"),
- ok = muc_set_role(Config, none, Reason),
+ ok = set_role(Config, none, Reason),
ct:comment("Receiving role change to 'none'"),
#muc_user{
status_codes = Codes,
@@ -805,20 +805,20 @@ muc_kick_master(Config) ->
actor = #muc_actor{nick = MyNick},
reason = Reason}]} =
recv_muc_presence(Config, PeerNickJID, unavailable),
- [] = muc_get_role(Config, participant),
+ [] = get_role(Config, participant),
ct:comment("Checking if the code is '307' (kicked)"),
true = lists:member(307, Codes),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_kick_slave(Config) ->
+kick_slave(Config) ->
Room = muc_room_jid(Config),
PeerNick = ?config(master_nick, Config),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
Reason = <<"Testing">>,
wait_for_master(Config),
- {[], _, _} = muc_join(Config),
+ {[], _, _} = join(Config),
ct:comment("Receiving role change to 'none'"),
#muc_user{status_codes = Codes,
items = [#muc_item{role = none,
@@ -832,7 +832,7 @@ muc_kick_slave(Config) ->
true = lists:member(307, Codes),
disconnect(Config).
-muc_destroy_master(Config) ->
+destroy_master(Config) ->
Reason = <<"Testing">>,
Room = muc_room_jid(Config),
AltRoom = alt_room_jid(Config),
@@ -841,7 +841,7 @@ muc_destroy_master(Config) ->
PeerNickJID = jid:replace_resource(Room, PeerNick),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
ct:comment("Waiting for slave to join"),
wait_for_slave(Config),
#muc_user{items = [#muc_item{role = participant,
@@ -849,7 +849,7 @@ muc_destroy_master(Config) ->
affiliation = none}]} =
recv_muc_presence(Config, PeerNickJID, available),
wait_for_slave(Config),
- ok = muc_destroy(Config, Reason),
+ ok = destroy(Config, Reason),
ct:comment("Receiving destruction presence"),
#muc_user{items = [#muc_item{role = none,
affiliation = none}],
@@ -858,15 +858,15 @@ muc_destroy_master(Config) ->
recv_muc_presence(Config, MyNickJID, unavailable),
disconnect(Config).
-muc_destroy_slave(Config) ->
+destroy_slave(Config) ->
Reason = <<"Testing">>,
Room = muc_room_jid(Config),
AltRoom = alt_room_jid(Config),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
wait_for_master(Config),
- {[], _, _} = muc_join(Config),
- #stanza_error{reason = 'forbidden'} = muc_destroy(Config, Reason),
+ {[], _, _} = join(Config),
+ #stanza_error{reason = 'forbidden'} = destroy(Config, Reason),
wait_for_master(Config),
ct:comment("Receiving destruction presence"),
#muc_user{items = [#muc_item{role = none,
@@ -876,43 +876,43 @@ muc_destroy_slave(Config) ->
recv_muc_presence(Config, MyNickJID, unavailable),
disconnect(Config).
-muc_vcard_master(Config) ->
+vcard_master(Config) ->
Room = muc_room_jid(Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
FN = randoms:get_string(),
VCard = #vcard_temp{fn = FN},
- ok = muc_join_new(Config),
+ ok = join_new(Config),
ct:comment("Waiting for slave to join"),
wait_for_slave(Config),
#muc_user{items = [#muc_item{role = participant,
affiliation = none}]} =
recv_muc_presence(Config, PeerNickJID, available),
- #stanza_error{reason = 'item-not-found'} = muc_get_vcard(Config),
- ok = muc_set_vcard(Config, VCard),
- VCard = muc_get_vcard(Config),
+ #stanza_error{reason = 'item-not-found'} = get_vcard(Config),
+ ok = set_vcard(Config, VCard),
+ VCard = get_vcard(Config),
put_event(Config, VCard),
recv_muc_presence(Config, PeerNickJID, unavailable),
leave = get_event(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_vcard_slave(Config) ->
+vcard_slave(Config) ->
wait_for_master(Config),
- {[], _, _} = muc_join(Config),
+ {[], _, _} = join(Config),
VCard = get_event(Config),
- VCard = muc_get_vcard(Config),
- #stanza_error{reason = 'forbidden'} = muc_set_vcard(Config, VCard),
- ok = muc_leave(Config),
- VCard = muc_get_vcard(Config),
+ VCard = get_vcard(Config),
+ #stanza_error{reason = 'forbidden'} = set_vcard(Config, VCard),
+ ok = leave(Config),
+ VCard = get_vcard(Config),
put_event(Config, leave),
disconnect(Config).
-muc_nick_change_master(Config) ->
+nick_change_master(Config) ->
NewNick = randoms:get_string(),
PeerJID = ?config(peer, Config),
PeerNickJID = peer_muc_jid(Config),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
put_event(Config, {new_nick, NewNick}),
ct:comment("Waiting for nickchange presence from the slave"),
#muc_user{status_codes = Codes,
@@ -926,13 +926,13 @@ muc_nick_change_master(Config) ->
recv_muc_presence(Config, PeerNewNickJID, available),
ct:comment("Waiting for the slave to leave"),
recv_muc_presence(Config, PeerNewNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_nick_change_slave(Config) ->
+nick_change_slave(Config) ->
MyJID = my_jid(Config),
MyNickJID = my_muc_jid(Config),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
{new_nick, NewNick} = get_event(Config),
MyNewNickJID = jid:replace_resource(MyNickJID, NewNick),
ct:comment("Sending new presence"),
@@ -955,131 +955,131 @@ muc_nick_change_slave(Config) ->
ct:comment("Checking if code '110' (self-presence) is set"),
lists:member(110, Codes2),
NewConfig = set_opt(nick, NewNick, Config),
- ok = muc_leave(NewConfig),
+ ok = leave(NewConfig),
disconnect(NewConfig).
-muc_config_title_desc_master(Config) ->
+config_title_desc_master(Config) ->
Title = randoms:get_string(),
Desc = randoms:get_string(),
Room = muc_room_jid(Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_master_join(Config),
- [104] = muc_set_config(Config, [{roomname, Title}, {roomdesc, Desc}]),
- RoomCfg = muc_get_config(Config),
+ ok = master_join(Config),
+ [104] = set_config(Config, [{roomname, Title}, {roomdesc, Desc}]),
+ RoomCfg = get_config(Config),
Title = proplists:get_value(roomname, RoomCfg),
Desc = proplists:get_value(roomdesc, RoomCfg),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_title_desc_slave(Config) ->
- {[], _, _} = muc_slave_join(Config),
- [104] = muc_recv_config_change_message(Config),
- ok = muc_leave(Config),
+config_title_desc_slave(Config) ->
+ {[], _, _} = slave_join(Config),
+ [104] = recv_config_change_message(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_public_list_master(Config) ->
+config_public_list_master(Config) ->
Room = muc_room_jid(Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
wait_for_slave(Config),
recv_muc_presence(Config, PeerNickJID, available),
lists:member(<<"muc_public">>, get_features(Config, Room)),
- [104] = muc_set_config(Config, [{public_list, false},
+ [104] = set_config(Config, [{public_list, false},
{publicroom, false}]),
recv_muc_presence(Config, PeerNickJID, unavailable),
lists:member(<<"muc_hidden">>, get_features(Config, Room)),
wait_for_slave(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_public_list_slave(Config) ->
+config_public_list_slave(Config) ->
Room = muc_room_jid(Config),
wait_for_master(Config),
PeerNick = ?config(peer_nick, Config),
PeerNickJID = peer_muc_jid(Config),
- [#disco_item{jid = Room}] = muc_disco_items(Config),
+ [#disco_item{jid = Room}] = disco_items(Config),
[#disco_item{jid = PeerNickJID,
- name = PeerNick}] = muc_disco_room_items(Config),
- {[], _, _} = muc_join(Config),
- [104] = muc_recv_config_change_message(Config),
- ok = muc_leave(Config),
- [] = muc_disco_items(Config),
- [] = muc_disco_room_items(Config),
+ name = PeerNick}] = disco_room_items(Config),
+ {[], _, _} = join(Config),
+ [104] = recv_config_change_message(Config),
+ ok = leave(Config),
+ [] = disco_items(Config),
+ [] = disco_room_items(Config),
wait_for_master(Config),
disconnect(Config).
-muc_config_password_master(Config) ->
+config_password_master(Config) ->
Password = randoms:get_string(),
Room = muc_room_jid(Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
lists:member(<<"muc_unsecured">>, get_features(Config, Room)),
- [104] = muc_set_config(Config, [{passwordprotectedroom, true},
+ [104] = set_config(Config, [{passwordprotectedroom, true},
{roomsecret, Password}]),
lists:member(<<"muc_passwordprotected">>, get_features(Config, Room)),
put_event(Config, Password),
recv_muc_presence(Config, PeerNickJID, available),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_password_slave(Config) ->
+config_password_slave(Config) ->
Password = get_event(Config),
- #stanza_error{reason = 'not-authorized'} = muc_join(Config),
+ #stanza_error{reason = 'not-authorized'} = join(Config),
#stanza_error{reason = 'not-authorized'} =
- muc_join(Config, #muc{password = randoms:get_string()}),
- {[], _, _} = muc_join(Config, #muc{password = Password}),
- ok = muc_leave(Config),
+ join(Config, #muc{password = randoms:get_string()}),
+ {[], _, _} = join(Config, #muc{password = Password}),
+ ok = leave(Config),
disconnect(Config).
-muc_config_whois_master(Config) ->
+config_whois_master(Config) ->
Room = muc_room_jid(Config),
PeerNickJID = peer_muc_jid(Config),
MyNickJID = my_muc_jid(Config),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
lists:member(<<"muc_semianonymous">>, get_features(Config, Room)),
- [172] = muc_set_config(Config, [{whois, anyone}]),
+ [172] = set_config(Config, [{whois, anyone}]),
lists:member(<<"muc_nonanonymous">>, get_features(Config, Room)),
recv_muc_presence(Config, PeerNickJID, unavailable),
recv_muc_presence(Config, PeerNickJID, available),
send(Config, #presence{to = Room}),
recv_muc_presence(Config, MyNickJID, available),
- [173] = muc_set_config(Config, [{whois, moderators}]),
+ [173] = set_config(Config, [{whois, moderators}]),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_whois_slave(Config) ->
+config_whois_slave(Config) ->
PeerJID = ?config(peer, Config),
PeerNickJID = peer_muc_jid(Config),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
ct:comment("Checking if the room becomes non-anonymous (code '172')"),
- [172] = muc_recv_config_change_message(Config),
+ [172] = recv_config_change_message(Config),
ct:comment("Re-joining in order to check status codes"),
- ok = muc_leave(Config),
- {[], _, Codes} = muc_join(Config),
+ ok = leave(Config),
+ {[], _, Codes} = join(Config),
ct:comment("Checking if code '100' (non-anonymous) present"),
true = lists:member(100, Codes),
ct:comment("Receiving presence from peer with JID exposed"),
#muc_user{items = [#muc_item{jid = PeerJID}]} =
recv_muc_presence(Config, PeerNickJID, available),
ct:comment("Waiting for the room to become anonymous again (code '173')"),
- [173] = muc_recv_config_change_message(Config),
- ok = muc_leave(Config),
+ [173] = recv_config_change_message(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_members_only_master(Config) ->
+config_members_only_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(peer, Config),
PeerBareJID = jid:remove_resource(PeerJID),
PeerNickJID = peer_muc_jid(Config),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
lists:member(<<"muc_open">>, get_features(Config, Room)),
- [104] = muc_set_config(Config, [{membersonly, true}]),
+ [104] = set_config(Config, [{membersonly, true}]),
#muc_user{status_codes = Codes,
items = [#muc_item{jid = PeerJID,
affiliation = none,
@@ -1090,7 +1090,7 @@ muc_config_members_only_master(Config) ->
lists:member(<<"muc_membersonly">>, get_features(Config, Room)),
ct:comment("Waiting for slave to fail joining the room"),
set_member = get_event(Config),
- ok = muc_set_affiliation(Config, member, randoms:get_string()),
+ ok = set_affiliation(Config, member, randoms:get_string()),
#message{from = Room, type = normal} = Msg = recv_message(Config),
#muc_user{items = [#muc_item{jid = PeerBareJID,
affiliation = member}]} =
@@ -1099,7 +1099,7 @@ muc_config_members_only_master(Config) ->
put_event(Config, join),
ct:comment("Waiting for peer to join"),
recv_muc_presence(Config, PeerNickJID, available),
- ok = muc_set_affiliation(Config, none, randoms:get_string()),
+ ok = set_affiliation(Config, none, randoms:get_string()),
ct:comment("Waiting for peer to be kicked"),
#muc_user{status_codes = NewCodes,
items = [#muc_item{affiliation = none,
@@ -1108,14 +1108,14 @@ muc_config_members_only_master(Config) ->
ct:comment("Checking if code '321' (became non-member in "
"members-only room) is set"),
true = lists:member(321, NewCodes),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_members_only_slave(Config) ->
+config_members_only_slave(Config) ->
MyJID = my_jid(Config),
MyNickJID = my_muc_jid(Config),
- {[], _, _} = muc_slave_join(Config),
- [104] = muc_recv_config_change_message(Config),
+ {[], _, _} = slave_join(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Getting kicked because the room has become members-only"),
#muc_user{status_codes = Codes,
items = [#muc_item{jid = MyJID,
@@ -1127,12 +1127,12 @@ muc_config_members_only_slave(Config) ->
true = lists:member(110, Codes),
true = lists:member(322, Codes),
ct:comment("Fail trying to join members-only room"),
- #stanza_error{reason = 'registration-required'} = muc_join(Config),
+ #stanza_error{reason = 'registration-required'} = join(Config),
ct:comment("Asking the peer to set us member"),
put_event(Config, set_member),
ct:comment("Waiting for the peer to ask for join"),
join = get_event(Config),
- {[], _, _} = muc_join(Config, participant, member),
+ {[], _, _} = join(Config, participant, member),
#muc_user{status_codes = NewCodes,
items = [#muc_item{jid = MyJID,
role = none,
@@ -1144,71 +1144,71 @@ muc_config_members_only_slave(Config) ->
true = lists:member(321, NewCodes),
disconnect(Config).
-muc_config_moderated_master(Config) ->
+config_moderated_master(Config) ->
Room = muc_room_jid(Config),
PeerNickJID = peer_muc_jid(Config),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
lists:member(<<"muc_moderated">>, get_features(Config, Room)),
- ok = muc_set_role(Config, visitor, randoms:get_string()),
+ ok = set_role(Config, visitor, randoms:get_string()),
#muc_user{items = [#muc_item{role = visitor}]} =
recv_muc_presence(Config, PeerNickJID, available),
set_unmoderated = get_event(Config),
- [104] = muc_set_config(Config, [{moderatedroom, false}]),
+ [104] = set_config(Config, [{moderatedroom, false}]),
#message{from = PeerNickJID, type = groupchat} = recv_message(Config),
recv_muc_presence(Config, PeerNickJID, unavailable),
lists:member(<<"muc_unmoderated">>, get_features(Config, Room)),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_moderated_slave(Config) ->
+config_moderated_slave(Config) ->
Room = muc_room_jid(Config),
MyNickJID = my_muc_jid(Config),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
#muc_user{items = [#muc_item{role = visitor}]} =
recv_muc_presence(Config, MyNickJID, available),
send(Config, #message{to = Room, type = groupchat}),
ErrMsg = #message{from = Room, type = error} = recv_message(Config),
#stanza_error{reason = 'forbidden'} = xmpp:get_error(ErrMsg),
put_event(Config, set_unmoderated),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
send(Config, #message{to = Room, type = groupchat}),
#message{from = MyNickJID, type = groupchat} = recv_message(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_private_messages_master(Config) ->
+config_private_messages_master(Config) ->
PeerNickJID = peer_muc_jid(Config),
- ok = muc_master_join(Config),
+ ok = master_join(Config),
ct:comment("Waiting for a private message from the slave"),
#message{from = PeerNickJID, type = chat} = recv_message(Config),
- ok = muc_set_role(Config, visitor, <<>>),
+ ok = set_role(Config, visitor, <<>>),
ct:comment("Waiting for the peer to become a visitor"),
recv_muc_presence(Config, PeerNickJID, available),
ct:comment("Waiting for a private message from the slave"),
#message{from = PeerNickJID, type = chat} = recv_message(Config),
- [104] = muc_set_config(Config, [{allow_private_messages_from_visitors, moderators}]),
+ [104] = set_config(Config, [{allow_private_messages_from_visitors, moderators}]),
ct:comment("Waiting for a private message from the slave"),
#message{from = PeerNickJID, type = chat} = recv_message(Config),
- [104] = muc_set_config(Config, [{allow_private_messages_from_visitors, nobody}]),
+ [104] = set_config(Config, [{allow_private_messages_from_visitors, nobody}]),
wait_for_slave(Config),
- [104] = muc_set_config(Config, [{allow_private_messages_from_visitors, anyone},
+ [104] = set_config(Config, [{allow_private_messages_from_visitors, anyone},
{allow_private_messages, false}]),
ct:comment("Fail trying to send a private message"),
send(Config, #message{to = PeerNickJID, type = chat}),
#message{from = PeerNickJID, type = error} = ErrMsg = recv_message(Config),
#stanza_error{reason = 'forbidden'} = xmpp:get_error(ErrMsg),
- ok = muc_set_role(Config, participant, <<>>),
+ ok = set_role(Config, participant, <<>>),
ct:comment("Waiting for the peer to become a participant"),
recv_muc_presence(Config, PeerNickJID, available),
ct:comment("Waiting for the peer to leave"),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_private_messages_slave(Config) ->
+config_private_messages_slave(Config) ->
MyNickJID = my_muc_jid(Config),
PeerNickJID = peer_muc_jid(Config),
- {[], _, _} = muc_slave_join(Config),
+ {[], _, _} = slave_join(Config),
ct:comment("Sending a private message"),
send(Config, #message{to = PeerNickJID, type = chat}),
ct:comment("Waiting to become a visitor"),
@@ -1216,16 +1216,16 @@ muc_config_private_messages_slave(Config) ->
recv_muc_presence(Config, MyNickJID, available),
ct:comment("Sending a private message"),
send(Config, #message{to = PeerNickJID, type = chat}),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Sending a private message"),
send(Config, #message{to = PeerNickJID, type = chat}),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Fail trying to send a private message"),
send(Config, #message{to = PeerNickJID, type = chat}),
#message{from = PeerNickJID, type = error} = ErrMsg1 = recv_message(Config),
#stanza_error{reason = 'forbidden'} = xmpp:get_error(ErrMsg1),
wait_for_master(Config),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Waiting to become a participant again"),
#muc_user{items = [#muc_item{role = participant}]} =
recv_muc_presence(Config, MyNickJID, available),
@@ -1233,29 +1233,29 @@ muc_config_private_messages_slave(Config) ->
send(Config, #message{to = PeerNickJID, type = chat}),
#message{from = PeerNickJID, type = error} = ErrMsg2 = recv_message(Config),
#stanza_error{reason = 'forbidden'} = xmpp:get_error(ErrMsg2),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_query_master(Config) ->
+config_query_master(Config) ->
PeerNickJID = peer_muc_jid(Config),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
wait_for_slave(Config),
recv_muc_presence(Config, PeerNickJID, available),
ct:comment("Receiving IQ query from the slave"),
#iq{type = get, from = PeerNickJID, id = I,
sub_els = [#ping{}]} = recv_iq(Config),
send(Config, #iq{type = result, to = PeerNickJID, id = I}),
- [104] = muc_set_config(Config, [{allow_query_users, false}]),
+ [104] = set_config(Config, [{allow_query_users, false}]),
ct:comment("Fail trying to send IQ"),
#iq{type = error, from = PeerNickJID} = Err =
send_recv(Config, #iq{type = get, to = PeerNickJID,
sub_els = [#ping{}]}),
#stanza_error{reason = 'not-allowed'} = xmpp:get_error(Err),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_query_slave(Config) ->
+config_query_slave(Config) ->
PeerNickJID = peer_muc_jid(Config),
wait_for_master(Config),
ct:comment("Checking if IQ queries are denied from non-occupants"),
@@ -1263,28 +1263,28 @@ muc_config_query_slave(Config) ->
send_recv(Config, #iq{type = get, to = PeerNickJID,
sub_els = [#ping{}]}),
#stanza_error{reason = 'not-acceptable'} = xmpp:get_error(Err1),
- {[], _, _} = muc_join(Config),
+ {[], _, _} = join(Config),
ct:comment("Sending IQ to the master"),
#iq{type = result, from = PeerNickJID, sub_els = []} =
send_recv(Config, #iq{to = PeerNickJID, type = get, sub_els = [#ping{}]}),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Fail trying to send IQ"),
#iq{type = error, from = PeerNickJID} = Err2 =
send_recv(Config, #iq{type = get, to = PeerNickJID,
sub_els = [#ping{}]}),
#stanza_error{reason = 'not-allowed'} = xmpp:get_error(Err2),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_allow_invites_master(Config) ->
+config_allow_invites_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(peer, Config),
PeerNickJID = peer_muc_jid(Config),
- ok = muc_master_join(Config),
- [104] = muc_set_config(Config, [{allowinvites, true}]),
+ ok = master_join(Config),
+ [104] = set_config(Config, [{allowinvites, true}]),
ct:comment("Receiving an invitation from the slave"),
#message{from = Room, type = normal} = recv_message(Config),
- [104] = muc_set_config(Config, [{allowinvites, false}]),
+ [104] = set_config(Config, [{allowinvites, false}]),
send_invitation = get_event(Config),
ct:comment("Sending an invitation"),
send(Config, #message{to = Room, type = normal,
@@ -1293,10 +1293,10 @@ muc_config_allow_invites_master(Config) ->
invites =
[#muc_invite{to = PeerJID}]}]}),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_allow_invites_slave(Config) ->
+config_allow_invites_slave(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(peer, Config),
InviteMsg = #message{to = Room, type = normal,
@@ -1304,11 +1304,11 @@ muc_config_allow_invites_slave(Config) ->
[#muc_user{
invites =
[#muc_invite{to = PeerJID}]}]},
- {[], _, _} = muc_slave_join(Config),
- [104] = muc_recv_config_change_message(Config),
+ {[], _, _} = slave_join(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Sending an invitation"),
send(Config, InviteMsg),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Fail sending an invitation"),
send(Config, InviteMsg),
#message{from = Room, type = error} = Err = recv_message(Config),
@@ -1316,85 +1316,85 @@ muc_config_allow_invites_slave(Config) ->
ct:comment("Checking if the master is still able to send invitations"),
put_event(Config, send_invitation),
#message{from = Room, type = normal} = recv_message(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_visitor_status_master(Config) ->
+config_visitor_status_master(Config) ->
PeerNickJID = peer_muc_jid(Config),
Status = xmpp:mk_text(randoms:get_string()),
- ok = muc_join_new(Config),
- [104] = muc_set_config(Config, [{members_by_default, false}]),
+ ok = join_new(Config),
+ [104] = set_config(Config, [{members_by_default, false}]),
ct:comment("Asking the slave to join as a visitor"),
put_event(Config, {join, Status}),
#muc_user{items = [#muc_item{role = visitor}]} =
recv_muc_presence(Config, PeerNickJID, available),
ct:comment("Receiving status change from the visitor"),
#presence{from = PeerNickJID, status = Status} = recv_presence(Config),
- [104] = muc_set_config(Config, [{allow_visitor_status, false}]),
+ [104] = set_config(Config, [{allow_visitor_status, false}]),
ct:comment("Receiving status change with <status/> stripped"),
#presence{from = PeerNickJID, status = []} = recv_presence(Config),
ct:comment("Waiting for the slave to leave"),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_visitor_status_slave(Config) ->
+config_visitor_status_slave(Config) ->
Room = muc_room_jid(Config),
MyNickJID = my_muc_jid(Config),
ct:comment("Waiting for 'join' command from the master"),
{join, Status} = get_event(Config),
- {[], _, _} = muc_join(Config, visitor, none),
+ {[], _, _} = join(Config, visitor, none),
ct:comment("Sending status change"),
send(Config, #presence{to = Room, status = Status}),
#presence{from = MyNickJID, status = Status} = recv_presence(Config),
- [104] = muc_recv_config_change_message(Config),
+ [104] = recv_config_change_message(Config),
ct:comment("Sending status change again"),
send(Config, #presence{to = Room, status = Status}),
#presence{from = MyNickJID, status = []} = recv_presence(Config),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_allow_voice_requests_master(Config) ->
+config_allow_voice_requests_master(Config) ->
PeerNickJID = peer_muc_jid(Config),
- ok = muc_join_new(Config),
- [104] = muc_set_config(Config, [{members_by_default, false}]),
+ ok = join_new(Config),
+ [104] = set_config(Config, [{members_by_default, false}]),
ct:comment("Asking the slave to join as a visitor"),
put_event(Config, join),
#muc_user{items = [#muc_item{role = visitor}]} =
recv_muc_presence(Config, PeerNickJID, available),
- [104] = muc_set_config(Config, [{allow_voice_requests, false}]),
+ [104] = set_config(Config, [{allow_voice_requests, false}]),
ct:comment("Waiting for the slave to leave"),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_allow_voice_requests_slave(Config) ->
+config_allow_voice_requests_slave(Config) ->
Room = muc_room_jid(Config),
ct:comment("Waiting for 'join' command from the master"),
join = get_event(Config),
- {[], _, _} = muc_join(Config, visitor),
- [104] = muc_recv_config_change_message(Config),
+ {[], _, _} = join(Config, visitor),
+ [104] = recv_config_change_message(Config),
ct:comment("Fail sending voice request"),
Fs = muc_request:encode([{role, participant}]),
X = #xdata{type = submit, fields = Fs},
send(Config, #message{to = Room, sub_els = [X]}),
#message{from = Room, type = error} = Err = recv_message(Config),
#stanza_error{reason = 'forbidden'} = xmpp:get_error(Err),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_voice_request_interval_master(Config) ->
+config_voice_request_interval_master(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(peer, Config),
PeerNick = ?config(peer_nick, Config),
PeerNickJID = peer_muc_jid(Config),
- ok = muc_join_new(Config),
- [104] = muc_set_config(Config, [{members_by_default, false}]),
+ ok = join_new(Config),
+ [104] = set_config(Config, [{members_by_default, false}]),
ct:comment("Asking the slave to join as a visitor"),
put_event(Config, join),
#muc_user{items = [#muc_item{role = visitor}]} =
recv_muc_presence(Config, PeerNickJID, available),
- [104] = muc_set_config(Config, [{voice_request_min_interval, 5}]),
+ [104] = set_config(Config, [{voice_request_min_interval, 5}]),
ct:comment("Receiving a voice request from slave"),
#message{from = Room, type = normal} = recv_message(Config),
ct:comment("Deny voice request at first"),
@@ -1407,17 +1407,17 @@ muc_config_voice_request_interval_master(Config) ->
#message{from = Room, type = normal} = recv_message(Config),
ct:comment("Waiting for the slave to leave"),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_voice_request_interval_slave(Config) ->
+config_voice_request_interval_slave(Config) ->
Room = muc_room_jid(Config),
Fs = muc_request:encode([{role, participant}]),
X = #xdata{type = submit, fields = Fs},
ct:comment("Waiting for 'join' command from the master"),
join = get_event(Config),
- {[], _, _} = muc_join(Config, visitor),
- [104] = muc_recv_config_change_message(Config),
+ {[], _, _} = join(Config, visitor),
+ [104] = recv_config_change_message(Config),
ct:comment("Sending voice request"),
send(Config, #message{to = Room, sub_els = [X]}),
ct:comment("Waiting for the master to deny our voice request"),
@@ -1431,59 +1431,59 @@ muc_config_voice_request_interval_slave(Config) ->
timer:sleep(timer:seconds(5)),
ct:comment("Repeating again"),
send(Config, #message{to = Room, sub_els = [X]}),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_visitor_nickchange_master(Config) ->
+config_visitor_nickchange_master(Config) ->
PeerNickJID = peer_muc_jid(Config),
- ok = muc_join_new(Config),
- [104] = muc_set_config(Config, [{members_by_default, false}]),
+ ok = join_new(Config),
+ [104] = set_config(Config, [{members_by_default, false}]),
ct:comment("Asking the slave to join as a visitor"),
put_event(Config, join),
ct:comment("Waiting for the slave to join"),
#muc_user{items = [#muc_item{role = visitor}]} =
recv_muc_presence(Config, PeerNickJID, available),
- [104] = muc_set_config(Config, [{allow_visitor_nickchange, false}]),
+ [104] = set_config(Config, [{allow_visitor_nickchange, false}]),
ct:comment("Waiting for the slave to leave"),
recv_muc_presence(Config, PeerNickJID, unavailable),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_config_visitor_nickchange_slave(Config) ->
+config_visitor_nickchange_slave(Config) ->
NewNick = randoms:get_string(),
MyNickJID = my_muc_jid(Config),
MyNewNickJID = jid:replace_resource(MyNickJID, NewNick),
ct:comment("Waiting for 'join' command from the master"),
join = get_event(Config),
- {[], _, _} = muc_join(Config, visitor),
- [104] = muc_recv_config_change_message(Config),
+ {[], _, _} = join(Config, visitor),
+ [104] = recv_config_change_message(Config),
ct:comment("Fail trying to change nickname"),
send(Config, #presence{to = MyNewNickJID}),
#presence{from = MyNewNickJID, type = error} = Err = recv_presence(Config),
#stanza_error{reason = 'not-allowed'} = xmpp:get_error(Err),
- ok = muc_leave(Config),
+ ok = leave(Config),
disconnect(Config).
-muc_register_master(Config) ->
+register_master(Config) ->
MUC = muc_jid(Config),
%% Register nick "master1"
- muc_register_nick(Config, MUC, <<"">>, <<"master1">>),
+ register_nick(Config, MUC, <<"">>, <<"master1">>),
%% Unregister nick "master1" via jabber:register
#iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, to = MUC,
sub_els = [#register{remove = true}]}),
%% Register nick "master2"
- muc_register_nick(Config, MUC, <<"">>, <<"master2">>),
+ register_nick(Config, MUC, <<"">>, <<"master2">>),
%% Now register nick "master"
- muc_register_nick(Config, MUC, <<"master2">>, <<"master">>),
+ register_nick(Config, MUC, <<"master2">>, <<"master">>),
%% Wait for slave to fail trying to register nick "master"
wait_for_slave(Config),
wait_for_slave(Config),
%% Now register empty ("") nick, which means we're unregistering
- muc_register_nick(Config, MUC, <<"master">>, <<"">>),
+ register_nick(Config, MUC, <<"master">>, <<"">>),
disconnect(Config).
-muc_register_slave(Config) ->
+register_slave(Config) ->
MUC = muc_jid(Config),
wait_for_master(Config),
%% Trying to register occupied nick "master"
@@ -1498,18 +1498,22 @@ muc_register_slave(Config) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
+single_test(T) ->
+ list_to_atom("muc_" ++ atom_to_list(T)).
+
master_slave_test(T) ->
- {T, [parallel], [list_to_atom(atom_to_list(T) ++ "_master"),
- list_to_atom(atom_to_list(T) ++ "_slave")]}.
+ {list_to_atom("muc_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("muc_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("muc_" ++ atom_to_list(T) ++ "_slave")]}.
recv_muc_presence(Config, From, Type) ->
Pres = #presence{from = From, type = Type} = recv_presence(Config),
xmpp:get_subtag(Pres, #muc_user{}).
-muc_join_new(Config) ->
- muc_join_new(Config, muc_room_jid(Config)).
+join_new(Config) ->
+ join_new(Config, muc_room_jid(Config)).
-muc_join_new(Config, Room) ->
+join_new(Config, Room) ->
MyJID = my_jid(Config),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
@@ -1537,41 +1541,41 @@ muc_join_new(Config, Room) ->
subject = [#text{data = <<>>}]} = recv_message(Config),
case ?config(persistent_room, Config) of
true ->
- [104] = muc_set_config(Config, [{persistentroom, true}], Room),
+ [104] = set_config(Config, [{persistentroom, true}], Room),
ok;
false ->
ok
end.
-muc_recv_history_and_subject(Config) ->
+recv_history_and_subject(Config) ->
ct:comment("Receiving room history and/or subject"),
- muc_recv_history_and_subject(Config, []).
+ recv_history_and_subject(Config, []).
-muc_recv_history_and_subject(Config, History) ->
+recv_history_and_subject(Config, History) ->
Room = muc_room_jid(Config),
#message{type = groupchat, subject = Subj,
body = Body, thread = Thread} = Msg = recv_message(Config),
case xmpp:get_subtag(Msg, #delay{}) of
#delay{from = Room} ->
- muc_recv_history_and_subject(Config, [Msg|History]);
+ recv_history_and_subject(Config, [Msg|History]);
false when Subj /= [], Body == [], Thread == undefined ->
{lists:reverse(History), Msg}
end.
-muc_join(Config) ->
- muc_join(Config, participant, none, #muc{}).
+join(Config) ->
+ join(Config, participant, none, #muc{}).
-muc_join(Config, Role) when is_atom(Role) ->
- muc_join(Config, Role, none, #muc{});
-muc_join(Config, #muc{} = SubEl) ->
- muc_join(Config, participant, none, SubEl).
+join(Config, Role) when is_atom(Role) ->
+ join(Config, Role, none, #muc{});
+join(Config, #muc{} = SubEl) ->
+ join(Config, participant, none, SubEl).
-muc_join(Config, Role, Aff) when is_atom(Role), is_atom(Aff) ->
- muc_join(Config, Role, Aff, #muc{});
-muc_join(Config, Role, #muc{} = SubEl) when is_atom(Role) ->
- muc_join(Config, Role, none, SubEl).
+join(Config, Role, Aff) when is_atom(Role), is_atom(Aff) ->
+ join(Config, Role, Aff, #muc{});
+join(Config, Role, #muc{} = SubEl) when is_atom(Role) ->
+ join(Config, Role, none, SubEl).
-muc_join(Config, Role, Aff, SubEl) ->
+join(Config, Role, Aff, SubEl) ->
ct:comment("Joining existing room as ~s/~s", [Aff, Role]),
MyJID = my_jid(Config),
Room = muc_room_jid(Config),
@@ -1595,7 +1599,7 @@ muc_join(Config, Role, Aff, SubEl) ->
recv_muc_presence(Config, MyNickJID, available),
ct:comment("Checking if code '110' (self-presence) is set"),
true = lists:member(110, Codes),
- {History, Subj} = muc_recv_history_and_subject(Config),
+ {History, Subj} = recv_history_and_subject(Config),
{History, Subj, Codes};
#presence{type = available, from = MyNickJID} = Pres ->
#muc_user{status_codes = Codes,
@@ -1605,21 +1609,21 @@ muc_join(Config, Role, Aff, SubEl) ->
xmpp:get_subtag(Pres, #muc_user{}),
ct:comment("Checking if code '110' (self-presence) is set"),
true = lists:member(110, Codes),
- {History, Subj} = muc_recv_history_and_subject(Config),
+ {History, Subj} = recv_history_and_subject(Config),
{empty, History, Subj, Codes}
end.
-muc_leave(Config) ->
- muc_leave(Config, muc_room_jid(Config)).
+leave(Config) ->
+ leave(Config, muc_room_jid(Config)).
-muc_leave(Config, Room) ->
+leave(Config, Room) ->
MyJID = my_jid(Config),
MyNick = ?config(nick, Config),
MyNickJID = jid:replace_resource(Room, MyNick),
Mode = ?config(mode, Config),
IsPersistent = ?config(persistent_room, Config),
if Mode /= slave, IsPersistent ->
- [104] = muc_set_config(Config, [{persistentroom, false}], Room);
+ [104] = set_config(Config, [{persistentroom, false}], Room);
true ->
ok
end,
@@ -1633,7 +1637,7 @@ muc_leave(Config, Room) ->
true = lists:member(110, Codes),
ok.
-muc_get_config(Config) ->
+get_config(Config) ->
ct:comment("Get room config"),
Room = muc_room_jid(Config),
case send_recv(Config,
@@ -1646,10 +1650,10 @@ muc_get_config(Config) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_set_config(Config, RoomConfig) ->
- muc_set_config(Config, RoomConfig, muc_room_jid(Config)).
+set_config(Config, RoomConfig) ->
+ set_config(Config, RoomConfig, muc_room_jid(Config)).
-muc_set_config(Config, RoomConfig, Room) ->
+set_config(Config, RoomConfig, Room) ->
ct:comment("Set room config: ~p", [RoomConfig]),
Fs = case RoomConfig of
[] -> [];
@@ -1667,15 +1671,15 @@ muc_set_config(Config, RoomConfig, Room) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_create_persistent(Config) ->
- [_|_] = muc_get_config(Config),
- [] = muc_set_config(Config, [{persistentroom, true}], false),
+create_persistent(Config) ->
+ [_|_] = get_config(Config),
+ [] = set_config(Config, [{persistentroom, true}], false),
ok.
-muc_destroy(Config) ->
- muc_destroy(Config, <<>>).
+destroy(Config) ->
+ destroy(Config, <<>>).
-muc_destroy(Config, Reason) ->
+destroy(Config, Reason) ->
Room = muc_room_jid(Config),
AltRoom = alt_room_jid(Config),
ct:comment("Destroying a room"),
@@ -1690,7 +1694,7 @@ muc_destroy(Config, Reason) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_disco_items(Config) ->
+disco_items(Config) ->
MUC = muc_jid(Config),
ct:comment("Performing disco#items request to ~s", [jid:to_string(MUC)]),
#iq{type = result, from = MUC, sub_els = [DiscoItems]} =
@@ -1698,14 +1702,14 @@ muc_disco_items(Config) ->
sub_els = [#disco_items{}]}),
lists:keysort(#disco_item.jid, DiscoItems#disco_items.items).
-muc_disco_room_items(Config) ->
+disco_room_items(Config) ->
Room = muc_room_jid(Config),
#iq{type = result, from = Room, sub_els = [DiscoItems]} =
send_recv(Config, #iq{type = get, to = Room,
sub_els = [#disco_items{}]}),
DiscoItems#disco_items.items.
-muc_get_affiliations(Config, Aff) ->
+get_affiliations(Config, Aff) ->
Room = muc_room_jid(Config),
case send_recv(Config,
#iq{type = get, to = Room,
@@ -1716,12 +1720,12 @@ muc_get_affiliations(Config, Aff) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_master_join(Config) ->
+master_join(Config) ->
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
PeerNick = ?config(slave_nick, Config),
PeerNickJID = jid:replace_resource(Room, PeerNick),
- ok = muc_join_new(Config),
+ ok = join_new(Config),
wait_for_slave(Config),
#muc_user{items = [#muc_item{jid = PeerJID,
role = participant,
@@ -1729,11 +1733,11 @@ muc_master_join(Config) ->
recv_muc_presence(Config, PeerNickJID, available),
ok.
-muc_slave_join(Config) ->
+slave_join(Config) ->
wait_for_master(Config),
- muc_join(Config).
+ join(Config).
-muc_set_role(Config, Role, Reason) ->
+set_role(Config, Role, Reason) ->
ct:comment("Changing role to ~s", [Role]),
Room = muc_room_jid(Config),
PeerNick = ?config(slave_nick, Config),
@@ -1751,7 +1755,7 @@ muc_set_role(Config, Role, Reason) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_get_role(Config, Role) ->
+get_role(Config, Role) ->
ct:comment("Requesting list for role '~s'", [Role]),
Room = muc_room_jid(Config),
case send_recv(
@@ -1765,7 +1769,7 @@ muc_get_role(Config, Role) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_set_affiliation(Config, Aff, Reason) ->
+set_affiliation(Config, Aff, Reason) ->
ct:comment("Changing affiliation to ~s", [Aff]),
Room = muc_room_jid(Config),
PeerJID = ?config(slave, Config),
@@ -1784,7 +1788,7 @@ muc_set_affiliation(Config, Aff, Reason) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_get_affiliation(Config, Aff) ->
+get_affiliation(Config, Aff) ->
ct:comment("Requesting list for affiliation '~s'", [Aff]),
Room = muc_room_jid(Config),
case send_recv(
@@ -1798,7 +1802,7 @@ muc_get_affiliation(Config, Aff) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_set_vcard(Config, VCard) ->
+set_vcard(Config, VCard) ->
Room = muc_room_jid(Config),
ct:comment("Setting vCard for ~s", [jid:to_string(Room)]),
case send_recv(Config, #iq{type = set, to = Room,
@@ -1809,7 +1813,7 @@ muc_set_vcard(Config, VCard) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_get_vcard(Config) ->
+get_vcard(Config) ->
Room = muc_room_jid(Config),
ct:comment("Retreiving vCard from ~s", [jid:to_string(Room)]),
case send_recv(Config, #iq{type = get, to = Room,
@@ -1820,14 +1824,14 @@ muc_get_vcard(Config) ->
xmpp:get_subtag(Err, #stanza_error{})
end.
-muc_recv_config_change_message(Config) ->
+recv_config_change_message(Config) ->
ct:comment("Receiving configuration change notification message"),
Room = muc_room_jid(Config),
#message{type = groupchat, from = Room} = Msg = recv_message(Config),
#muc_user{status_codes = Codes} = xmpp:get_subtag(Msg, #muc_user{}),
lists:sort(Codes).
-muc_register_nick(Config, MUC, PrevNick, Nick) ->
+register_nick(Config, MUC, PrevNick, Nick) ->
PrevRegistered = if PrevNick /= <<"">> -> true;
true -> false
end,
@@ -1859,7 +1863,7 @@ muc_register_nick(Config, MUC, PrevNick, Nick) ->
Nick = proplists:get_value(
roomnick, muc_register:decode(FsWithNick)).
-muc_subscribe(Config, Events, Room) ->
+subscribe(Config, Events, Room) ->
MyNick = ?config(nick, Config),
case send_recv(Config,
#iq{type = set, to = Room,
@@ -1871,7 +1875,7 @@ muc_subscribe(Config, Events, Room) ->
xmpp:get_error(Err)
end.
-muc_unsubscribe(Config, Room) ->
+unsubscribe(Config, Room) ->
case send_recv(Config, #iq{type = set, to = Room,
sub_els = [#muc_unsubscribe{}]}) of
#iq{type = result, sub_els = []} ->
diff --git a/test/privacy_tests.erl b/test/privacy_tests.erl
index 2ee945f1..640f53d4 100644
--- a/test/privacy_tests.erl
+++ b/test/privacy_tests.erl
@@ -13,7 +13,7 @@
-import(suite, [disconnect/1, send_recv/2, get_event/1, put_event/2,
recv_iq/1, recv_presence/1, recv_message/1, recv/1,
send/2, my_jid/1, server_jid/1, get_features/1,
- set_roster/3, del_roster/1]).
+ set_roster/3, del_roster/1, get_roster/1]).
-include("suite.hrl").
-include("mod_roster.hrl").
@@ -233,7 +233,7 @@ set_get_block(Config) ->
%%% Master-slave cases
%%%===================================================================
master_slave_cases() ->
- {privacy_master_slave, [parallel],
+ {privacy_master_slave, [sequence],
[master_slave_test(deny_bare_jid),
master_slave_test(deny_full_jid),
master_slave_test(deny_server_jid),
@@ -319,7 +319,8 @@ deny_master(Config, {Type, Value}) ->
set_roster(Config, Sub, Groups),
lists:foreach(
fun(Opts) ->
- ListName = str:format("deny-~s-~s-~p", [Type, Value, Opts]),
+ ct:pal("Set list for ~s, ~s, ~w", [Type, Value, Opts]),
+ ListName = randoms:get_string(),
Item = #privacy_item{order = 0,
action = deny,
iq = proplists:get_bool(iq, Opts),
diff --git a/test/proxy65_tests.erl b/test/proxy65_tests.erl
new file mode 100644
index 00000000..01292f50
--- /dev/null
+++ b/test/proxy65_tests.erl
@@ -0,0 +1,105 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(proxy65_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [disconnect/1, is_feature_advertised/3, proxy_jid/1,
+ my_jid/1, wait_for_slave/1, wait_for_master/1,
+ send_recv/2, put_event/2, get_event/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {proxy65_single, [sequence],
+ [single_test(feature_enabled)]}.
+
+feature_enabled(Config) ->
+ true = is_feature_advertised(Config, ?NS_BYTESTREAMS, proxy_jid(Config)),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {proxy65_master_slave, [sequence],
+ [master_slave_test(all)]}.
+
+all_master(Config) ->
+ Proxy = proxy_jid(Config),
+ MyJID = my_jid(Config),
+ Peer = ?config(slave, Config),
+ wait_for_slave(Config),
+ #presence{} = send_recv(Config, #presence{}),
+ #iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} =
+ send_recv(
+ Config,
+ #iq{type = get, sub_els = [#bytestreams{}], to = Proxy}),
+ SID = randoms:get_string(),
+ Data = randoms:bytes(1024),
+ put_event(Config, {StreamHost, SID, Data}),
+ Socks5 = socks5_connect(StreamHost, {SID, MyJID, Peer}),
+ wait_for_slave(Config),
+ #iq{type = result, sub_els = []} =
+ send_recv(Config,
+ #iq{type = set, to = Proxy,
+ sub_els = [#bytestreams{activate = Peer, sid = SID}]}),
+ socks5_send(Socks5, Data),
+ disconnect(Config).
+
+all_slave(Config) ->
+ MyJID = my_jid(Config),
+ Peer = ?config(master, Config),
+ #presence{} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ {StreamHost, SID, Data} = get_event(Config),
+ Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}),
+ wait_for_master(Config),
+ socks5_recv(Socks5, Data),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("proxy65_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("proxy65_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("proxy65_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("proxy65_" ++ atom_to_list(T) ++ "_slave")]}.
+
+socks5_connect(#streamhost{host = Host, port = Port},
+ {SID, JID1, JID2}) ->
+ Hash = p1_sha:sha([SID, jid:to_string(JID1), jid:to_string(JID2)]),
+ {ok, Sock} = gen_tcp:connect(binary_to_list(Host), Port,
+ [binary, {active, false}]),
+ Init = <<?VERSION_5, 1, ?AUTH_ANONYMOUS>>,
+ InitAck = <<?VERSION_5, ?AUTH_ANONYMOUS>>,
+ Req = <<?VERSION_5, ?CMD_CONNECT, 0,
+ ?ATYP_DOMAINNAME, 40, Hash:40/binary, 0, 0>>,
+ Resp = <<?VERSION_5, ?SUCCESS, 0, ?ATYP_DOMAINNAME,
+ 40, Hash:40/binary, 0, 0>>,
+ gen_tcp:send(Sock, Init),
+ {ok, InitAck} = gen_tcp:recv(Sock, size(InitAck)),
+ gen_tcp:send(Sock, Req),
+ {ok, Resp} = gen_tcp:recv(Sock, size(Resp)),
+ Sock.
+
+socks5_send(Sock, Data) ->
+ ok = gen_tcp:send(Sock, Data).
+
+socks5_recv(Sock, Data) ->
+ {ok, Data} = gen_tcp:recv(Sock, size(Data)).
diff --git a/test/pubsub_tests.erl b/test/pubsub_tests.erl
new file mode 100644
index 00000000..fae7234e
--- /dev/null
+++ b/test/pubsub_tests.erl
@@ -0,0 +1,729 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(pubsub_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [pubsub_jid/1, send_recv/2, get_features/2, disconnect/1,
+ put_event/2, get_event/1, wait_for_master/1, wait_for_slave/1,
+ recv_message/1, my_jid/1, send/2, recv_presence/1, recv/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {pubsub_single, [sequence],
+ [single_test(test_features),
+ single_test(test_create),
+ single_test(test_configure),
+ single_test(test_delete),
+ single_test(test_get_affiliations),
+ single_test(test_get_subscriptions),
+ single_test(test_create_instant),
+ single_test(test_default),
+ single_test(test_create_configure),
+ single_test(test_publish),
+ single_test(test_auto_create),
+ single_test(test_get_items),
+ single_test(test_delete_item),
+ single_test(test_purge),
+ single_test(test_subscribe),
+ single_test(test_unsubscribe)]}.
+
+test_features(Config) ->
+ PJID = pubsub_jid(Config),
+ AllFeatures = sets:from_list(get_features(Config, PJID)),
+ NeededFeatures = sets:from_list(
+ [?NS_PUBSUB,
+ ?PUBSUB("access-open"),
+ ?PUBSUB("access-authorize"),
+ ?PUBSUB("create-nodes"),
+ ?PUBSUB("instant-nodes"),
+ ?PUBSUB("config-node"),
+ ?PUBSUB("retrieve-default"),
+ ?PUBSUB("create-and-configure"),
+ ?PUBSUB("publish"),
+ ?PUBSUB("auto-create"),
+ ?PUBSUB("retrieve-items"),
+ ?PUBSUB("delete-items"),
+ ?PUBSUB("subscribe"),
+ ?PUBSUB("retrieve-affiliations"),
+ ?PUBSUB("modify-affiliations"),
+ ?PUBSUB("retrieve-subscriptions"),
+ ?PUBSUB("manage-subscriptions"),
+ ?PUBSUB("purge-nodes"),
+ ?PUBSUB("delete-nodes")]),
+ true = sets:is_subset(NeededFeatures, AllFeatures),
+ disconnect(Config).
+
+test_create(Config) ->
+ Node = ?config(pubsub_node, Config),
+ Node = create_node(Config, Node),
+ disconnect(Config).
+
+test_create_instant(Config) ->
+ Node = create_node(Config, <<>>),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_configure(Config) ->
+ Node = ?config(pubsub_node, Config),
+ NodeTitle = ?config(pubsub_node_title, Config),
+ NodeConfig = get_node_config(Config, Node),
+ MyNodeConfig = set_opts(NodeConfig,
+ [{title, NodeTitle}]),
+ set_node_config(Config, Node, MyNodeConfig),
+ NewNodeConfig = get_node_config(Config, Node),
+ NodeTitle = proplists:get_value(title, NewNodeConfig),
+ disconnect(Config).
+
+test_default(Config) ->
+ get_default_node_config(Config),
+ disconnect(Config).
+
+test_create_configure(Config) ->
+ NodeTitle = ?config(pubsub_node_title, Config),
+ DefaultNodeConfig = get_default_node_config(Config),
+ CustomNodeConfig = set_opts(DefaultNodeConfig,
+ [{title, NodeTitle}]),
+ Node = create_node(Config, <<>>, CustomNodeConfig),
+ NodeConfig = get_node_config(Config, Node),
+ NodeTitle = proplists:get_value(title, NodeConfig),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_publish(Config) ->
+ Node = create_node(Config, <<>>),
+ publish_item(Config, Node),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_auto_create(Config) ->
+ Node = randoms:get_string(),
+ publish_item(Config, Node),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_get_items(Config) ->
+ Node = create_node(Config, <<>>),
+ ItemsIn = [publish_item(Config, Node) || _ <- lists:seq(1, 5)],
+ ItemsOut = get_items(Config, Node),
+ true = [I || #ps_item{id = I} <- lists:sort(ItemsIn)]
+ == [I || #ps_item{id = I} <- lists:sort(ItemsOut)],
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_delete_item(Config) ->
+ Node = create_node(Config, <<>>),
+ #ps_item{id = I} = publish_item(Config, Node),
+ [#ps_item{id = I}] = get_items(Config, Node),
+ delete_item(Config, Node, I),
+ [] = get_items(Config, Node),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_subscribe(Config) ->
+ Node = create_node(Config, <<>>),
+ #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
+ [#ps_subscription{node = Node}] = get_subscriptions(Config),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_unsubscribe(Config) ->
+ Node = create_node(Config, <<>>),
+ subscribe_node(Config, Node),
+ [#ps_subscription{node = Node}] = get_subscriptions(Config),
+ unsubscribe_node(Config, Node),
+ [] = get_subscriptions(Config),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_get_affiliations(Config) ->
+ Nodes = lists:sort([create_node(Config, <<>>) || _ <- lists:seq(1, 5)]),
+ Affs = get_affiliations(Config),
+ Nodes = lists:sort([Node || #ps_affiliation{node = Node,
+ type = owner} <- Affs]),
+ [delete_node(Config, Node) || Node <- Nodes],
+ disconnect(Config).
+
+test_get_subscriptions(Config) ->
+ Nodes = lists:sort([create_node(Config, <<>>) || _ <- lists:seq(1, 5)]),
+ [subscribe_node(Config, Node) || Node <- Nodes],
+ Subs = get_subscriptions(Config),
+ Nodes = lists:sort([Node || #ps_subscription{node = Node} <- Subs]),
+ [delete_node(Config, Node) || Node <- Nodes],
+ disconnect(Config).
+
+test_purge(Config) ->
+ Node = create_node(Config, <<>>),
+ ItemsIn = [publish_item(Config, Node) || _ <- lists:seq(1, 5)],
+ ItemsOut = get_items(Config, Node),
+ true = [I || #ps_item{id = I} <- lists:sort(ItemsIn)]
+ == [I || #ps_item{id = I} <- lists:sort(ItemsOut)],
+ purge_node(Config, Node),
+ [] = get_items(Config, Node),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+test_delete(Config) ->
+ Node = ?config(pubsub_node, Config),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {pubsub_master_slave, [sequence],
+ [master_slave_test(publish),
+ master_slave_test(subscriptions),
+ master_slave_test(affiliations),
+ master_slave_test(authorize)]}.
+
+publish_master(Config) ->
+ Node = create_node(Config, <<>>),
+ put_event(Config, Node),
+ wait_for_slave(Config),
+ #ps_item{id = ID} = publish_item(Config, Node),
+ #ps_item{id = ID} = get_event(Config),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+publish_slave(Config) ->
+ Node = get_event(Config),
+ subscribe_node(Config, Node),
+ wait_for_master(Config),
+ #message{
+ sub_els =
+ [#ps_event{
+ items = #ps_items{node = Node,
+ items = [Item]}}]} = recv_message(Config),
+ put_event(Config, Item),
+ disconnect(Config).
+
+subscriptions_master(Config) ->
+ Peer = ?config(slave, Config),
+ Node = ?config(pubsub_node, Config),
+ Node = create_node(Config, Node),
+ [] = get_subscriptions(Config, Node),
+ wait_for_slave(Config),
+ lists:foreach(
+ fun(Type) ->
+ ok = set_subscriptions(Config, Node, [{Peer, Type}]),
+ #ps_item{} = publish_item(Config, Node),
+ case get_subscriptions(Config, Node) of
+ [] when Type == none; Type == pending ->
+ ok;
+ [#ps_subscription{jid = Peer, type = Type}] ->
+ ok
+ end
+ end, [subscribed, unconfigured, pending, none]),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+subscriptions_slave(Config) ->
+ wait_for_master(Config),
+ MyJID = my_jid(Config),
+ Node = ?config(pubsub_node, Config),
+ lists:foreach(
+ fun(subscribed = Type) ->
+ ?recv2(#message{
+ sub_els =
+ [#ps_event{
+ subscription = #ps_subscription{
+ node = Node,
+ jid = MyJID,
+ type = Type}}]},
+ #message{sub_els = [#ps_event{}]});
+ (Type) ->
+ #message{
+ sub_els =
+ [#ps_event{
+ subscription = #ps_subscription{
+ node = Node,
+ jid = MyJID,
+ type = Type}}]} =
+ recv_message(Config)
+ end, [subscribed, unconfigured, pending, none]),
+ disconnect(Config).
+
+affiliations_master(Config) ->
+ Peer = ?config(slave, Config),
+ BarePeer = jid:remove_resource(Peer),
+ lists:foreach(
+ fun(Aff) ->
+ Node = <<(atom_to_binary(Aff, utf8))/binary,
+ $-, (randoms:get_string())/binary>>,
+ create_node(Config, Node, default_node_config(Config)),
+ #ps_item{id = I} = publish_item(Config, Node),
+ ok = set_affiliations(Config, Node, [{Peer, Aff}]),
+ Affs = get_affiliations(Config, Node),
+ case lists:keyfind(BarePeer, #ps_affiliation.jid, Affs) of
+ false when Aff == none ->
+ ok;
+ #ps_affiliation{type = Aff} ->
+ ok
+ end,
+ put_event(Config, {Aff, Node, I}),
+ wait_for_slave(Config),
+ delete_node(Config, Node)
+ end, [outcast, none, member, publish_only, publisher, owner]),
+ put_event(Config, disconnect),
+ disconnect(Config).
+
+affiliations_slave(Config) ->
+ affiliations_slave(Config, get_event(Config)).
+
+affiliations_slave(Config, {outcast, Node, ItemID}) ->
+ #stanza_error{reason = 'forbidden'} = subscribe_node(Config, Node),
+ #stanza_error{} = unsubscribe_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_items(Config, Node),
+ #stanza_error{reason = 'forbidden'} = publish_item(Config, Node),
+ #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
+ #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_node_config(Config, Node, default_node_config(Config)),
+ #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
+ #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_affiliations(Config, Node, [{?config(master, Config), outcast},
+ {my_jid(Config), owner}]),
+ #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
+ wait_for_master(Config),
+ affiliations_slave(Config, get_event(Config));
+affiliations_slave(Config, {none, Node, ItemID}) ->
+ #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
+ ok = unsubscribe_node(Config, Node),
+ %% This violates the affiliation char from section 4.1
+ [_|_] = get_items(Config, Node),
+ #stanza_error{reason = 'forbidden'} = publish_item(Config, Node),
+ #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
+ #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_node_config(Config, Node, default_node_config(Config)),
+ #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
+ #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_affiliations(Config, Node, [{?config(master, Config), outcast},
+ {my_jid(Config), owner}]),
+ #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
+ wait_for_master(Config),
+ affiliations_slave(Config, get_event(Config));
+affiliations_slave(Config, {member, Node, ItemID}) ->
+ #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
+ ok = unsubscribe_node(Config, Node),
+ [_|_] = get_items(Config, Node),
+ #stanza_error{reason = 'forbidden'} = publish_item(Config, Node),
+ #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
+ #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_node_config(Config, Node, default_node_config(Config)),
+ #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
+ #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_affiliations(Config, Node, [{?config(master, Config), outcast},
+ {my_jid(Config), owner}]),
+ #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
+ wait_for_master(Config),
+ affiliations_slave(Config, get_event(Config));
+affiliations_slave(Config, {publish_only, Node, ItemID}) ->
+ #stanza_error{reason = 'forbidden'} = subscribe_node(Config, Node),
+ #stanza_error{} = unsubscribe_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_items(Config, Node),
+ #ps_item{id = _MyItemID} = publish_item(Config, Node),
+ %% BUG: This should be fixed
+ %% ?match(ok, delete_item(Config, Node, MyItemID)),
+ #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
+ #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_node_config(Config, Node, default_node_config(Config)),
+ #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
+ #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_affiliations(Config, Node, [{?config(master, Config), outcast},
+ {my_jid(Config), owner}]),
+ #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
+ wait_for_master(Config),
+ affiliations_slave(Config, get_event(Config));
+affiliations_slave(Config, {publisher, Node, _ItemID}) ->
+ #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
+ ok = unsubscribe_node(Config, Node),
+ [_|_] = get_items(Config, Node),
+ #ps_item{id = MyItemID} = publish_item(Config, Node),
+ ok = delete_item(Config, Node, MyItemID),
+ %% BUG: this should be fixed
+ %% #stanza_error{reason = 'forbidden'} = delete_item(Config, Node, ItemID),
+ #stanza_error{reason = 'forbidden'} = purge_node(Config, Node),
+ #stanza_error{reason = 'forbidden'} = get_node_config(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_node_config(Config, Node, default_node_config(Config)),
+ #stanza_error{reason = 'forbidden'} = get_subscriptions(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_subscriptions(Config, Node, [{my_jid(Config), subscribed}]),
+ #stanza_error{reason = 'forbidden'} = get_affiliations(Config, Node),
+ #stanza_error{reason = 'forbidden'} =
+ set_affiliations(Config, Node, [{?config(master, Config), outcast},
+ {my_jid(Config), owner}]),
+ #stanza_error{reason = 'forbidden'} = delete_node(Config, Node),
+ wait_for_master(Config),
+ affiliations_slave(Config, get_event(Config));
+affiliations_slave(Config, {owner, Node, ItemID}) ->
+ MyJID = my_jid(Config),
+ Peer = ?config(master, Config),
+ #ps_subscription{type = subscribed} = subscribe_node(Config, Node),
+ ok = unsubscribe_node(Config, Node),
+ [_|_] = get_items(Config, Node),
+ #ps_item{id = MyItemID} = publish_item(Config, Node),
+ ok = delete_item(Config, Node, MyItemID),
+ ok = delete_item(Config, Node, ItemID),
+ ok = purge_node(Config, Node),
+ [_|_] = get_node_config(Config, Node),
+ ok = set_node_config(Config, Node, default_node_config(Config)),
+ ok = set_subscriptions(Config, Node, []),
+ [] = get_subscriptions(Config, Node),
+ ok = set_affiliations(Config, Node, [{Peer, outcast}, {MyJID, owner}]),
+ [_, _] = get_affiliations(Config, Node),
+ ok = delete_node(Config, Node),
+ wait_for_master(Config),
+ affiliations_slave(Config, get_event(Config));
+affiliations_slave(Config, disconnect) ->
+ disconnect(Config).
+
+authorize_master(Config) ->
+ send(Config, #presence{}),
+ #presence{} = recv_presence(Config),
+ Peer = ?config(slave, Config),
+ PJID = pubsub_jid(Config),
+ NodeConfig = set_opts(default_node_config(Config),
+ [{access_model, authorize}]),
+ Node = ?config(pubsub_node, Config),
+ Node = create_node(Config, Node, NodeConfig),
+ wait_for_slave(Config),
+ #message{sub_els = [#xdata{fields = F1}]} = recv_message(Config),
+ C1 = pubsub_subscribe_authorization:decode(F1),
+ Node = proplists:get_value(node, C1),
+ Peer = proplists:get_value(subscriber_jid, C1),
+ %% Deny it at first
+ Deny = #xdata{type = submit,
+ fields = pubsub_subscribe_authorization:encode(
+ [{node, Node},
+ {subscriber_jid, Peer},
+ {allow, false}])},
+ send(Config, #message{to = PJID, sub_els = [Deny]}),
+ %% We should not have any subscriptions
+ [] = get_subscriptions(Config, Node),
+ wait_for_slave(Config),
+ #message{sub_els = [#xdata{fields = F2}]} = recv_message(Config),
+ C2 = pubsub_subscribe_authorization:decode(F2),
+ Node = proplists:get_value(node, C2),
+ Peer = proplists:get_value(subscriber_jid, C2),
+ %% Now we accept is as the peer is very insisting ;)
+ Approve = #xdata{type = submit,
+ fields = pubsub_subscribe_authorization:encode(
+ [{node, Node},
+ {subscriber_jid, Peer},
+ {allow, true}])},
+ send(Config, #message{to = PJID, sub_els = [Approve]}),
+ wait_for_slave(Config),
+ delete_node(Config, Node),
+ disconnect(Config).
+
+authorize_slave(Config) ->
+ Node = ?config(pubsub_node, Config),
+ MyJID = my_jid(Config),
+ wait_for_master(Config),
+ #ps_subscription{type = pending} = subscribe_node(Config, Node),
+ %% We're denied at first
+ #message{
+ sub_els =
+ [#ps_event{
+ subscription = #ps_subscription{type = none,
+ jid = MyJID}}]} =
+ recv_message(Config),
+ wait_for_master(Config),
+ #ps_subscription{type = pending} = subscribe_node(Config, Node),
+ %% Now much better!
+ #message{
+ sub_els =
+ [#ps_event{
+ subscription = #ps_subscription{type = subscribed,
+ jid = MyJID}}]} =
+ recv_message(Config),
+ wait_for_master(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("pubsub_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("pubsub_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("pubsub_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("pubsub_" ++ atom_to_list(T) ++ "_slave")]}.
+
+set_opts(Config, Options) ->
+ lists:foldl(
+ fun({Opt, Val}, Acc) ->
+ lists:keystore(Opt, 1, Acc, {Opt, Val})
+ end, Config, Options).
+
+create_node(Config, Node) ->
+ create_node(Config, Node, undefined).
+
+create_node(Config, Node, Options) ->
+ PJID = pubsub_jid(Config),
+ NodeConfig = if is_list(Options) ->
+ #xdata{type = submit,
+ fields = pubsub_node_config:encode(Options)};
+ true ->
+ undefined
+ end,
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub{create = Node,
+ configure = {<<>>, NodeConfig}}]}) of
+ #iq{type = result, sub_els = [#pubsub{create = NewNode}]} ->
+ NewNode;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+delete_node(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub_owner{delete = {Node, <<>>}}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+purge_node(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub_owner{purge = Node}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_default_node_config(Config) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub_owner{default = {<<>>, undefined}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub_owner{default = {<<>>, NodeConfig}}]} ->
+ pubsub_node_config:decode(NodeConfig#xdata.fields);
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_node_config(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub_owner{configure = {Node, undefined}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub_owner{configure = {Node, NodeConfig}}]} ->
+ pubsub_node_config:decode(NodeConfig#xdata.fields);
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+set_node_config(Config, Node, Options) ->
+ PJID = pubsub_jid(Config),
+ NodeConfig = #xdata{type = submit,
+ fields = pubsub_node_config:encode(Options)},
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub_owner{configure =
+ {Node, NodeConfig}}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+publish_item(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ ItemID = randoms:get_string(),
+ Item = #ps_item{id = ItemID, xml_els = [xmpp:encode(#presence{id = ItemID})]},
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub{publish = #ps_publish{
+ node = Node,
+ items = [Item]}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub{publish = #ps_publish{
+ node = Node,
+ items = [#ps_item{id = ItemID}]}}]} ->
+ Item;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_items(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub{items = #ps_items{node = Node}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub{items = #ps_items{node = Node, items = Items}}]} ->
+ Items;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+delete_item(Config, Node, I) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub{retract =
+ #ps_retract{
+ node = Node,
+ items = [#ps_item{id = I}]}}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+subscribe_node(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ MyJID = my_jid(Config),
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub{subscribe = #ps_subscribe{
+ node = Node,
+ jid = MyJID}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub{
+ subscription = #ps_subscription{
+ node = Node,
+ jid = MyJID} = Sub}]} ->
+ Sub;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+unsubscribe_node(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ MyJID = my_jid(Config),
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub{
+ unsubscribe = #ps_unsubscribe{
+ node = Node,
+ jid = MyJID}}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_affiliations(Config) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub{affiliations = {<<>>, []}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub{affiliations = {<<>>, Affs}}]} ->
+ Affs;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_affiliations(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub_owner{affiliations = {Node, []}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub_owner{affiliations = {Node, Affs}}]} ->
+ Affs;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+set_affiliations(Config, Node, JTs) ->
+ PJID = pubsub_jid(Config),
+ Affs = [#ps_affiliation{jid = J, type = T} || {J, T} <- JTs],
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub_owner{affiliations =
+ {Node, Affs}}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_subscriptions(Config) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub{subscriptions = {<<>>, []}}]}) of
+ #iq{type = result, sub_els = [#pubsub{subscriptions = {<<>>, Subs}}]} ->
+ Subs;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+get_subscriptions(Config, Node) ->
+ PJID = pubsub_jid(Config),
+ case send_recv(Config,
+ #iq{type = get, to = PJID,
+ sub_els = [#pubsub_owner{subscriptions = {Node, []}}]}) of
+ #iq{type = result,
+ sub_els = [#pubsub_owner{subscriptions = {Node, Subs}}]} ->
+ Subs;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+set_subscriptions(Config, Node, JTs) ->
+ PJID = pubsub_jid(Config),
+ Subs = [#ps_subscription{jid = J, type = T} || {J, T} <- JTs],
+ case send_recv(Config,
+ #iq{type = set, to = PJID,
+ sub_els = [#pubsub_owner{subscriptions =
+ {Node, Subs}}]}) of
+ #iq{type = result, sub_els = []} ->
+ ok;
+ #iq{type = error} = IQ ->
+ xmpp:get_subtag(IQ, #stanza_error{})
+ end.
+
+default_node_config(Config) ->
+ [{title, ?config(pubsub_node_title, Config)},
+ {notify_delete, false},
+ {send_last_published_item, never}].
diff --git a/test/replaced_tests.erl b/test/replaced_tests.erl
new file mode 100644
index 00000000..e50c27f0
--- /dev/null
+++ b/test/replaced_tests.erl
@@ -0,0 +1,57 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(replaced_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [bind/1, wait_for_slave/1, wait_for_master/1, recv/1,
+ close_socket/1, disconnect/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {replaced_single, [sequence], []}.
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {replaced_master_slave, [sequence], []}.
+%% Disable tests for now due to a race condition
+%% because ejabberd_sm:sid() is generated in ejabberd_s2s:init()
+%%[master_slave_test(conflict)]}.
+
+conflict_master(Config0) ->
+ Config = bind(Config0),
+ wait_for_slave(Config),
+ #stream_error{reason = conflict} = recv(Config),
+ {xmlstreamend, <<"stream:stream">>} = recv(Config),
+ close_socket(Config).
+
+conflict_slave(Config0) ->
+ wait_for_master(Config0),
+ Config = bind(Config0),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("replaced_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("replaced_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("replaced_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("replaced_" ++ atom_to_list(T) ++ "_slave")]}.
diff --git a/test/roster_tests.erl b/test/roster_tests.erl
index 2d05709a..4aa06b95 100644
--- a/test/roster_tests.erl
+++ b/test/roster_tests.erl
@@ -13,8 +13,7 @@
-import(suite, [send_recv/2, recv_iq/1, send/2, disconnect/1, del_roster/1,
del_roster/2, make_iq_result/1, wait_for_slave/1,
wait_for_master/1, recv_presence/1, self_presence/2,
- put_event/2, get_event/1, match_failure/2, get_roster/1,
- is_feature_advertised/2]).
+ put_event/2, get_event/1, match_failure/2, get_roster/1]).
-include("suite.hrl").
-include("mod_roster.hrl").
@@ -132,7 +131,7 @@ version(Config) ->
%%% Master-slave tests
%%%===================================================================
master_slave_cases() ->
- {roster_master_slave, [parallel],
+ {roster_master_slave, [sequence],
[master_slave_test(subscribe)]}.
subscribe_master(Config) ->
@@ -149,6 +148,7 @@ process_subscriptions_master(Config, Actions) ->
self_presence(Config, available),
lists:foldl(
fun({N, {Dir, Type}}, State) ->
+ timer:sleep(100),
if Dir == out -> put_event(Config, {N, in, Type});
Dir == in -> put_event(Config, {N, out, Type})
end,
diff --git a/test/sm_tests.erl b/test/sm_tests.erl
new file mode 100644
index 00000000..0a74d392
--- /dev/null
+++ b/test/sm_tests.erl
@@ -0,0 +1,99 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(sm_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [send/2, recv/1, close_socket/1, set_opt/3, my_jid/1,
+ recv_message/1, disconnect/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {sm_single, [sequence],
+ [single_test(feature_enabled),
+ single_test(enable),
+ single_test(resume),
+ single_test(resume_failed)]}.
+
+feature_enabled(Config) ->
+ true = ?config(sm, Config),
+ disconnect(Config).
+
+enable(Config) ->
+ Server = ?config(server, Config),
+ ServerJID = jid:make(<<"">>, Server, <<"">>),
+ %% Send messages of type 'headline' so the server discards them silently
+ Msg = #message{to = ServerJID, type = headline,
+ body = [#text{data = <<"body">>}]},
+ %% Enable the session management with resumption enabled
+ send(Config, #sm_enable{resume = true, xmlns = ?NS_STREAM_MGMT_3}),
+ #sm_enabled{id = ID, resume = true} = recv(Config),
+ %% Initial request; 'h' should be 0.
+ send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}),
+ #sm_a{h = 0} = recv(Config),
+ %% sending two messages and requesting again; 'h' should be 3.
+ send(Config, Msg),
+ send(Config, Msg),
+ send(Config, Msg),
+ send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}),
+ #sm_a{h = 3} = recv(Config),
+ close_socket(Config),
+ {save_config, set_opt(sm_previd, ID, Config)}.
+
+resume(Config) ->
+ {_, SMConfig} = ?config(saved_config, Config),
+ ID = ?config(sm_previd, SMConfig),
+ Server = ?config(server, Config),
+ ServerJID = jid:make(<<"">>, Server, <<"">>),
+ MyJID = my_jid(Config),
+ Txt = #text{data = <<"body">>},
+ Msg = #message{from = ServerJID, to = MyJID, body = [Txt]},
+ %% Route message. The message should be queued by the C2S process.
+ ejabberd_router:route(ServerJID, MyJID, Msg),
+ send(Config, #sm_resume{previd = ID, h = 0, xmlns = ?NS_STREAM_MGMT_3}),
+ #sm_resumed{previd = ID, h = 3} = recv(Config),
+ #message{from = ServerJID, to = MyJID, body = [Txt]} = recv_message(Config),
+ #sm_r{} = recv(Config),
+ send(Config, #sm_a{h = 1, xmlns = ?NS_STREAM_MGMT_3}),
+ %% Send another stanza to increment the server's 'h' for sm_resume_failed.
+ send(Config, #presence{to = ServerJID}),
+ close_socket(Config),
+ {save_config, set_opt(sm_previd, ID, Config)}.
+
+resume_failed(Config) ->
+ {_, SMConfig} = ?config(saved_config, Config),
+ ID = ?config(sm_previd, SMConfig),
+ ct:sleep(5000), % Wait for session to time out.
+ send(Config, #sm_resume{previd = ID, h = 1, xmlns = ?NS_STREAM_MGMT_3}),
+ #sm_failed{reason = 'item-not-found', h = 4} = recv(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {sm_master_slave, [sequence], []}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("sm_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("sm_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("sm_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("sm_" ++ atom_to_list(T) ++ "_slave")]}.
diff --git a/test/suite.erl b/test/suite.erl
index 52c030df..a288a5f6 100644
--- a/test/suite.erl
+++ b/test/suite.erl
@@ -488,8 +488,9 @@ decode(El, NS, Opts) ->
[format_element(El), xmpp:pp(Pkt)]),
Pkt
catch _:{xmpp_codec, Why} ->
- ct:fail("recv failed: ~p->~n~s",
- [El, xmpp:format_error(Why)])
+ ct:pal("recv failed: ~p->~n~s",
+ [El, xmpp:format_error(Why)]),
+ erlang:error({xmpp_codec, Why})
end.
send_text(Config, Text) ->
diff --git a/test/vcard_tests.erl b/test/vcard_tests.erl
new file mode 100644
index 00000000..bb3efb47
--- /dev/null
+++ b/test/vcard_tests.erl
@@ -0,0 +1,125 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 16 Nov 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(vcard_tests).
+
+%% API
+-compile(export_all).
+-import(suite, [send_recv/2, disconnect/1, is_feature_advertised/2,
+ is_feature_advertised/3,
+ my_jid/1, wait_for_slave/1, wait_for_master/1,
+ recv_presence/1, recv/1]).
+
+-include("suite.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+%%%===================================================================
+%%% Single user tests
+%%%===================================================================
+single_cases() ->
+ {vcard_single, [sequence],
+ [single_test(feature_enabled),
+ single_test(get_set)]}.
+
+feature_enabled(Config) ->
+ BareMyJID = jid:remove_resource(my_jid(Config)),
+ true = is_feature_advertised(Config, ?NS_VCARD),
+ true = is_feature_advertised(Config, ?NS_VCARD, BareMyJID),
+ disconnect(Config).
+
+get_set(Config) ->
+ VCard =
+ #vcard_temp{fn = <<"Peter Saint-Andre">>,
+ n = #vcard_name{family = <<"Saint-Andre">>,
+ given = <<"Peter">>},
+ nickname = <<"stpeter">>,
+ bday = <<"1966-08-06">>,
+ adr = [#vcard_adr{work = true,
+ extadd = <<"Suite 600">>,
+ street = <<"1899 Wynkoop Street">>,
+ locality = <<"Denver">>,
+ region = <<"CO">>,
+ pcode = <<"80202">>,
+ ctry = <<"USA">>},
+ #vcard_adr{home = true,
+ locality = <<"Denver">>,
+ region = <<"CO">>,
+ pcode = <<"80209">>,
+ ctry = <<"USA">>}],
+ tel = [#vcard_tel{work = true,voice = true,
+ number = <<"303-308-3282">>},
+ #vcard_tel{home = true,voice = true,
+ number = <<"303-555-1212">>}],
+ email = [#vcard_email{internet = true,pref = true,
+ userid = <<"stpeter@jabber.org">>}],
+ jabberid = <<"stpeter@jabber.org">>,
+ title = <<"Executive Director">>,role = <<"Patron Saint">>,
+ org = #vcard_org{name = <<"XMPP Standards Foundation">>},
+ url = <<"http://www.xmpp.org/xsf/people/stpeter.shtml">>,
+ desc = <<"More information about me is located on my "
+ "personal website: http://www.saint-andre.com/">>},
+ #iq{type = result, sub_els = []} =
+ send_recv(Config, #iq{type = set, sub_els = [VCard]}),
+ %% TODO: check if VCard == VCard1.
+ #iq{type = result, sub_els = [_VCard1]} =
+ send_recv(Config, #iq{type = get, sub_els = [#vcard_temp{}]}),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Master-slave tests
+%%%===================================================================
+master_slave_cases() ->
+ {vcard_master_slave, [sequence], []}.
+ %%[master_slave_test(xupdate)]}.
+
+xupdate_master(Config) ->
+ Img = <<137, "PNG\r\n", 26, $\n>>,
+ ImgHash = p1_sha:sha(Img),
+ MyJID = my_jid(Config),
+ Peer = ?config(slave, Config),
+ wait_for_slave(Config),
+ #presence{from = MyJID, type = available} = send_recv(Config, #presence{}),
+ #presence{from = Peer, type = available} = recv_presence(Config),
+ VCard = #vcard_temp{photo = #vcard_photo{type = <<"image/png">>, binval = Img}},
+ #iq{type = result, sub_els = []} =
+ send_recv(Config, #iq{type = set, sub_els = [VCard]}),
+ #presence{from = MyJID, type = available,
+ sub_els = [#vcard_xupdate{hash = ImgHash}]} = recv_presence(Config),
+ #iq{type = result, sub_els = []} =
+ send_recv(Config, #iq{type = set, sub_els = [#vcard_temp{}]}),
+ ?recv2(#presence{from = MyJID, type = available,
+ sub_els = [#vcard_xupdate{hash = undefined}]},
+ #presence{from = Peer, type = unavailable}),
+ disconnect(Config).
+
+xupdate_slave(Config) ->
+ Img = <<137, "PNG\r\n", 26, $\n>>,
+ ImgHash = p1_sha:sha(Img),
+ MyJID = my_jid(Config),
+ Peer = ?config(master, Config),
+ #presence{from = MyJID, type = available} = send_recv(Config, #presence{}),
+ wait_for_master(Config),
+ #presence{from = Peer, type = available} = recv_presence(Config),
+ #presence{from = Peer, type = available,
+ sub_els = [#vcard_xupdate{hash = ImgHash}]} = recv_presence(Config),
+ #presence{from = Peer, type = available,
+ sub_els = [#vcard_xupdate{hash = undefined}]} = recv_presence(Config),
+ disconnect(Config).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+single_test(T) ->
+ list_to_atom("vcard_" ++ atom_to_list(T)).
+
+master_slave_test(T) ->
+ {list_to_atom("vcard_" ++ atom_to_list(T)), [parallel],
+ [list_to_atom("vcard_" ++ atom_to_list(T) ++ "_master"),
+ list_to_atom("vcard_" ++ atom_to_list(T) ++ "_slave")]}.