1: %%%-------------------------------------------------------------------
    2: %%% @author bartek
    3: %%% @copyright (C) 2017, <COMPANY>
    4: %%% @doc
    5: %%%
    6: %%% @end
    7: %%% Created : 21. Apr 2017 16:09
    8: %%%-------------------------------------------------------------------
    9: -module(roster_SUITE).
   10: -author("bartek").
   11: 
   12: -include_lib("eunit/include/eunit.hrl").
   13: -include("mongoose.hrl").
   14: -include_lib("exml/include/exml_stream.hrl").
   15: -include_lib("mod_roster.hrl").
   16: -compile([export_all, nowarn_export_all]).
   17: 
   18: -define(ACC_PARAMS, #{location => ?LOCATION,
   19:                       lserver => domain(),
   20:                       host_type => host_type(),
   21:                       element => undefined}).
   22: 
   23: all() -> [
   24:     roster_old,
   25:     roster_old_with_filter,
   26:     roster_new,
   27:     roster_case_insensitive
   28: ].
   29: 
   30: init_per_suite(C) ->
   31:     ok = mnesia:create_schema([node()]),
   32:     ok = mnesia:start(),
   33:     {ok, _} = application:ensure_all_started(jid),
   34:     {ok, _} = application:ensure_all_started(exometer_core),
   35:     meck:new(gen_iq_handler, [no_link]),
   36:     meck:expect(gen_iq_handler, add_iq_handler_for_domain, fun(_, _, _, _, _, _) -> ok end),
   37:     meck:expect(gen_iq_handler, remove_iq_handler_for_domain, fun(_, _, _) -> ok end),
   38:     meck:new(mongoose_domain_api, [no_link]),
   39:     meck:expect(mongoose_domain_api, get_domain_host_type, fun(_) -> {ok, host_type()} end),
   40:     mongoose_config:set_opts(opts()),
   41:     C.
   42: 
   43: end_per_suite(_C) ->
   44:     mongoose_config:erase_opts(),
   45:     meck:unload(),
   46:     mnesia:stop(),
   47:     mnesia:delete_schema([node()]).
   48: 
   49: init_per_testcase(_TC, C) ->
   50:     init_ets(),
   51:     mongooseim_helper:start_link_loaded_hooks(),
   52:     mongoose_modules:start(),
   53:     C.
   54: 
   55: end_per_testcase(_TC, C) ->
   56:     Acc = mongoose_acc:new(?ACC_PARAMS),
   57:     JID = jid:make_bare(a(), domain()),
   58:     mod_roster:remove_user(Acc, #{jid => JID}, #{host_type => mongoose_acc:host_type(Acc)}),
   59:     mongoose_modules:stop(),
   60:     delete_ets(),
   61:     C.
   62: 
   63: opts() ->
   64:     #{hosts => [host_type()],
   65:       host_types => [],
   66:       all_metrics_are_global => false,
   67:       {modules, host_type()} => #{mod_roster => config_parser_helper:default_mod_config(mod_roster)}}.
   68: 
   69: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   70: %%%%%%%%%%%%%%%%%%%%%%%%%%% TESTS %%%%%%%%%%%%%%%%%%%%%%%
   71: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   72: 
   73: 
   74: roster_old(_C) ->
   75:     R1 = get_roster_old(),
   76:     ?assertEqual(length(R1), 0),
   77:     ok = mod_roster:set_items(host_type(), alice_jid(), addbob_stanza()),
   78:     assert_state_old(none, none),
   79:     subscription(out, subscribe),
   80:     assert_state_old(none, out),
   81:     ok.
   82: 
   83: roster_old_with_filter(_C) ->
   84:     R1 = get_roster_old(),
   85:     ?assertEqual(0, length(R1)),
   86:     ok = mod_roster:set_items(host_type(), alice_jid(), addbob_stanza()),
   87:     assert_state_old(none, none),
   88:     subscription(in, subscribe),
   89:     R2 = get_roster_old(),
   90:     ?assertEqual(0, length(R2)),
   91:     R3 = get_full_roster(),
   92:     ?assertEqual(1, length(R3)),
   93:     ok.
   94: 
   95: roster_new(_C) ->
   96:     R1 = mod_roster:get_roster_entry(host_type(), alice_jid(), bob_ljid(), short),
   97:     ?assertEqual(does_not_exist, R1),
   98:     ok = mod_roster:set_items(host_type(), alice_jid(), addbob_stanza()),
   99:     assert_state_old(none, none),
  100:     ct:pal("get_roster_old(): ~p", [get_roster_old()]),
  101:     R2 = mod_roster:get_roster_entry(host_type(), alice_jid(), bob_ljid(), short),
  102:     ?assertMatch(#roster{}, R2), % is not guaranteed to contain full info
  103:     R3 = mod_roster:get_roster_entry(host_type(), alice_jid(), bob_ljid(), full),
  104:     assert_state(R3, none, none, [<<"friends">>]),
  105:     subscription(out, subscribe),
  106:     R4 = mod_roster:get_roster_entry(host_type(), alice_jid(), bob_ljid(), full),
  107:     assert_state(R4, none, out, [<<"friends">>]).
  108: 
  109: 
  110: roster_case_insensitive(_C) ->
  111:     ok = mod_roster:set_items(host_type(), alice_jid(), addbob_stanza()),
  112:     R1 = get_roster_old(),
  113:     ?assertEqual(1, length(R1)),
  114:     R2 = get_roster_old(ae()),
  115:     ?assertEqual(1, length(R2)),
  116:     R3 = mod_roster:get_roster_entry(host_type(), alice_jid(), bob_ljid(), full),
  117:     assert_state(R3, none, none, [<<"friends">>]),
  118:     R3 = mod_roster:get_roster_entry(host_type(), alicE_jid(), bob_ljid(), full),
  119:     assert_state(R3, none, none, [<<"friends">>]),
  120:     ok.
  121: 
  122: 
  123: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  124: %%%%%%%%%%%%%%%%%%%%%%%%%% HELPERS %%%%%%%%%%%%%%%%%%%%%%
  125: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  126: 
  127: assert_state(Rentry, Subscription, Ask, Groups) ->
  128:     ?assertEqual(Subscription, Rentry#roster.subscription),
  129:     ?assertEqual(Ask, Rentry#roster.ask),
  130:     ?assertEqual(Groups, Rentry#roster.groups).
  131: 
  132: subscription(Direction, Type) ->
  133:     TFun = fun() ->
  134:                    mod_roster:process_subscription_t(host_type(), Direction, alice_jid(),
  135:                                                      bob_jid(), Type, <<>>)
  136:            end,
  137:     {atomic, _} = mod_roster:transaction(host_type(), TFun).
  138: 
  139: get_roster_old() ->
  140:     get_roster_old(a()).
  141: 
  142: get_roster_old(User) ->
  143:     Acc = mongoose_acc:new(?ACC_PARAMS),
  144:     Params = #{mongoose_acc => Acc, show_full_roster => false, jid => jid:make_bare(User, domain())},
  145:     Extra = #{host_type => mongoose_acc:host_type(Acc)},
  146:     {ok, Roster} = mod_roster:get_user_roster([], Params, Extra),
  147:     Roster.
  148: 
  149: get_full_roster() ->
  150:     Acc = mongoose_acc:new(?ACC_PARAMS),
  151:     Params = #{mongoose_acc => Acc, show_full_roster => true, jid => alice_jid()},
  152:     Extra = #{host_type => mongoose_acc:host_type(Acc)},
  153:     {ok, Roster} = mod_roster:get_user_roster([], Params, Extra),
  154:     Roster.
  155: 
  156: assert_state_old(Subscription, Ask) ->
  157:     [Rentry] = get_roster_old(),
  158:     ?assertEqual(Subscription, Rentry#roster.subscription),
  159:     ?assertEqual(Ask, Rentry#roster.ask).
  160: 
  161: init_ets() ->
  162:     catch ets:new(mongoose_services, [named_table]),
  163:     ok.
  164: 
  165: delete_ets() ->
  166:     catch ets:delete(mongoose_services),
  167:     ok.
  168: 
  169: alice_jid() ->
  170:     jid:make(a(), domain(), <<>>).
  171: 
  172: alicE_jid() ->
  173:     jid:make(ae(), domain(), <<>>).
  174: 
  175: a() -> <<"alice">>.
  176: ae() -> <<"alicE">>.
  177: 
  178: domain() -> <<"localhost">>.
  179: 
  180: bob() -> <<"bob@localhost">>.
  181: 
  182: bob_jid() ->
  183:     jid:make(<<"bob">>, domain(), <<>>).
  184: 
  185: bob_ljid() ->
  186:     jid:to_lower(bob_jid()).
  187: 
  188: host_type() -> <<"test type">>.
  189: 
  190: addbob_stanza() ->
  191:     #xmlel{children = [
  192:         #xmlel{
  193:             attrs = [{<<"jid">>, bob()}],
  194:             children = [
  195:                 #xmlel{name = <<"group">>,
  196:                     children = [
  197:                         #xmlcdata{content = <<"friends">>}
  198:                     ]}
  199:             ]}
  200:         ]
  201:     }.