24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-20 22:22:09 +02:00
xmpp.chapril.org-ejabberd/test/ejabberd_SUITE.erl

1001 lines
38 KiB
Erlang
Raw Normal View History

%%%-------------------------------------------------------------------
%%% @author Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2013, Evgeniy Khramtsov
%%% @doc
%%%
%%% @end
%%% Created : 2 Jun 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%-------------------------------------------------------------------
-module(ejabberd_SUITE).
-compile(export_all).
2013-06-26 19:55:29 +02:00
-import(suite, [init_config/1, connect/1, disconnect/1,
recv/0, send/2, send_recv/2, my_jid/1, server_jid/1,
pubsub_jid/1, proxy_jid/1, muc_jid/1,
muc_room_jid/1, get_features/2, re_register/1,
is_feature_advertised/2, subscribe_to_events/1,
is_feature_advertised/3, set_opt/3, auth_SASL/2,
wait_for_master/1, wait_for_slave/1,
make_iq_result/1, start_event_relay/0,
stop_event_relay/1, put_event/2, get_event/1,
bind/1, auth/1, open_session/1, zlib/1, starttls/1]).
-include("suite.hrl").
suite() ->
2013-07-15 03:36:12 +02:00
[{timetrap, {seconds,20}}].
init_per_suite(Config) ->
2013-06-26 19:55:29 +02:00
NewConfig = init_config(Config),
DataDir = proplists:get_value(data_dir, NewConfig),
{ok, CWD} = file:get_cwd(),
2013-06-26 19:55:29 +02:00
ExtAuthScript = filename:join([DataDir, "extauth.py"]),
LDIFFile = filename:join([DataDir, "ejabberd.ldif"]),
2013-06-26 04:29:50 +02:00
{ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])),
{ok, _} = ldap_srv:start(LDIFFile),
ok = application:start(ejabberd),
2013-06-26 19:55:29 +02:00
NewConfig.
end_per_suite(_Config) ->
ok.
init_per_group(no_db, Config) ->
2013-06-26 19:55:29 +02:00
re_register(Config),
Config;
init_per_group(mnesia, Config) ->
mod_muc:shutdown_rooms(?MNESIA_VHOST),
set_opt(server, ?MNESIA_VHOST, Config);
init_per_group(mysql, Config) ->
case catch ejabberd_odbc:sql_query(?MYSQL_VHOST, [<<"select 1;">>]) of
{selected, _, _} ->
mod_muc:shutdown_rooms(?MYSQL_VHOST),
create_sql_tables(mysql, ?config(base_dir, Config)),
set_opt(server, ?MYSQL_VHOST, Config);
Err ->
{skip, {mysql_not_available, Err}}
end;
init_per_group(pgsql, Config) ->
case catch ejabberd_odbc:sql_query(?PGSQL_VHOST, [<<"select 1;">>]) of
{selected, _, _} ->
mod_muc:shutdown_rooms(?PGSQL_VHOST),
create_sql_tables(pgsql, ?config(base_dir, Config)),
set_opt(server, ?PGSQL_VHOST, Config);
Err ->
{skip, {pgsql_not_available, Err}}
end;
2013-06-21 19:23:56 +02:00
init_per_group(ldap, Config) ->
set_opt(server, ?LDAP_VHOST, Config);
2013-06-26 04:29:50 +02:00
init_per_group(extauth, Config) ->
set_opt(server, ?EXTAUTH_VHOST, Config);
2013-06-15 15:28:14 +02:00
init_per_group(_GroupName, Config) ->
Pid = start_event_relay(),
set_opt(event_relay, Pid, Config).
end_per_group(mnesia, _Config) ->
ok;
end_per_group(mysql, _Config) ->
ok;
end_per_group(pgsql, _Config) ->
ok;
end_per_group(no_db, _Config) ->
ok;
2013-06-21 19:23:56 +02:00
end_per_group(ldap, _Config) ->
ok;
2013-06-26 04:29:50 +02:00
end_per_group(extauth, _Config) ->
ok;
2013-06-15 15:28:14 +02:00
end_per_group(_GroupName, Config) ->
stop_event_relay(Config),
ok.
init_per_testcase(stop_ejabberd, Config) ->
2013-06-15 15:28:14 +02:00
open_session(bind(auth(connect(Config))));
init_per_testcase(TestCase, OrigConfig) ->
2013-06-15 15:28:14 +02:00
subscribe_to_events(OrigConfig),
2013-06-15 18:45:18 +02:00
Server = ?config(server, OrigConfig),
Resource = ?config(resource, OrigConfig),
2013-06-15 15:28:14 +02:00
Test = atom_to_list(TestCase),
IsMaster = lists:suffix("_master", Test),
IsSlave = lists:suffix("_slave", Test),
User = if IsMaster -> <<"test_master">>;
IsSlave -> <<"test_slave">>;
true -> <<"test_single">>
end,
2013-06-15 18:45:18 +02:00
Slave = jlib:make_jid(<<"test_slave">>, Server, Resource),
Master = jlib:make_jid(<<"test_master">>, Server, Resource),
Config = set_opt(user, User,
set_opt(slave, Slave,
set_opt(master, Master, OrigConfig))),
case TestCase of
test_connect ->
Config;
test_auth ->
connect(Config);
2013-06-14 16:16:32 +02:00
test_starttls ->
connect(Config);
2013-06-14 16:45:04 +02:00
test_zlib ->
connect(Config);
2013-06-14 16:16:32 +02:00
test_register ->
2013-06-14 10:47:50 +02:00
connect(Config);
auth_md5 ->
connect(Config);
auth_plain ->
connect(Config);
test_bind ->
auth(connect(Config));
test_open_session ->
bind(auth(connect(Config)));
2013-06-15 15:28:14 +02:00
_ when IsMaster or IsSlave ->
Password = ?config(password, Config),
ejabberd_auth:try_register(User, Server, Password),
open_session(bind(auth(connect(Config))));
_ ->
open_session(bind(auth(connect(Config))))
end.
end_per_testcase(_TestCase, _Config) ->
ok.
2013-06-21 19:23:56 +02:00
no_db_tests() ->
[{generic, [sequence],
[test_connect,
test_starttls,
test_zlib,
test_auth,
test_bind,
test_open_session,
presence,
ping,
version,
time,
stats,
disco]},
{test_proxy65, [parallel],
[proxy65_master, proxy65_slave]}].
2013-06-21 19:23:56 +02:00
db_tests() ->
[{single_user, [sequence],
[test_register,
auth_plain,
auth_md5,
presence_broadcast,
last,
roster_get,
private,
privacy,
blocking,
vcard,
2013-06-16 20:00:19 +02:00
muc_single,
pubsub,
2013-06-15 15:28:14 +02:00
test_unregister]},
2013-06-16 20:00:19 +02:00
{test_roster_subscribe, [parallel],
[roster_subscribe_master,
roster_subscribe_slave]},
2013-06-17 09:15:27 +02:00
{test_offline, [sequence],
[offline_master, offline_slave]},
2013-06-16 20:00:19 +02:00
{test_roster_remove, [parallel],
[roster_remove_master,
roster_remove_slave]}].
2013-06-21 19:23:56 +02:00
ldap_tests() ->
[{ldap_tests, [sequence],
[test_auth,
vcard_get]}].
2013-06-26 04:29:50 +02:00
extauth_tests() ->
[{extauth_tests, [sequence],
[test_auth,
test_unregister]}].
groups() ->
2013-06-21 19:23:56 +02:00
[{ldap, [sequence], ldap_tests()},
2013-06-26 04:29:50 +02:00
{extauth, [sequence], extauth_tests()},
2013-06-21 19:23:56 +02:00
{no_db, [sequence], no_db_tests()},
{mnesia, [sequence], db_tests()},
{mysql, [sequence], db_tests()},
{pgsql, [sequence], db_tests()}].
all() ->
2013-06-21 19:23:56 +02:00
[{group, ldap},
{group, no_db},
{group, mnesia},
{group, mysql},
{group, pgsql},
2013-06-26 04:29:50 +02:00
{group, extauth},
2013-06-15 18:45:18 +02:00
stop_ejabberd].
stop_ejabberd(Config) ->
ok = application:stop(ejabberd),
#stream_error{reason = 'system-shutdown'} = recv(),
{xmlstreamend, <<"stream:stream">>} = recv(),
Config.
test_connect(Config) ->
disconnect(connect(Config)).
2013-06-14 16:16:32 +02:00
test_starttls(Config) ->
case ?config(starttls, Config) of
true ->
disconnect(starttls(Config));
2013-06-14 16:16:32 +02:00
_ ->
{skipped, 'starttls_not_available'}
end.
2013-06-14 16:45:04 +02:00
test_zlib(Config) ->
case ?config(compression, Config) of
[_|_] = Ms ->
case lists:member(<<"zlib">>, Ms) of
true ->
disconnect(zlib(Config));
2013-06-14 16:45:04 +02:00
false ->
{skipped, 'zlib_not_available'}
end;
_ ->
{skipped, 'compression_not_available'}
end.
2013-06-14 16:16:32 +02:00
test_register(Config) ->
2013-06-14 10:47:50 +02:00
case ?config(register, Config) of
true ->
disconnect(register(Config));
2013-06-14 16:16:32 +02:00
_ ->
{skipped, 'registration_not_available'}
2013-06-14 10:47:50 +02:00
end.
2013-06-14 16:16:32 +02:00
register(Config) ->
2013-06-16 20:00:19 +02:00
#iq{type = result,
2013-06-14 10:47:50 +02:00
sub_els = [#register{username = none,
2013-06-16 20:00:19 +02:00
password = none}]} =
send_recv(Config, #iq{type = get, to = server_jid(Config),
sub_els = [#register{}]}),
#iq{type = result, sub_els = []} =
send_recv(
Config,
#iq{type = set,
sub_els = [#register{username = ?config(user, Config),
password = ?config(password, Config)}]}),
Config.
2013-06-14 10:47:50 +02:00
2013-06-14 18:58:26 +02:00
test_unregister(Config) ->
case ?config(register, Config) of
true ->
2013-06-14 19:22:36 +02:00
try_unregister(Config);
2013-06-14 18:58:26 +02:00
_ ->
{skipped, 'registration_not_available'}
end.
try_unregister(Config) ->
2013-06-14 19:22:36 +02:00
true = is_feature_advertised(Config, ?NS_REGISTER),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = []} =
send_recv(
Config,
#iq{type = set,
sub_els = [#register{remove = true}]}),
2013-06-14 19:22:36 +02:00
#stream_error{reason = conflict} = recv(),
2013-06-14 18:58:26 +02:00
Config.
2013-06-26 19:55:29 +02:00
auth_md5(Config) ->
Mechs = ?config(mechs, Config),
case lists:member(<<"DIGEST-MD5">>, Mechs) of
true ->
disconnect(auth_SASL(<<"DIGEST-MD5">>, Config));
false ->
disconnect(Config),
{skipped, 'DIGEST-MD5_not_available'}
end.
2013-06-26 19:55:29 +02:00
auth_plain(Config) ->
Mechs = ?config(mechs, Config),
2013-06-26 19:55:29 +02:00
case lists:member(<<"PLAIN">>, Mechs) of
true ->
disconnect(auth_SASL(<<"PLAIN">>, Config));
false ->
disconnect(Config),
{skipped, 'PLAIN_not_available'}
end.
2013-06-26 19:55:29 +02:00
test_auth(Config) ->
disconnect(auth(Config)).
test_bind(Config) ->
disconnect(bind(Config)).
test_open_session(Config) ->
disconnect(open_session(Config)).
roster_get(Config) ->
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#roster{items = []}]} =
send_recv(Config, #iq{type = get, sub_els = [#roster{}]}),
disconnect(Config).
presence(Config) ->
send(Config, #presence{}),
JID = my_jid(Config),
#presence{from = JID, to = JID} = recv(),
disconnect(Config).
presence_broadcast(Config) ->
send(Config, #presence{}),
JID = my_jid(Config),
2013-06-16 20:00:19 +02:00
%% We receive the welcome message and the presence broadcast
?recv2(#message{type = normal},
#presence{from = JID, to = JID}),
disconnect(Config).
ping(Config) ->
true = is_feature_advertised(Config, ?NS_PING),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = []} =
send_recv(
Config,
#iq{type = get, sub_els = [#ping{}], to = server_jid(Config)}),
disconnect(Config).
version(Config) ->
true = is_feature_advertised(Config, ?NS_VERSION),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#version{}]} =
send_recv(
Config, #iq{type = get, sub_els = [#version{}],
to = server_jid(Config)}),
disconnect(Config).
time(Config) ->
true = is_feature_advertised(Config, ?NS_TIME),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#time{}]} =
send_recv(Config, #iq{type = get, sub_els = [#time{}],
to = server_jid(Config)}),
disconnect(Config).
disco(Config) ->
true = is_feature_advertised(Config, ?NS_DISCO_INFO),
true = is_feature_advertised(Config, ?NS_DISCO_ITEMS),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#disco_items{items = Items}]} =
send_recv(
Config, #iq{type = get, sub_els = [#disco_items{}],
to = server_jid(Config)}),
lists:foreach(
fun(#disco_item{jid = JID, node = Node}) ->
2013-06-16 20:00:19 +02:00
#iq{type = result} =
send_recv(Config,
#iq{type = get, to = JID,
sub_els = [#disco_info{node = Node}]})
end, Items),
disconnect(Config).
private(Config) ->
Conference = #bookmark_conference{name = <<"Some name">>,
autojoin = true,
jid = jlib:make_jid(
<<"some">>,
<<"some.conference.org">>,
<<>>)},
Storage = #bookmark_storage{conference = [Conference]},
StorageXMLOut = xmpp_codec:encode(Storage),
2013-06-16 20:00:19 +02:00
#iq{type = error} =
send_recv(Config, #iq{type = get, sub_els = [#private{}],
to = server_jid(Config)}),
#iq{type = result, sub_els = []} =
send_recv(
Config, #iq{type = set,
sub_els = [#private{xml_els = [StorageXMLOut]}]}),
2013-06-16 20:00:19 +02:00
#iq{type = result,
sub_els = [#private{xml_els = [StorageXMLIn]}]} =
2013-06-16 20:00:19 +02:00
send_recv(
Config,
#iq{type = get,
sub_els = [#private{xml_els = [xmpp_codec:encode(
#bookmark_storage{})]}]}),
Storage = xmpp_codec:decode(StorageXMLIn),
disconnect(Config).
last(Config) ->
true = is_feature_advertised(Config, ?NS_LAST),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#last{}]} =
send_recv(Config, #iq{type = get, sub_els = [#last{}],
to = server_jid(Config)}),
disconnect(Config).
privacy(Config) ->
true = is_feature_advertised(Config, ?NS_PRIVACY),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#privacy{}]} =
send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}),
JID = <<"tybalt@example.com">>,
2013-06-16 20:00:19 +02:00
I1 = send(Config,
#iq{type = set,
sub_els = [#privacy{
lists = [#privacy_list{
name = <<"public">>,
items =
[#privacy_item{
type = jid,
order = 3,
action = deny,
2013-06-16 20:00:19 +02:00
kinds = ['presence-in'],
value = JID}]}]}]}),
2013-06-16 20:00:19 +02:00
{Push1, _} =
?recv2(
#iq{type = set,
sub_els = [#privacy{
lists = [#privacy_list{
name = <<"public">>}]}]},
#iq{type = result, id = I1, sub_els = []}),
2013-06-15 15:28:14 +02:00
send(Config, make_iq_result(Push1)),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set,
sub_els = [#privacy{active = <<"public">>}]}),
#iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set,
sub_els = [#privacy{default = <<"public">>}]}),
#iq{type = result,
sub_els = [#privacy{default = <<"public">>,
active = <<"public">>,
2013-06-16 20:00:19 +02:00
lists = [#privacy_list{name = <<"public">>}]}]} =
send_recv(Config, #iq{type = get, sub_els = [#privacy{}]}),
#iq{type = result, sub_els = []} =
send_recv(Config,
#iq{type = set, sub_els = [#privacy{default = none}]}),
#iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, sub_els = [#privacy{active = none}]}),
I2 = send(Config, #iq{type = set,
sub_els = [#privacy{
lists =
[#privacy_list{
name = <<"public">>}]}]}),
2013-06-16 20:00:19 +02:00
{Push2, _} =
?recv2(
#iq{type = set,
sub_els = [#privacy{
lists = [#privacy_list{
name = <<"public">>}]}]},
#iq{type = result, id = I2, sub_els = []}),
2013-06-15 15:28:14 +02:00
send(Config, make_iq_result(Push2)),
disconnect(Config).
blocking(Config) ->
true = is_feature_advertised(Config, ?NS_BLOCKING),
JID = jlib:make_jid(<<"romeo">>, <<"montague.net">>, <<>>),
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#block_list{}]} =
send_recv(Config, #iq{type = get, sub_els = [#block_list{}]}),
I1 = send(Config, #iq{type = set,
sub_els = [#block{items = [JID]}]}),
2013-06-16 20:00:19 +02:00
{Push1, Push2, _} =
?recv3(
#iq{type = set,
sub_els = [#privacy{lists = [#privacy_list{}]}]},
#iq{type = set,
sub_els = [#block{items = [JID]}]},
#iq{type = result, id = I1, sub_els = []}),
send(Config, make_iq_result(Push1)),
send(Config, make_iq_result(Push2)),
I2 = send(Config, #iq{type = set,
sub_els = [#unblock{items = [JID]}]}),
2013-06-16 20:00:19 +02:00
{Push3, Push4, _} =
?recv3(
#iq{type = set,
sub_els = [#privacy{lists = [#privacy_list{}]}]},
#iq{type = set,
sub_els = [#unblock{items = [JID]}]},
#iq{type = result, id = I2, sub_els = []}),
send(Config, make_iq_result(Push3)),
send(Config, make_iq_result(Push4)),
disconnect(Config).
vcard(Config) ->
true = is_feature_advertised(Config, ?NS_VCARD),
VCard =
#vcard{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/">>},
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = []} =
send_recv(Config, #iq{type = set, sub_els = [VCard]}),
%% TODO: check if VCard == VCard1.
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [_VCard1]} =
send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}),
disconnect(Config).
2013-06-21 19:23:56 +02:00
vcard_get(Config) ->
true = is_feature_advertised(Config, ?NS_VCARD),
%% TODO: check if VCard corresponds to LDIF data from ejabberd.ldif
#iq{type = result, sub_els = [_VCard]} =
send_recv(Config, #iq{type = get, sub_els = [#vcard{}]}),
disconnect(Config).
stats(Config) ->
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [#stats{stat = Stats}]} =
send_recv(Config, #iq{type = get, sub_els = [#stats{}],
to = server_jid(Config)}),
lists:foreach(
2013-06-15 15:28:14 +02:00
fun(#stat{} = Stat) ->
2013-06-16 20:00:19 +02:00
#iq{type = result, sub_els = [_|_]} =
send_recv(Config, #iq{type = get,
sub_els = [#stats{stat = [Stat]}],
to = server_jid(Config)})
end, Stats),
disconnect(Config).
pubsub(Config) ->
2013-06-25 19:32:08 +02:00
Features = get_features(Config, pubsub_jid(Config)),
true = lists:member(?NS_PUBSUB, Features),
%% Publish <presence/> element within node "presence"
ItemID = randoms:get_string(),
Node = <<"presence">>,
Item = #pubsub_item{id = ItemID,
xml_els = [xmpp_codec:encode(#presence{})]},
2013-06-16 20:00:19 +02:00
#iq{type = result,
2013-06-25 19:00:27 +02:00
sub_els = [#pubsub{publish = #pubsub_publish{
node = Node,
items = [#pubsub_item{id = ItemID}]}}]} =
2013-06-16 20:00:19 +02:00
send_recv(Config,
#iq{type = set, to = pubsub_jid(Config),
2013-06-25 19:00:27 +02:00
sub_els = [#pubsub{publish = #pubsub_publish{
node = Node,
items = [Item]}}]}),
%% Subscribe to node "presence"
2013-06-25 19:00:27 +02:00
I1 = send(Config,
2013-06-16 20:00:19 +02:00
#iq{type = set, to = pubsub_jid(Config),
2013-06-25 19:00:27 +02:00
sub_els = [#pubsub{subscribe = #pubsub_subscribe{
node = Node,
jid = my_jid(Config)}}]}),
2013-06-16 20:00:19 +02:00
?recv2(
#message{sub_els = [#pubsub_event{}, #delay{}]},
2013-06-25 19:00:27 +02:00
#iq{type = result, id = I1}),
%% Get subscriptions
2013-06-25 19:32:08 +02:00
true = lists:member(?PUBSUB("retrieve-subscriptions"), Features),
2013-06-16 20:00:19 +02:00
#iq{type = result,
sub_els =
[#pubsub{subscriptions =
2013-06-16 20:00:19 +02:00
{none, [#pubsub_subscription{node = Node}]}}]} =
send_recv(Config, #iq{type = get, to = pubsub_jid(Config),
sub_els = [#pubsub{subscriptions = {none, []}}]}),
%% Get affiliations
2013-06-25 19:32:08 +02:00
true = lists:member(?PUBSUB("retrieve-affiliations"), Features),
2013-06-16 20:00:19 +02:00
#iq{type = result,
sub_els = [#pubsub{
affiliations =
2013-06-16 20:00:19 +02:00
[#pubsub_affiliation{node = Node, type = owner}]}]} =
send_recv(Config, #iq{type = get, to = pubsub_jid(Config),
sub_els = [#pubsub{affiliations = []}]}),
2013-06-25 19:00:27 +02:00
%% Get subscription options
2013-06-25 19:32:08 +02:00
true = lists:member(?PUBSUB("subscription-options"), Features),
2013-06-25 19:00:27 +02:00
#iq{type = result, sub_els = [#pubsub{options = #pubsub_options{
node = Node}}]} =
send_recv(Config,
#iq{type = get, to = pubsub_jid(Config),
sub_els = [#pubsub{options = #pubsub_options{
node = Node,
jid = my_jid(Config)}}]}),
%% Fetching published items from node "presence"
#iq{type = result,
sub_els = [#pubsub{items = #pubsub_items{
node = Node,
items = [Item]}}]} =
send_recv(Config,
#iq{type = get, to = pubsub_jid(Config),
sub_els = [#pubsub{items = #pubsub_items{node = Node}}]}),
%% Deleting the item from the node
2013-06-25 19:32:08 +02:00
true = lists:member(?PUBSUB("delete-items"), Features),
2013-06-25 19:00:27 +02:00
I2 = send(Config,
#iq{type = set, to = pubsub_jid(Config),
sub_els = [#pubsub{retract = #pubsub_retract{
node = Node,
items = [#pubsub_item{id = ItemID}]}}]}),
?recv2(
#iq{type = result, id = I2, sub_els = []},
#message{sub_els = [#pubsub_event{
items = [#pubsub_event_items{
node = Node,
retract = [ItemID]}]},
#shim{headers = [{<<"Collection">>, Node}]}]}),
%% Unsubscribe from node "presence"
#iq{type = result, sub_els = []} =
send_recv(Config,
#iq{type = set, to = pubsub_jid(Config),
sub_els = [#pubsub{unsubscribe = #pubsub_unsubscribe{
node = Node,
jid = my_jid(Config)}}]}),
disconnect(Config).
2013-06-16 20:00:19 +02:00
roster_subscribe_master(Config) ->
2013-06-15 15:28:14 +02:00
send(Config, #presence{}),
#presence{} = recv(),
wait_for_slave(Config),
2013-06-15 18:45:18 +02:00
Peer = ?config(slave, Config),
2013-06-15 15:28:14 +02:00
LPeer = jlib:jid_remove_resource(Peer),
send(Config, #presence{type = subscribe, to = LPeer}),
Push1 = #iq{type = set,
sub_els = [#roster{items = [#roster_item{
ask = subscribe,
subscription = none,
jid = LPeer}]}]} = recv(),
send(Config, make_iq_result(Push1)),
{Push2, _} = ?recv2(
#iq{type = set,
sub_els = [#roster{items = [#roster_item{
subscription = to,
jid = LPeer}]}]},
#presence{type = subscribed, from = LPeer}),
send(Config, make_iq_result(Push2)),
#presence{type = undefined, from = Peer} = recv(),
%% BUG: ejabberd sends previous push again. Is it ok?
Push3 = #iq{type = set,
sub_els = [#roster{items = [#roster_item{
subscription = to,
jid = LPeer}]}]} = recv(),
send(Config, make_iq_result(Push3)),
#presence{type = subscribe, from = LPeer} = recv(),
send(Config, #presence{type = subscribed, to = LPeer}),
Push4 = #iq{type = set,
sub_els = [#roster{items = [#roster_item{
subscription = both,
jid = LPeer}]}]} = recv(),
send(Config, make_iq_result(Push4)),
%% Move into a group
Groups = [<<"A">>, <<"B">>],
Item = #roster_item{jid = LPeer, groups = Groups},
I1 = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}),
{Push5, _} = ?recv2(
#iq{type = set,
sub_els =
[#roster{items = [#roster_item{
jid = LPeer,
subscription = both}]}]},
#iq{type = result, id = I1, sub_els = []}),
send(Config, make_iq_result(Push5)),
2013-06-16 20:00:19 +02:00
#iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push5,
Groups = lists:sort(G1),
2013-06-15 15:28:14 +02:00
wait_for_slave(Config),
2013-06-15 18:45:18 +02:00
#presence{type = unavailable, from = Peer} = recv(),
2013-06-15 15:28:14 +02:00
disconnect(Config).
2013-06-16 20:00:19 +02:00
roster_subscribe_slave(Config) ->
2013-06-15 15:28:14 +02:00
send(Config, #presence{}),
#presence{} = recv(),
wait_for_master(Config),
2013-06-15 18:45:18 +02:00
Peer = ?config(master, Config),
2013-06-15 15:28:14 +02:00
LPeer = jlib:jid_remove_resource(Peer),
#presence{type = subscribe, from = LPeer} = recv(),
send(Config, #presence{type = subscribed, to = LPeer}),
Push1 = #iq{type = set,
sub_els = [#roster{items = [#roster_item{
subscription = from,
jid = LPeer}]}]} = recv(),
send(Config, make_iq_result(Push1)),
send(Config, #presence{type = subscribe, to = LPeer}),
Push2 = #iq{type = set,
sub_els = [#roster{items = [#roster_item{
ask = subscribe,
subscription = from,
jid = LPeer}]}]} = recv(),
send(Config, make_iq_result(Push2)),
{Push3, _} = ?recv2(
#iq{type = set,
sub_els = [#roster{items = [#roster_item{
subscription = both,
jid = LPeer}]}]},
#presence{type = subscribed, from = LPeer}),
send(Config, make_iq_result(Push3)),
#presence{type = undefined, from = Peer} = recv(),
wait_for_master(Config),
2013-06-16 20:00:19 +02:00
disconnect(Config).
roster_remove_master(Config) ->
MyJID = my_jid(Config),
Peer = ?config(slave, Config),
LPeer = jlib:jid_remove_resource(Peer),
Groups = [<<"A">>, <<"B">>],
wait_for_slave(Config),
send(Config, #presence{}),
?recv2(#presence{from = MyJID, type = undefined},
#presence{from = Peer, type = undefined}),
%% The peer removed us from its roster.
{Push1, Push2, _, _, _} =
?recv5(
%% TODO: I guess this can be optimized, we don't need
%% to send transient roster push with subscription = 'to'.
#iq{type = set,
sub_els =
[#roster{items = [#roster_item{
jid = LPeer,
subscription = to}]}]},
#iq{type = set,
sub_els =
[#roster{items = [#roster_item{
jid = LPeer,
subscription = none}]}]},
#presence{type = unsubscribe, from = LPeer},
#presence{type = unsubscribed, from = LPeer},
#presence{type = unavailable, from = Peer}),
send(Config, make_iq_result(Push1)),
send(Config, make_iq_result(Push2)),
#iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push1,
#iq{sub_els = [#roster{items = [#roster_item{groups = G2}]}]} = Push2,
Groups = lists:sort(G1), Groups = lists:sort(G2),
disconnect(Config).
roster_remove_slave(Config) ->
MyJID = my_jid(Config),
Peer = ?config(master, Config),
LPeer = jlib:jid_remove_resource(Peer),
send(Config, #presence{}),