diff options
Diffstat (limited to 'test/privacy_tests.erl')
-rw-r--r-- | test/privacy_tests.erl | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/test/privacy_tests.erl b/test/privacy_tests.erl new file mode 100644 index 000000000..2ee945f1e --- /dev/null +++ b/test/privacy_tests.erl @@ -0,0 +1,821 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net> +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 18 Oct 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net> +%%%------------------------------------------------------------------- +-module(privacy_tests). + +%% API +-compile(export_all). +-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]). +-include("suite.hrl"). +-include("mod_roster.hrl"). + +%%%=================================================================== +%%% API +%%%=================================================================== +%%%=================================================================== +%%% Single cases +%%%=================================================================== +single_cases() -> + {privacy_single, [sequence], + [single_test(feature_enabled), + single_test(set_get_list), + single_test(get_list_non_existent), + single_test(set_default), + single_test(del_default), + single_test(set_default_non_existent), + single_test(set_active), + single_test(del_active), + single_test(set_active_non_existent), + single_test(remove_list), + single_test(remove_default_list), + single_test(remove_active_list), + %% TODO: this should be fixed + %% single_test(remove_list_non_existent), + single_test(allow_local_server), + single_test(malformed_iq_query), + single_test(malformed_get), + single_test(malformed_set), + single_test(malformed_type_value), + single_test(set_get_block)]}. + +feature_enabled(Config) -> + Features = get_features(Config), + true = lists:member(?NS_PRIVACY, Features), + true = lists:member(?NS_BLOCKING, Features), + disconnect(Config). + +set_get_list(Config) -> + ListName = <<"set-get-list">>, + Items = [#privacy_item{order = 0, action = deny, + type = jid, value = <<"user@jabber.org">>, + iq = true}, + #privacy_item{order = 1, action = allow, + type = group, value = <<"group">>, + message = true}, + #privacy_item{order = 2, action = allow, + type = subscription, value = <<"both">>, + presence_in = true}, + #privacy_item{order = 3, action = deny, + type = subscription, value = <<"from">>, + presence_out = true}, + #privacy_item{order = 4, action = deny, + type = subscription, value = <<"to">>, + iq = true, message = true}, + #privacy_item{order = 5, action = deny, + type = subscription, value = <<"none">>, + _ = true}, + #privacy_item{order = 6, action = deny}], + ok = set_items(Config, ListName, Items), + #privacy_list{name = ListName, items = Items1} = get_list(Config, ListName), + Items = lists:keysort(#privacy_item.order, Items1), + del_privacy(disconnect(Config)). + +get_list_non_existent(Config) -> + ListName = <<"get-list-non-existent">>, + #stanza_error{reason = 'item-not-found'} = get_list(Config, ListName), + disconnect(Config). + +set_default(Config) -> + ListName = <<"set-default">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_default(Config, ListName), + #privacy_query{default = ListName} = get_lists(Config), + del_privacy(disconnect(Config)). + +del_default(Config) -> + ListName = <<"del-default">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_default(Config, ListName), + #privacy_query{default = ListName} = get_lists(Config), + ok = set_default(Config, none), + #privacy_query{default = none} = get_lists(Config), + del_privacy(disconnect(Config)). + +set_default_non_existent(Config) -> + ListName = <<"set-default-non-existent">>, + #stanza_error{reason = 'item-not-found'} = set_default(Config, ListName), + disconnect(Config). + +set_active(Config) -> + ListName = <<"set-active">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_active(Config, ListName), + #privacy_query{active = ListName} = get_lists(Config), + del_privacy(disconnect(Config)). + +del_active(Config) -> + ListName = <<"del-active">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_active(Config, ListName), + #privacy_query{active = ListName} = get_lists(Config), + ok = set_active(Config, none), + #privacy_query{active = none} = get_lists(Config), + del_privacy(disconnect(Config)). + +set_active_non_existent(Config) -> + ListName = <<"set-active-non-existent">>, + #stanza_error{reason = 'item-not-found'} = set_active(Config, ListName), + disconnect(Config). + +remove_list(Config) -> + ListName = <<"remove-list">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = del_list(Config, ListName), + #privacy_query{lists = []} = get_lists(Config), + del_privacy(disconnect(Config)). + +remove_active_list(Config) -> + ListName = <<"remove-active-list">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_active(Config, ListName), + #stanza_error{reason = 'conflict'} = del_list(Config, ListName), + del_privacy(disconnect(Config)). + +remove_default_list(Config) -> + ListName = <<"remove-default-list">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_default(Config, ListName), + #stanza_error{reason = 'conflict'} = del_list(Config, ListName), + del_privacy(disconnect(Config)). + +remove_list_non_existent(Config) -> + ListName = <<"remove-list-non-existent">>, + #stanza_error{reason = 'item-not-found'} = del_list(Config, ListName), + disconnect(Config). + +allow_local_server(Config) -> + ListName = <<"allow-local-server">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_active(Config, ListName), + %% Whatever privacy rules are set, we should always communicate + %% with our home server + server_send_iqs(Config), + server_recv_iqs(Config), + send_stanzas_to_server_resource(Config), + del_privacy(disconnect(Config)). + +malformed_iq_query(Config) -> + lists:foreach( + fun(Type) -> + #iq{type = error} = + send_recv(Config, + #iq{type = Type, + sub_els = [#privacy_list{name = <<"foo">>}]}) + end, [get, set]), + disconnect(Config). + +malformed_get(Config) -> + JID = jid:make(randoms:get_string()), + lists:foreach( + fun(SubEl) -> + #iq{type = error} = + send_recv(Config, #iq{type = get, sub_els = [SubEl]}) + end, [#privacy_query{active = none}, + #privacy_query{default = none}, + #privacy_query{lists = [#privacy_list{name = <<"1">>}, + #privacy_list{name = <<"2">>}]}, + #block{items = [JID]}, #unblock{items = [JID]}, + #block{}, #unblock{}]), + disconnect(Config). + +malformed_set(Config) -> + lists:foreach( + fun(SubEl) -> + #iq{type = error} = + send_recv(Config, #iq{type = set, sub_els = [SubEl]}) + end, [#privacy_query{active = none, default = none}, + #privacy_query{lists = [#privacy_list{name = <<"1">>}, + #privacy_list{name = <<"2">>}]}, + #block{}, + #block_list{}, + #block_list{items = [jid:make(randoms:get_string())]}]). + +malformed_type_value(Config) -> + Item = #privacy_item{order = 0, action = deny}, + #stanza_error{reason = 'bad-request'} = + set_items(Config, <<"malformed-jid">>, + [Item#privacy_item{type = jid, value = <<"@bad">>}]), + #stanza_error{reason = 'bad-request'} = + set_items(Config, <<"malformed-group">>, + [Item#privacy_item{type = group, value = <<"">>}]), + #stanza_error{reason = 'bad-request'} = + set_items(Config, <<"malformed-subscription">>, + [Item#privacy_item{type = subscription, value = <<"bad">>}]), + disconnect(Config). + +set_get_block(Config) -> + J1 = jid:make(randoms:get_string(), randoms:get_string()), + J2 = jid:make(randoms:get_string(), randoms:get_string()), + {ok, ListName} = set_block(Config, [J1, J2]), + JIDs = get_block(Config), + JIDs = lists:sort([J1, J2]), + {ok, ListName} = set_unblock(Config, [J2, J1]), + [] = get_block(Config), + del_privacy(disconnect(Config)). + +%%%=================================================================== +%%% Master-slave cases +%%%=================================================================== +master_slave_cases() -> + {privacy_master_slave, [parallel], + [master_slave_test(deny_bare_jid), + master_slave_test(deny_full_jid), + master_slave_test(deny_server_jid), + master_slave_test(deny_group), + master_slave_test(deny_sub_both), + master_slave_test(deny_sub_from), + master_slave_test(deny_sub_to), + master_slave_test(deny_sub_none), + master_slave_test(deny_all), + master_slave_test(deny_offline), + master_slave_test(block), + master_slave_test(unblock), + master_slave_test(unblock_all)]}. + +deny_bare_jid_master(Config) -> + PeerJID = ?config(peer, Config), + PeerBareJID = jid:remove_resource(PeerJID), + deny_master(Config, {jid, jid:to_string(PeerBareJID)}). + +deny_bare_jid_slave(Config) -> + deny_slave(Config). + +deny_full_jid_master(Config) -> + PeerJID = ?config(peer, Config), + deny_master(Config, {jid, jid:to_string(PeerJID)}). + +deny_full_jid_slave(Config) -> + deny_slave(Config). + +deny_server_jid_master(Config) -> + {_, Server, _} = jid:tolower(?config(peer, Config)), + deny_master(Config, {jid, Server}). + +deny_server_jid_slave(Config) -> + deny_slave(Config). + +deny_group_master(Config) -> + Group = randoms:get_string(), + deny_master(Config, {group, Group}). + +deny_group_slave(Config) -> + deny_slave(Config). + +deny_sub_both_master(Config) -> + deny_master(Config, {subscription, <<"both">>}). + +deny_sub_both_slave(Config) -> + deny_slave(Config). + +deny_sub_from_master(Config) -> + deny_master(Config, {subscription, <<"from">>}). + +deny_sub_from_slave(Config) -> + deny_slave(Config). + +deny_sub_to_master(Config) -> + deny_master(Config, {subscription, <<"to">>}). + +deny_sub_to_slave(Config) -> + deny_slave(Config). + +deny_sub_none_master(Config) -> + deny_master(Config, {subscription, <<"none">>}). + +deny_sub_none_slave(Config) -> + deny_slave(Config). + +deny_all_master(Config) -> + deny_master(Config, {undefined, <<"">>}). + +deny_all_slave(Config) -> + deny_slave(Config). + +deny_master(Config, {Type, Value}) -> + Sub = if Type == subscription -> + erlang:binary_to_atom(Value, utf8); + true -> + both + end, + Groups = if Type == group -> [Value]; + true -> [] + end, + set_roster(Config, Sub, Groups), + lists:foreach( + fun(Opts) -> + ListName = str:format("deny-~s-~s-~p", [Type, Value, Opts]), + Item = #privacy_item{order = 0, + action = deny, + iq = proplists:get_bool(iq, Opts), + message = proplists:get_bool(message, Opts), + presence_in = proplists:get_bool(presence_in, Opts), + presence_out = proplists:get_bool(presence_out, Opts), + type = Type, + value = Value}, + ok = set_items(Config, ListName, [Item]), + ok = set_active(Config, ListName), + put_event(Config, Opts), + case is_presence_in_blocked(Opts) of + true -> ok; + false -> recv_presences(Config) + end, + case is_iq_in_blocked(Opts) of + true -> ok; + false -> recv_iqs(Config) + end, + case is_message_in_blocked(Opts) of + true -> ok; + false -> recv_messages(Config) + end, + ct:comment("Waiting for 'send' command from the slave"), + send = get_event(Config), + case is_presence_out_blocked(Opts) of + true -> check_presence_blocked(Config, 'not-acceptable'); + false -> ok + end, + case is_iq_out_blocked(Opts) of + true -> check_iq_blocked(Config, 'not-acceptable'); + false -> send_iqs(Config) + end, + case is_message_out_blocked(Opts) of + true -> check_message_blocked(Config, 'not-acceptable'); + false -> send_messages(Config) + end, + case is_other_blocked(Opts) of + true -> check_other_blocked(Config, 'not-acceptable'); + false -> ok + end, + ct:comment("Waiting for slave to finish processing our stanzas"), + done = get_event(Config) + end, + [[iq], [message], [presence_in], [presence_out], + [iq, message, presence_in, presence_out], []]), + put_event(Config, disconnect), + clean_up(disconnect(Config)). + +deny_slave(Config) -> + set_roster(Config, both, []), + deny_slave(Config, get_event(Config)). + +deny_slave(Config, disconnect) -> + clean_up(disconnect(Config)); +deny_slave(Config, Opts) -> + send_presences(Config), + case is_iq_in_blocked(Opts) of + true -> check_iq_blocked(Config, 'service-unavailable'); + false -> send_iqs(Config) + end, + case is_message_in_blocked(Opts) of + true -> check_message_blocked(Config, 'service-unavailable'); + false -> send_messages(Config) + end, + put_event(Config, send), + case is_iq_out_blocked(Opts) of + true -> ok; + false -> recv_iqs(Config) + end, + case is_message_out_blocked(Opts) of + true -> ok; + false -> recv_messages(Config) + end, + put_event(Config, done), + deny_slave(Config, get_event(Config)). + +deny_offline_master(Config) -> + set_roster(Config, both, []), + ListName = <<"deny-offline">>, + Item = #privacy_item{order = 0, action = deny}, + ok = set_items(Config, ListName, [Item]), + ok = set_default(Config, ListName), + NewConfig = disconnect(Config), + put_event(NewConfig, send), + ct:comment("Waiting for the slave to finish"), + done = get_event(NewConfig), + clean_up(NewConfig). + +deny_offline_slave(Config) -> + set_roster(Config, both, []), + ct:comment("Waiting for 'send' command from the master"), + send = get_event(Config), + send_presences(Config), + check_iq_blocked(Config, 'service-unavailable'), + check_message_blocked(Config, 'service-unavailable'), + put_event(Config, done), + clean_up(disconnect(Config)). + +block_master(Config) -> + PeerJID = ?config(peer, Config), + set_roster(Config, both, []), + {ok, _} = set_block(Config, [PeerJID]), + check_presence_blocked(Config, 'not-acceptable'), + check_iq_blocked(Config, 'not-acceptable'), + check_message_blocked(Config, 'not-acceptable'), + check_other_blocked(Config, 'not-acceptable'), + %% We should always be able to communicate with our home server + server_send_iqs(Config), + server_recv_iqs(Config), + send_stanzas_to_server_resource(Config), + put_event(Config, send), + done = get_event(Config), + clean_up(disconnect(Config)). + +block_slave(Config) -> + set_roster(Config, both, []), + ct:comment("Waiting for 'send' command from master"), + send = get_event(Config), + send_presences(Config), + check_iq_blocked(Config, 'service-unavailable'), + check_message_blocked(Config, 'service-unavailable'), + put_event(Config, done), + clean_up(disconnect(Config)). + +unblock_master(Config) -> + PeerJID = ?config(peer, Config), + set_roster(Config, both, []), + {ok, ListName} = set_block(Config, [PeerJID]), + {ok, ListName} = set_unblock(Config, [PeerJID]), + put_event(Config, send), + recv_presences(Config), + recv_iqs(Config), + recv_messages(Config), + clean_up(disconnect(Config)). + +unblock_slave(Config) -> + set_roster(Config, both, []), + ct:comment("Waiting for 'send' command from master"), + send = get_event(Config), + send_presences(Config), + send_iqs(Config), + send_messages(Config), + clean_up(disconnect(Config)). + +unblock_all_master(Config) -> + PeerJID = ?config(peer, Config), + set_roster(Config, both, []), + {ok, ListName} = set_block(Config, [PeerJID]), + {ok, ListName} = set_unblock(Config, []), + put_event(Config, send), + recv_presences(Config), + recv_iqs(Config), + recv_messages(Config), + clean_up(disconnect(Config)). + +unblock_all_slave(Config) -> + set_roster(Config, both, []), + ct:comment("Waiting for 'send' command from master"), + send = get_event(Config), + send_presences(Config), + send_iqs(Config), + send_messages(Config), + clean_up(disconnect(Config)). + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +single_test(T) -> + list_to_atom("privacy_" ++ atom_to_list(T)). + +master_slave_test(T) -> + {list_to_atom("privacy_" ++ atom_to_list(T)), [parallel], + [list_to_atom("privacy_" ++ atom_to_list(T) ++ "_master"), + list_to_atom("privacy_" ++ atom_to_list(T) ++ "_slave")]}. + +set_items(Config, Name, Items) -> + ct:comment("Setting privacy list ~s with items = ~p", [Name, Items]), + case send_recv( + Config, + #iq{type = set, sub_els = [#privacy_query{ + lists = [#privacy_list{ + name = Name, + items = Items}]}]}) of + #iq{type = result, sub_els = []} -> + ct:comment("Receiving privacy list push"), + #iq{type = set, id = ID, + sub_els = [#privacy_query{lists = [#privacy_list{ + name = Name}]}]} = + recv_iq(Config), + send(Config, #iq{type = result, id = ID}), + ok; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +get_list(Config, Name) -> + ct:comment("Requesting privacy list ~s", [Name]), + case send_recv(Config, + #iq{type = get, + sub_els = [#privacy_query{ + lists = [#privacy_list{name = Name}]}]}) of + #iq{type = result, sub_els = [#privacy_query{lists = [List]}]} -> + List; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +get_lists(Config) -> + ct:comment("Requesting privacy lists"), + case send_recv(Config, #iq{type = get, sub_els = [#privacy_query{}]}) of + #iq{type = result, sub_els = [SubEl]} -> + SubEl; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +del_list(Config, Name) -> + case send_recv( + Config, + #iq{type = set, sub_els = [#privacy_query{ + lists = [#privacy_list{ + name = Name}]}]}) of + #iq{type = result, sub_els = []} -> + ct:comment("Receiving privacy list push"), + #iq{type = set, id = ID, + sub_els = [#privacy_query{lists = [#privacy_list{ + name = Name}]}]} = + recv_iq(Config), + send(Config, #iq{type = result, id = ID}), + ok; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +set_active(Config, Name) -> + ct:comment("Setting active privacy list ~s", [Name]), + case send_recv( + Config, + #iq{type = set, sub_els = [#privacy_query{active = Name}]}) of + #iq{type = result, sub_els = []} -> + ok; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +set_default(Config, Name) -> + ct:comment("Setting default privacy list ~s", [Name]), + case send_recv( + Config, + #iq{type = set, sub_els = [#privacy_query{default = Name}]}) of + #iq{type = result, sub_els = []} -> + ok; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +get_block(Config) -> + case send_recv(Config, #iq{type = get, sub_els = [#block_list{}]}) of + #iq{type = result, sub_els = [#block_list{items = JIDs}]} -> + lists:sort(JIDs); + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +set_block(Config, JIDs) -> + case send_recv(Config, #iq{type = set, + sub_els = [#block{items = JIDs}]}) of + #iq{type = result, sub_els = []} -> + {#iq{id = I1, sub_els = [#block{items = Items}]}, + #iq{id = I2, sub_els = [#privacy_query{lists = Lists}]}} = + ?recv2(#iq{type = set, sub_els = [#block{}]}, + #iq{type = set, sub_els = [#privacy_query{}]}), + send(Config, #iq{type = result, id = I1}), + send(Config, #iq{type = result, id = I2}), + ct:comment("Checking if all JIDs present in the push"), + true = lists:sort(JIDs) == lists:sort(Items), + ct:comment("Getting name of the corresponding privacy list"), + [#privacy_list{name = Name}] = Lists, + {ok, Name}; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +set_unblock(Config, JIDs) -> + ct:comment("Unblocking ~p", [JIDs]), + case send_recv(Config, #iq{type = set, + sub_els = [#unblock{items = JIDs}]}) of + #iq{type = result, sub_els = []} -> + {#iq{id = I1, sub_els = [#unblock{items = Items}]}, + #iq{id = I2, sub_els = [#privacy_query{lists = Lists}]}} = + ?recv2(#iq{type = set, sub_els = [#unblock{}]}, + #iq{type = set, sub_els = [#privacy_query{}]}), + send(Config, #iq{type = result, id = I1}), + send(Config, #iq{type = result, id = I2}), + ct:comment("Checking if all JIDs present in the push"), + true = lists:sort(JIDs) == lists:sort(Items), + ct:comment("Getting name of the corresponding privacy list"), + [#privacy_list{name = Name}] = Lists, + {ok, Name}; + #iq{type = error} = Err -> + xmpp:get_error(Err) + end. + +del_privacy(Config) -> + {U, S, _} = jid:tolower(my_jid(Config)), + ct:comment("Removing all privacy data"), + mod_privacy:remove_user(U, S), + Config. + +clean_up(Config) -> + del_privacy(del_roster(Config)). + +check_iq_blocked(Config, Reason) -> + PeerJID = ?config(peer, Config), + ct:comment("Checking if all IQs are blocked"), + lists:foreach( + fun(Type) -> + send(Config, #iq{type = Type, to = PeerJID}) + end, [error, result]), + lists:foreach( + fun(Type) -> + #iq{type = error} = Err = + send_recv(Config, #iq{type = Type, to = PeerJID, + sub_els = [#ping{}]}), + #stanza_error{reason = Reason} = xmpp:get_error(Err) + end, [set, get]). + +check_message_blocked(Config, Reason) -> + PeerJID = ?config(peer, Config), + ct:comment("Checking if all messages are blocked"), + %% TODO: do something with headline and groupchat. + %% The hack from 64d96778b452aad72349b21d2ac94e744617b07a + %% screws this up. + lists:foreach( + fun(Type) -> + send(Config, #message{type = Type, to = PeerJID}) + end, [error]), + lists:foreach( + fun(Type) -> + #message{type = error} = Err = + send_recv(Config, #message{type = Type, to = PeerJID}), + #stanza_error{reason = Reason} = xmpp:get_error(Err) + end, [chat, normal]). + +check_presence_blocked(Config, Reason) -> + PeerJID = ?config(peer, Config), + ct:comment("Checking if all presences are blocked"), + lists:foreach( + fun(Type) -> + #presence{type = error} = Err = + send_recv(Config, #presence{type = Type, to = PeerJID}), + #stanza_error{reason = Reason} = xmpp:get_error(Err) + end, [available, unavailable]). + +check_other_blocked(Config, Reason) -> + PeerJID = ?config(peer, Config), + ct:comment("Checking if subscriptions and presence-errors are blocked"), + send(Config, #presence{type = error, to = PeerJID}), + lists:foreach( + fun(Type) -> + #presence{type = error} = Err = + send_recv(Config, #presence{type = Type, to = PeerJID}), + #stanza_error{reason = Reason} = xmpp:get_error(Err) + end, [subscribe, subscribed, unsubscribe, unsubscribed]). + +send_presences(Config) -> + PeerJID = ?config(peer, Config), + ct:comment("Sending all types of presences to the peer"), + lists:foreach( + fun(Type) -> + send(Config, #presence{type = Type, to = PeerJID}) + end, [available, unavailable]). + +send_iqs(Config) -> + PeerJID = ?config(peer, Config), + ct:comment("Sending all types of IQs to the peer"), + lists:foreach( + fun(Type) -> + send(Config, #iq{type = Type, to = PeerJID}) + end, [set, get, error, result]). + +send_messages(Config) -> + PeerJID = ?config(peer, Config), + ct:comment("Sending all types of messages to the peer"), + lists:foreach( + fun(Type) -> + send(Config, #message{type = Type, to = PeerJID}) + end, [chat, error, groupchat, headline, normal]). + +recv_presences(Config) -> + PeerJID = ?config(peer, Config), + lists:foreach( + fun(Type) -> + #presence{type = Type, from = PeerJID} = + recv_presence(Config) + end, [available, unavailable]). + +recv_iqs(Config) -> + PeerJID = ?config(peer, Config), + lists:foreach( + fun(Type) -> + #iq{type = Type, from = PeerJID} = recv_iq(Config) + end, [set, get, error, result]). + +recv_messages(Config) -> + PeerJID = ?config(peer, Config), + lists:foreach( + fun(Type) -> + #message{type = Type, from = PeerJID} = recv_message(Config) + end, [chat, error, groupchat, headline, normal]). + +match_all(Opts) -> + IQ = proplists:get_bool(iq, Opts), + Message = proplists:get_bool(message, Opts), + PresenceIn = proplists:get_bool(presence_in, Opts), + PresenceOut = proplists:get_bool(presence_out, Opts), + not (IQ or Message or PresenceIn or PresenceOut). + +is_message_in_blocked(Opts) -> + proplists:get_bool(message, Opts) or match_all(Opts). + +is_message_out_blocked(Opts) -> + match_all(Opts). + +is_iq_in_blocked(Opts) -> + proplists:get_bool(iq, Opts) or match_all(Opts). + +is_iq_out_blocked(Opts) -> + match_all(Opts). + +is_presence_in_blocked(Opts) -> + proplists:get_bool(presence_in, Opts) or match_all(Opts). + +is_presence_out_blocked(Opts) -> + proplists:get_bool(presence_out, Opts) or match_all(Opts). + +is_other_blocked(Opts) -> + %% 'other' means subscriptions and presence-errors + match_all(Opts). + +server_send_iqs(Config) -> + ServerJID = server_jid(Config), + MyJID = my_jid(Config), + ct:comment("Sending IQs from ~s to ~s", + [jid:to_string(ServerJID), jid:to_string(MyJID)]), + lists:foreach( + fun(Type) -> + ejabberd_router:route( + ServerJID, MyJID, #iq{type = Type}) + end, [error, result]), + lists:foreach( + fun(Type) -> + ejabberd_local:route_iq( + ServerJID, MyJID, #iq{type = Type}, + fun(#iq{type = result, sub_els = []}) -> ok; + (IQ) -> ct:fail({unexpected_iq_result, IQ}) + end) + end, [set, get]). + +server_recv_iqs(Config) -> + ServerJID = server_jid(Config), + ct:comment("Receiving IQs from ~s", [jid:to_string(ServerJID)]), + lists:foreach( + fun(Type) -> + #iq{type = Type, from = ServerJID} = recv_iq(Config) + end, [error, result]), + lists:foreach( + fun(Type) -> + #iq{type = Type, from = ServerJID, id = I} = recv_iq(Config), + send(Config, #iq{to = ServerJID, type = result, id = I}) + end, [set, get]). + +send_stanzas_to_server_resource(Config) -> + ServerJID = server_jid(Config), + ServerJIDResource = jid:replace_resource(ServerJID, <<"resource">>), + %% All stanzas sent should be handled by local_send_to_resource_hook + %% and should be bounced with item-not-found error + ct:comment("Sending IQs to ~s", [jid:to_string(ServerJIDResource)]), + lists:foreach( + fun(Type) -> + #iq{type = error} = Err = + send_recv(Config, #iq{type = Type, to = ServerJIDResource}), + #stanza_error{reason = 'item-not-found'} = xmpp:get_error(Err) + end, [set, get]), + ct:comment("Sending messages to ~s", [jid:to_string(ServerJIDResource)]), + lists:foreach( + fun(Type) -> + #message{type = error} = Err = + send_recv(Config, #message{type = Type, to = ServerJIDResource}), + #stanza_error{reason = 'item-not-found'} = xmpp:get_error(Err) + end, [normal, chat, groupchat, headline]), + ct:comment("Sending presences to ~s", [jid:to_string(ServerJIDResource)]), + lists:foreach( + fun(Type) -> + #presence{type = error} = Err = + send_recv(Config, #presence{type = Type, to = ServerJIDResource}), + #stanza_error{reason = 'item-not-found'} = xmpp:get_error(Err) + end, [available, unavailable]). |