1: -module(smart_markers_SUITE).
    2: -compile([export_all, nowarn_export_all]).
    3: 
    4: -include("muc_light.hrl").
    5: 
    6: -import(distributed_helper, [mim/0, rpc/4, subhost_pattern/1]).
    7: -import(domain_helper, [host_type/0]).
    8: 
    9: %%% Suite configuration
   10: all() ->
   11:     case (not ct_helper:is_ct_running())
   12:           orelse mongoose_helper:is_rdbms_enabled(host_type()) of
   13:         true -> all_cases();
   14:         false -> {skip, require_rdbms}
   15:     end.
   16: 
   17: all_cases() ->
   18:     [
   19:      {group, one2one},
   20:      {group, muclight}
   21:     ].
   22: 
   23: groups() ->
   24:     [
   25:      {one2one, [],
   26:       [
   27:        marker_is_stored,
   28:        remove_markers_when_removed_user
   29:       ]},
   30:      {muclight, [],
   31:       [
   32:        marker_is_stored_for_room,
   33:        marker_is_removed_when_user_leaves_room,
   34:        markers_are_removed_when_room_is_removed
   35:       ]}
   36:     ].
   37: 
   38: suite() ->
   39:     escalus:suite().
   40: 
   41: init_per_suite(Config) ->
   42:     escalus:init_per_suite(Config).
   43: 
   44: end_per_suite(Config) ->
   45:     escalus:end_per_suite(Config).
   46: 
   47: init_per_group(GroupName, Config) ->
   48:     ok = dynamic_modules:ensure_modules(host_type(), group_to_module(GroupName)),
   49:     Config.
   50: 
   51: group_to_module(one2one) ->
   52:     [{mod_smart_markers, [{backend, rdbms}]}];
   53: group_to_module(muclight) ->
   54:     [{mod_smart_markers, [{backend, rdbms}]},
   55:      {mod_muc_light,
   56:       [{host, subhost_pattern(muc_light_helper:muc_host_pattern())},
   57:        {backend, rdbms}]}].
   58: 
   59: end_per_group(muclight, Config) ->
   60:     muc_light_helper:clear_db(host_type()),
   61:     end_per_group(generic, Config);
   62: end_per_group(_, Config) ->
   63:     escalus_fresh:clean(),
   64:     dynamic_modules:restore_modules(Config),
   65:     Config.
   66: 
   67: init_per_testcase(Name, Config) ->
   68:     escalus:init_per_testcase(Name, Config).
   69: end_per_testcase(Name, Config) ->
   70:     escalus:end_per_testcase(Name, Config).
   71: 
   72: %%% tests
   73: marker_is_stored(Config) ->
   74:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
   75:         send_message_respond_marker(Alice, Bob),
   76:         AliceJid = jid:from_binary(escalus_client:full_jid(Alice)),
   77:         BobJid = jid:from_binary(escalus_client:full_jid(Bob)),
   78:         mongoose_helper:wait_until(
   79:           fun() -> length(fetch_markers_for_users(BobJid, AliceJid)) > 0 end, true)
   80:     end).
   81: 
   82: remove_markers_when_removed_user(Config) ->
   83:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
   84:         Body = <<"Hello Bob!">>,
   85:         MsgId = escalus_stanza:id(),
   86:         Msg = escalus_stanza:set_id(escalus_stanza:chat_to(Bob, Body), MsgId),
   87:         escalus:send(Alice, Msg),
   88:         escalus:wait_for_stanza(Bob),
   89:         ChatMarker = escalus_stanza:chat_marker(Alice, <<"displayed">>, MsgId),
   90:         escalus:send(Bob, ChatMarker),
   91:         escalus:wait_for_stanza(Alice),
   92:         AliceJid = jid:from_binary(escalus_client:full_jid(Alice)),
   93:         BobJid = jid:from_binary(escalus_client:full_jid(Bob)),
   94:         mongoose_helper:wait_until(fun() -> length(fetch_markers_for_users(BobJid, AliceJid)) > 0 end, true),
   95:         unregister_user(Bob),
   96:         mongoose_helper:wait_until(fun() -> length(fetch_markers_for_users(BobJid, AliceJid)) end, 0)
   97:     end).
   98: 
   99: marker_is_stored_for_room(Config) ->
  100:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}, {kate, 1}],
  101:                         fun(Alice, Bob, Kate) ->
  102:         Users = [Alice, Bob, Kate],
  103:         RoomId = create_room(Alice, [Bob, Kate], Config),
  104:         RoomBinJid = muc_light_helper:room_bin_jid(RoomId),
  105:         one_marker_in_room(Users, RoomBinJid, Alice, Bob),
  106:         BobJid = jid:from_binary(escalus_client:full_jid(Bob)),
  107:         mongoose_helper:wait_until(
  108:           fun() -> length(fetch_markers_for_users(BobJid, jid:from_binary(RoomBinJid))) > 0 end, true)
  109:     end).
  110: 
  111: marker_is_removed_when_user_leaves_room(Config) ->
  112:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}],
  113:                         fun(Alice, Bob) ->
  114:         Users = [Alice, Bob],
  115:         RoomId = create_room(Alice, [Bob], Config),
  116:         RoomBinJid = muc_light_helper:room_bin_jid(RoomId),
  117:         RoomJid = jid:from_binary(RoomBinJid),
  118:         one_marker_in_room(Users, RoomBinJid, Alice, Bob),
  119:         BobJid = jid:from_binary(escalus_client:full_jid(Bob)),
  120:         mongoose_helper:wait_until(
  121:           fun() -> length(fetch_markers_for_users(BobJid, RoomJid)) > 0 end, true),
  122:         % Remove Bob from the room
  123:         muc_light_helper:user_leave(RoomId, Bob, [Alice]),
  124:         mongoose_helper:wait_until(
  125:           fun() -> length(fetch_markers_for_users(BobJid, RoomJid)) end, 0)
  126:     end).
  127: 
  128: markers_are_removed_when_room_is_removed(Config) ->
  129:     escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) ->
  130:         Users = [Alice, Bob],
  131:         RoomId = create_room(Alice, [Bob], Config),
  132:         RoomBinJid = muc_light_helper:room_bin_jid(RoomId),
  133:         RoomJid = jid:from_binary(RoomBinJid),
  134:         one_marker_in_room(Users, RoomBinJid, Alice, Bob),
  135:         BobJid = jid:from_binary(escalus_client:full_jid(Bob)),
  136:         mongoose_helper:wait_until(
  137:           fun() -> length(fetch_markers_for_users(BobJid, RoomJid)) > 0 end, true),
  138:         %% The room is then deleted
  139:         delete_room(Alice, Users, RoomBinJid),
  140:         [ begin
  141:               Jid = jid:from_binary(escalus_client:full_jid(User)),
  142:               mongoose_helper:wait_until(
  143:                 fun() -> length(fetch_markers_for_users(Jid, RoomJid)) end, 0)
  144:           end || User <- Users]
  145:     end).
  146: 
  147: %%% helpers
  148: fetch_markers_for_users(From, To) ->
  149:     MRs = rpc(mim(), mod_smart_markers_backend, get_chat_markers,
  150:               [host_type(), To, undefined, 0]),
  151:     [MR || #{from := FR} = MR <- MRs, jid:are_bare_equal(From, FR)].
  152: 
  153: create_room(Owner, Members, Config) ->
  154:     RoomId = muc_helper:fresh_room_name(),
  155:     MucHost = muc_light_helper:muc_host(),
  156:     muc_light_helper:create_room(RoomId, MucHost, Owner, Members, Config, muc_light_helper:ver(1)),
  157:     RoomId.
  158: 
  159: delete_room(Owner, Users, RoomBinJid) ->
  160:     Destroy = escalus_stanza:to(escalus_stanza:iq_set(?NS_MUC_LIGHT_DESTROY, []), RoomBinJid),
  161:     escalus:send(Owner, Destroy),
  162:     AffUsersChanges = [{User, none} || User <- Users ],
  163:     muc_light_helper:verify_aff_bcast([], AffUsersChanges, [?NS_MUC_LIGHT_DESTROY]),
  164:     escalus:assert(is_iq_result, escalus:wait_for_stanza(Owner)).
  165: 
  166: one_marker_in_room(Users, RoomBinJid, Writer, Marker) ->
  167:         MsgId = escalus_stanza:id(),
  168:         Msg = escalus_stanza:set_id(
  169:                 escalus_stanza:groupchat_to(RoomBinJid, <<"Hello">>), MsgId),
  170:         escalus:send(Writer, Msg),
  171:         [ escalus:wait_for_stanza(User) || User <- Users],
  172:         ChatMarker = escalus_stanza:setattr(
  173:                        escalus_stanza:chat_marker(RoomBinJid, <<"displayed">>, MsgId),
  174:                        <<"type">>, <<"groupchat">>),
  175:         escalus:send(Marker, ChatMarker),
  176:         [ escalus:wait_for_stanza(User) || User <- Users],
  177:         MsgId.
  178: 
  179: send_message_respond_marker(MsgWriter, MarkerAnswerer) ->
  180:     Body = <<"Hello">>,
  181:     MsgId = escalus_stanza:id(),
  182:     Msg = escalus_stanza:set_id(escalus_stanza:chat_to(MarkerAnswerer, Body), MsgId),
  183:     escalus:send(MsgWriter, Msg),
  184:     escalus:wait_for_stanza(MarkerAnswerer),
  185:     ChatMarker = escalus_stanza:chat_marker(MsgWriter, <<"displayed">>, MsgId),
  186:     escalus:send(MarkerAnswerer, ChatMarker),
  187:     escalus:wait_for_stanza(MsgWriter).
  188: 
  189: unregister_user(Client) ->
  190:     Jid = jid:from_binary(escalus_client:short_jid(Client)),
  191:     rpc(mim(), ejabberd_auth, remove_user, [Jid]).