1: -module(xep_0352_csi_SUITE). 2: 3: -include_lib("exml/include/exml.hrl"). 4: -include_lib("escalus/include/escalus.hrl"). 5: 6: -compile([export_all, nowarn_export_all]). 7: 8: -import(domain_helper, [host_type/0]). 9: 10: -define(CSI_BUFFER_MAX, 10). 11: 12: all() -> 13: [{group, basic}]. 14: 15: 16: groups() -> 17: [{basic, [parallel, shuffle], all_tests()}]. 18: 19: all_tests() -> 20: [ 21: server_announces_csi, 22: alice_is_inactive_and_no_stanza_arrived, 23: alice_gets_msgs_after_activate, 24: alice_gets_msgs_after_activate_in_order, 25: alice_gets_message_after_buffer_overflow, 26: alice_gets_buffered_messages_after_reconnection_with_sm, 27: alice_gets_buffered_messages_after_stream_resumption, 28: bob_gets_msgs_from_inactive_alice, 29: alice_is_inactive_but_sends_sm_req_and_recives_ack 30: ]. 31: 32: suite() -> 33: escalus:suite(). 34: 35: init_per_suite(Config) -> 36: NewConfig = dynamic_modules:save_modules(host_type(), Config), 37: dynamic_modules:ensure_modules( 38: host_type(), [{mod_offline, []}, {mod_csi, [{buffer_max, ?CSI_BUFFER_MAX}]}]), 39: [{escalus_user_db, {module, escalus_ejabberd}} | escalus:init_per_suite(NewConfig)]. 40: 41: end_per_suite(Config) -> 42: escalus_fresh:clean(), 43: dynamic_modules:restore_modules(Config), 44: escalus:end_per_suite(Config). 45: 46: init_per_group(_, Config) -> 47: escalus_users:update_userspec(Config, alice, stream_management, true). 48: 49: end_per_group(_Group, Config) -> 50: Config. 51: 52: init_per_testcase(CaseName, Config) -> 53: escalus:init_per_testcase(CaseName, Config). 54: 55: end_per_testcase(CaseName, Config) -> 56: escalus:end_per_testcase(CaseName, Config). 57: 58: server_announces_csi(Config) -> 59: NewConfig = escalus_fresh:create_users(Config, [{alice, 1}]), 60: Spec = escalus_users:get_userspec(NewConfig, alice), 61: Steps = [start_stream, 62: stream_features, 63: maybe_use_ssl, 64: authenticate, 65: bind, 66: session], 67: {ok, _Client, Features} = escalus_connection:start(Spec, Steps), 68: true = proplists:get_value(client_state_indication, Features). 69: 70: alice_is_inactive_and_no_stanza_arrived(Config) -> 71: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 72: given_client_is_inactive_and_messages_sent(Alice, Bob, 1), 73: 74: escalus_assert:has_no_stanzas(Alice) 75: end). 76: 77: alice_gets_msgs_after_activate(Config) -> 78: alice_gets_msgs_after_activate(Config, 1). 79: 80: alice_gets_msgs_after_activate_in_order(Config) -> 81: alice_gets_msgs_after_activate(Config, 3). 82: 83: alice_gets_msgs_after_activate(Config, N) -> 84: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 85: %%Given 86: Msgs = given_client_is_inactive_and_messages_sent(Alice, Bob, N), 87: 88: %%When client becomes active again 89: escalus:send(Alice, csi_stanza(<<"active">>)), 90: 91: then_client_receives_message(Alice, Msgs) 92: end). 93: 94: alice_gets_buffered_messages_after_reconnection_with_sm(Config) -> 95: NewConfig = escalus_fresh:create_users(Config, [{alice, 1}, {bob, 1}]), 96: AliceSpec = escalus_users:get_userspec(NewConfig, alice), 97: BobSpec = escalus_users:get_userspec(NewConfig, bob), 98: {ok, Alice0 = #client{props = AliceProps}, _} = escalus_connection:start(AliceSpec), 99: JID = make_jid_from_spec(AliceProps), 100: Alice = Alice0#client{jid = JID}, 101: {ok, Bob, _} = escalus_connection:start(BobSpec), 102: 103: given_client_is_inactive(Alice), 104: 105: MsgsToAlice = given_client_is_inactive_and_messages_sent(Alice, Bob, 5), 106: 107: %% then Alice disconnects 108: 109: escalus_connection:kill(Alice), 110: 111: {ok, Alice2, _} = escalus_connection:start(AliceSpec), 112: 113: escalus_connection:send(Alice2, escalus_stanza:presence(<<"available">>)), 114: 115: then_client_receives_message(Alice2, MsgsToAlice), 116: 117: ok. 118: 119: alice_gets_buffered_messages_after_stream_resumption(Config) -> 120: ConnSteps = [start_stream, 121: stream_features, 122: authenticate, 123: bind, 124: session, 125: stream_resumption], 126: NewConfig = escalus_fresh:create_users(Config, [{alice, 1}, {bob, 1}]), 127: AliceSpec = escalus_users:get_userspec(NewConfig, alice), 128: BobSpec = escalus_users:get_userspec(NewConfig, bob), 129: {ok, Alice0 = #client{props = AliceProps}, _} = escalus_connection:start(AliceSpec, 130: ConnSteps), 131: JID = make_jid_from_spec(AliceProps), 132: Alice = Alice0#client{jid = JID}, 133: 134: escalus_connection:send(Alice, escalus_stanza:presence(<<"available">>)), 135: escalus:wait_for_stanza(Alice), 136: {ok, Bob, _} = escalus_connection:start(BobSpec), 137: 138: given_client_is_inactive(Alice), 139: 140: MsgsToAlice = given_client_is_inactive_and_messages_sent(Alice, Bob, 5), 141: 142: %% then Alice disconnects 143: 144: escalus_connection:kill(Alice), 145: 146: SMID = proplists:get_value(smid, AliceProps), 147: ResumeSession = [start_stream, 148: stream_features, 149: authenticate, 150: mk_resume_stream(SMID, 1)], 151: 152: {ok, Alice2, _} = escalus_connection:start(AliceSpec, ResumeSession), 153: 154: escalus_connection:send(Alice2, escalus_stanza:presence(<<"available">>)), 155: 156: then_client_receives_message(Alice2, MsgsToAlice), 157: 158: ok. 159: 160: make_jid_from_spec(AliceProps) -> 161: AliceUsername = proplists:get_value(username, AliceProps), 162: AliceServer = proplists:get_value(server, AliceProps), 163: <<AliceUsername/binary, "@", AliceServer/binary>>. 164: 165: mk_resume_stream(SMID, PrevH) -> 166: fun (Conn = #client{props = Props}, Features) -> 167: escalus_connection:send(Conn, escalus_stanza:resume(SMID, PrevH)), 168: Resumed = escalus_connection:get_stanza(Conn, get_resumed), 169: true = escalus_pred:is_sm_resumed(SMID, Resumed), 170: {Conn#client{props = [{smid, SMID} | Props]}, Features} 171: end. 172: 173: alice_gets_message_after_buffer_overflow(Config) -> 174: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 175: Msgs = given_client_is_inactive_and_messages_sent(Alice, Bob, ?CSI_BUFFER_MAX+5), 176: 177: {Flushed, Awaiting} = lists:split(?CSI_BUFFER_MAX+1, Msgs), 178: 179: then_client_receives_message(Alice, Flushed), 180: %% and no other stanza 181: escalus_assert:has_no_stanzas(Alice), 182: %% Alice activates 183: escalus:send(Alice, csi_stanza(<<"active">>)), 184: %% ands gets remaining stanzas 185: then_client_receives_message(Alice, Awaiting) 186: end). 187: 188: bob_gets_msgs_from_inactive_alice(Config) -> 189: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 190: given_client_is_inactive_but_sends_messages(Alice, Bob, 1), 191: 192: escalus:assert(is_chat_message, escalus:wait_for_stanza(Bob)) 193: end). 194: 195: alice_is_inactive_but_sends_sm_req_and_recives_ack(Config) -> 196: escalus:fresh_story(Config, [{alice,1}], fun(Alice) -> 197: given_client_is_inactive(Alice), 198: 199: escalus:send(Alice, escalus_stanza:sm_request()), 200: 201: escalus:assert(is_sm_ack, escalus:wait_for_stanza(Alice)) 202: 203: end). 204: 205: given_client_is_inactive_but_sends_messages(Alice, Bob, N) -> 206: %%Given 207: MsgsToAlice = given_client_is_inactive_and_messages_sent(Alice, Bob, N), 208: 209: MsgsToBob = gen_msgs(<<"Hi, Bob">>, N), 210: send_msgs(Alice, Bob, MsgsToBob), 211: timer:sleep(1), 212: {MsgsToAlice, MsgsToBob}. 213: 214: 215: then_client_receives_message(Alice, Msgs) -> 216: [escalus:assert(is_chat_message, [Msg], escalus:wait_for_stanza(Alice)) || 217: Msg <- Msgs]. 218: 219: 220: given_client_is_inactive_and_messages_sent(Alice, Bob, N) -> 221: %%Given 222: given_client_is_inactive(Alice), 223: 224: timer:sleep(1000), 225: 226: %%When 227: Msgs = gen_msgs(<<"Hi, Alice">>, N), 228: send_msgs(Bob, Alice, Msgs), 229: timer:sleep(timer:seconds(1)), 230: Msgs. 231: 232: send_msgs(From, To, Msgs) -> 233: [escalus:send(From, escalus_stanza:chat_to(To, Msg)) || 234: Msg <- Msgs]. 235: 236: 237: gen_msgs(Prefix, N) -> 238: [<<Prefix/binary, (integer_to_binary(I))/binary>> || I <- lists:seq(1, N)]. 239: 240: given_client_is_inactive(Alice) -> 241: escalus:send(Alice, csi_stanza(<<"inactive">>)). 242: 243: csi_stanza(Name) -> 244: #xmlel{name = Name, 245: attrs = [{<<"xmlns">>, <<"urn:xmpp:csi:0">>}]}.