1: %%============================================================================== 2: %% Copyright 2010 Erlang Solutions Ltd. 3: %% 4: %% Licensed under the Apache License, Version 2.0 (the "License"); 5: %% you may not use this file except in compliance with the License. 6: %% You may obtain a copy of the License at 7: %% 8: %% http://www.apache.org/licenses/LICENSE-2.0 9: %% 10: %% Unless required by applicable law or agreed to in writing, software 11: %% distributed under the License is distributed on an "AS IS" BASIS, 12: %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13: %% See the License for the specific language governing permissions and 14: %% limitations under the License. 15: %%============================================================================== 16: 17: -module(presence_SUITE). 18: -compile([export_all, nowarn_export_all]). 19: 20: -include_lib("exml/include/exml.hrl"). 21: -include_lib("escalus/include/escalus.hrl"). 22: -include_lib("common_test/include/ct.hrl"). 23: 24: -import(distributed_helper, [mim/0, 25: require_rpc_nodes/1, 26: rpc/4]). 27: 28: -import(domain_helper, [host_type/0]). 29: 30: -import(roster_helper, [set_versioning/3]). 31: 32: %%-------------------------------------------------------------------- 33: %% Suite configuration 34: %%-------------------------------------------------------------------- 35: 36: all() -> 37: [{group, presence}, 38: {group, presence_priority}, 39: {group, roster}, 40: {group, roster_versioning}, 41: {group, subscribe_group}]. 42: 43: groups() -> 44: [{presence, [parallel], [available, 45: explicit_available, 46: available_direct, 47: available_direct_then_unavailable, 48: become_unavailable, 49: available_direct_then_disconnect, 50: additions, 51: invalid_presence 52: ]}, 53: {presence_priority, [parallel], [negative_priority_presence]}, 54: {roster, [parallel], [get_roster, 55: fail_to_get_another_users_roster, 56: add_contact, 57: fail_to_add_contact_for_another_user, 58: remove_contact]}, 59: {roster_versioning, [], [versioning, 60: versioning_no_store]}, 61: {subscribe_group, [parallel], [subscribe, 62: subscribe_decline, 63: subscribe_relog, 64: subscribe_preserves_extra_info, 65: unsubscribe, 66: remove_unsubscribe]}]. 67: 68: suite() -> 69: require_rpc_nodes([mim]) ++ escalus:suite(). 70: 71: %%-------------------------------------------------------------------- 72: %% Init & teardown 73: %%-------------------------------------------------------------------- 74: 75: init_per_suite(Config) -> 76: escalus:init_per_suite(Config). 77: 78: end_per_suite(Config) -> 79: escalus_fresh:clean(), 80: escalus:end_per_suite(Config). 81: 82: init_per_group(roster_versioning, Config) -> 83: Config0 = dynamic_modules:save_modules(host_type(), Config), 84: escalus:create_users(Config0, escalus:get_users([alice, bob])); 85: init_per_group(_GroupName, Config) -> 86: escalus:create_users(Config, escalus:get_users([alice, bob])). 87: 88: end_per_group(roster_versioning, Config) -> 89: dynamic_modules:restore_modules(Config), 90: escalus:delete_users(Config, escalus:get_users([alice, bob])); 91: end_per_group(_GroupName, Config) -> 92: escalus:delete_users(Config, escalus:get_users([alice, bob])). 93: 94: init_per_testcase(versioning, ConfigIn) -> 95: Config = set_versioning(true, true, ConfigIn), 96: escalus:init_per_testcase(versioning, Config); 97: init_per_testcase(versioning_no_store, ConfigIn) -> 98: Config = set_versioning(true, false, ConfigIn), 99: escalus:init_per_testcase(versioning_no_store, Config); 100: init_per_testcase(CaseName, Config) -> 101: escalus:init_per_testcase(CaseName, Config). 102: 103: end_per_testcase(add_contact, Config) -> 104: [{_, UserSpec} | _] = escalus_config:get_config(escalus_users, Config), 105: remove_roster(Config, UserSpec), 106: escalus:end_per_testcase(add_contact, Config); 107: end_per_testcase(subscribe, Config) -> 108: end_rosters_remove(Config); 109: end_per_testcase(subscribe_decline, Config) -> 110: end_rosters_remove(Config); 111: end_per_testcase(unsubscribe, Config) -> 112: end_rosters_remove(Config); 113: end_per_testcase(VersionCases, Config) 114: when VersionCases =:= versioning; VersionCases =:= versioning_no_store -> 115: end_rosters_remove(Config); 116: end_per_testcase(CaseName, Config) -> 117: escalus:end_per_testcase(CaseName, Config). 118: 119: end_rosters_remove(Config) -> 120: [{_, UserSpec1}, {_, UserSpec2} | _] = 121: escalus_config:get_config(escalus_users, Config), 122: remove_roster(Config, UserSpec1), 123: remove_roster(Config, UserSpec2), 124: escalus:end_per_testcase(subscription, Config). 125: 126: 127: %%-------------------------------------------------------------------- 128: %% Tests 129: %%-------------------------------------------------------------------- 130: 131: available(Config) -> 132: Presence = escalus_stanza:presence(<<"available">>), 133: run_send_available_presence(Config, Presence). 134: 135: explicit_available(Config) -> 136: Presence = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"available">>}]}, 137: run_send_available_presence(Config, Presence). 138: 139: run_send_available_presence(Config, Presence) -> 140: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 141: escalus:send(Alice, Presence), 142: escalus:assert(is_presence, escalus:wait_for_stanza(Alice)) 143: end). 144: 145: available_direct(Config) -> 146: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 147: 148: BobJid = escalus_client:short_jid(Bob), 149: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"available">>)), 150: Received = escalus:wait_for_stanza(Bob), 151: escalus:assert(is_presence, Received), 152: escalus_assert:is_stanza_from(Alice, Received) 153: 154: end). 155: 156: available_direct_then_unavailable(Config) -> 157: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 158: %% given Alice has sent direct presence to Bob 159: escalus:send(Alice, escalus_stanza:presence_direct(Bob, <<"available">>)), 160: Received1 = escalus:wait_for_stanza(Bob), 161: escalus:assert(is_presence, Received1), 162: escalus_assert:is_stanza_from(Alice, Received1), 163: 164: %% when Alice sends presence unavailable 165: escalus:send(Alice, escalus_stanza:presence(<<"unavailable">>)), 166: 167: %% then Bob receives presence unavailable 168: Received2 = escalus:wait_for_stanza(Bob), 169: escalus:assert(is_presence, Received2), 170: escalus_assert:is_stanza_from(Alice, Received2) 171: end). 172: 173: become_unavailable(Config) -> 174: %% We test that after sending presence unavailable, priority is set to undefined in the SM table, 175: %% so the session is not on a list of active sessions 176: escalus:story(Config, [{alice, 1}], fun(Alice) -> push_helper:become_unavailable(Alice) end). 177: 178: available_direct_then_disconnect(Config) -> 179: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 180: %% given Alice has sent direct presence to Bob 181: escalus:send(Alice, escalus_stanza:presence_direct(Bob, <<"available">>)), 182: Received1 = escalus:wait_for_stanza(Bob), 183: escalus:assert(is_presence, Received1), 184: escalus_assert:is_stanza_from(Alice, Received1), 185: 186: %% when Alice suddenly disconnects 187: escalus_client:kill_connection(Config, Alice), 188: 189: %% then Bob receives presence unavailable 190: Received2 = escalus:wait_for_stanza(Bob), 191: escalus:assert(is_presence, Received2), 192: escalus_assert:is_stanza_from(Alice, Received2) 193: end). 194: 195: additions(Config) -> 196: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 197: 198: Tags = escalus_stanza:tags([ 199: {<<"show">>, <<"dnd">>}, 200: {<<"priority">>, <<"1">>}, 201: {<<"status">>, <<"Short break">>} 202: ]), 203: BobJid = escalus_client:short_jid(Bob), 204: Presence = escalus_stanza:presence_direct(BobJid, <<"available">>, Tags), 205: escalus:send(Alice, Presence), 206: 207: Received = escalus:wait_for_stanza(Bob), 208: escalus:assert(is_presence, Received), 209: escalus:assert(is_presence_with_show, [<<"dnd">>], Received), 210: escalus:assert(is_presence_with_status, [<<"Short break">>], Received), 211: escalus:assert(is_presence_with_priority, [<<"1">>], Received) 212: 213: end). 214: 215: invalid_presence(Config) -> 216: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 217: Presence = escalus_stanza:presence(<<"invalid-type">>), 218: escalus:send(Alice, Presence), 219: Received = escalus:wait_for_stanza(Alice), 220: escalus_assert:is_error(Received, <<"modify">>, <<"bad-request">>) 221: end). 222: 223: negative_priority_presence(Config) -> 224: escalus:fresh_story(Config, [{alice, 2}, {bob, 1}], fun(Alice1, Alice2, Bob) -> 225: 226: %% Alice1 updates presense priority 227: Tags = escalus_stanza:tags([ 228: {<<"priority">>, <<"-10">>} 229: ]), 230: Presence = escalus_stanza:presence(<<"available">>, Tags), 231: escalus:send(Alice1, Presence), 232: 233: Received1 = escalus:wait_for_stanza(Alice1), 234: Received2 = escalus:wait_for_stanza(Alice2), 235: escalus:assert(is_presence, Received1), 236: escalus:assert(is_presence, Received2), 237: escalus:assert(is_presence_with_priority, [<<"-10">>], Received1), 238: escalus:assert(is_presence_with_priority, [<<"-10">>], Received2), 239: 240: %% Bob sends to the Alice's bare JID. 241: escalus:send(Bob, escalus_stanza:chat_to_short_jid(Alice1, <<"Hi.">>)), 242: 243: %% If priority is negative, than the client does not want to receive 244: %% any messages. 245: timer:sleep(1000), 246: escalus_assert:has_no_stanzas(Alice1) 247: 248: end). 249: 250: get_roster(Config) -> 251: escalus:fresh_story(Config, [{alice, 1}], fun(Alice) -> 252: escalus:send(Alice, escalus_stanza:roster_get()), 253: escalus_assert:is_roster_result(escalus:wait_for_stanza(Alice)) 254: 255: end). 256: 257: fail_to_get_another_users_roster(Config) -> 258: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 259: BobJid = escalus_client:short_jid(Bob), 260: Request = escalus_stanza:roster_get(), 261: escalus:send(Alice, escalus_stanza:to(Request, BobJid)), 262: Response = escalus:wait_for_stanza(Alice), 263: escalus:assert(is_iq_error, [Request], Response), 264: escalus:assert(is_error, [<<"auth">>, <<"forbidden">>], Response), 265: escalus:assert(is_stanza_from, [BobJid], Response) 266: 267: end). 268: 269: add_contact(Config) -> 270: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 271: 272: %% add contact 273: Stanza = escalus_stanza:roster_add_contact(Bob, bobs_default_groups(), 274: bobs_default_name()), 275: escalus:send(Alice, Stanza), 276: Received = escalus:wait_for_stanzas(Alice, 2), 277: escalus:assert_many([is_roster_set, is_iq_result], Received), 278: 279: Result = hd([R || R <- Received, escalus_pred:is_roster_set(R)]), 280: escalus:assert(count_roster_items, [1], Result), 281: escalus:send(Alice, escalus_stanza:iq_result(Result)), 282: 283: %% check roster 284: escalus:send(Alice, escalus_stanza:roster_get()), 285: Received2 = escalus:wait_for_stanza(Alice), 286: 287: escalus:assert(is_roster_result, Received2), 288: BobJid = escalus_client:short_jid(Bob), 289: escalus:assert(roster_contains, [BobJid], Received2) 290: 291: end). 292: 293: fail_to_add_contact_for_another_user(Config) -> 294: escalus:story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 295: BobJid = escalus_client:short_jid(Bob), 296: Request = escalus_stanza:roster_add_contact(BobJid, bobs_default_groups(), 297: bobs_default_name()), 298: escalus:send(Alice, escalus_stanza:to(Request, BobJid)), 299: Response = escalus:wait_for_stanza(Alice), 300: escalus:assert(is_iq_error, [Request], Response), 301: escalus:assert(is_error, [<<"auth">>, <<"forbidden">>], Response), 302: escalus:assert(is_stanza_from, [BobJid], Response) 303: 304: end). 305: 306: remove_contact(Config) -> 307: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 308: 309: %% add contact 310: add_sample_contact(Alice, Bob), 311: 312: %% check roster 313: escalus:send(Alice, escalus_stanza:roster_get()), 314: escalus:assert(count_roster_items, [1], escalus:wait_for_stanza(Alice)), 315: 316: %% remove contact 317: escalus:send(Alice, escalus_stanza:roster_remove_contact(Bob)), 318: IsSubscriptionRemove = fun(El) -> 319: Sub = exml_query:paths(El, [{element, <<"query">>}, 320: {element, <<"item">>}, 321: {attr, <<"subscription">>}]), 322: Sub == [<<"remove">>] 323: end, 324: escalus:assert_many([IsSubscriptionRemove, is_iq_result], 325: escalus:wait_for_stanzas(Alice, 2)), 326: 327: %% check roster 328: escalus:send(Alice, escalus_stanza:roster_get()), 329: escalus:assert(count_roster_items, [0], escalus:wait_for_stanza(Alice)) 330: 331: end). 332: 333: versioning(Config) -> 334: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 335: 336: escalus:send(Alice, escalus_stanza:roster_get(<<"">>)), 337: RosterResult = escalus:wait_for_stanza(Alice), 338: 339: escalus_assert:is_roster_result(RosterResult), 340: Ver = exml_query:path(RosterResult, [{element, <<"query">>}, {attr, <<"ver">>}]), 341: 342: true = Ver /= undefined, 343: 344: %% add contact 345: Stanza = escalus_stanza:roster_add_contact(Bob, bobs_default_groups(), 346: bobs_default_name()), 347: escalus:send(Alice, Stanza), 348: Received = escalus:wait_for_stanzas(Alice, 2), 349: 350: escalus:assert_many([is_roster_set, is_iq_result], Received), 351: 352: RosterSet = hd(Received), 353: 354: Ver2 = exml_query:path(RosterSet, [{element, <<"query">>}, {attr, <<"ver">>}]), 355: 356: true = Ver2 /= undefined, 357: 358: Result = hd([R || R <- Received, escalus_pred:is_roster_set(R)]), 359: escalus:assert(count_roster_items, [1], Result), 360: escalus:send(Alice, escalus_stanza:iq_result(Result)), 361: 362: %% check roster, send old ver 363: escalus:send(Alice, escalus_stanza:roster_get(Ver)), 364: Received2 = escalus:wait_for_stanza(Alice), 365: 366: escalus:assert(is_roster_result, Received2), 367: BobJid = escalus_client:short_jid(Bob), 368: escalus:assert(roster_contains, [BobJid], Received2), 369: 370: %% check version 371: 372: Ver2 = exml_query:path(Received2, [{element, <<"query">>}, {attr, <<"ver">>}]), 373: 374: %% check roster, send correct Ver 375: 376: escalus:send(Alice, escalus_stanza:roster_get(Ver2)), 377: Received3 = escalus:wait_for_stanza(Alice), 378: 379: escalus:assert(is_iq_result, Received3), 380: 381: %% There is no content as version matches 382: 383: undefined = exml_query:path(Received3, [{element, <<"query">>}]) 384: 385: end). 386: 387: versioning_no_store(Config) -> 388: versioning(Config). 389: 390: subscribe(Config) -> 391: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 392: BobJid = escalus_client:short_jid(Bob), 393: AliceJid = escalus_client:short_jid(Alice), 394: 395: %% Alice adds Bob as a contact 396: add_sample_contact(Alice, Bob), 397: 398: %% She subscribes to his presences 399: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, 400: <<"subscribe">>)), 401: PushReq = escalus:wait_for_stanza(Alice), 402: escalus:assert(is_roster_set, PushReq), 403: escalus:send(Alice, escalus_stanza:iq_result(PushReq)), 404: 405: %% Bob receives subscription request 406: Received = escalus:wait_for_stanza(Bob), 407: escalus:assert(is_presence_with_type, [<<"subscribe">>], Received), 408: 409: check_roster_count(Bob, 0), % she is in his roster but invisible 410: % because she is {none, in} 411: 412: %% Bob adds new contact to his roster 413: escalus:send(Bob, escalus_stanza:roster_add_contact(Alice, 414: [<<"enemies">>], 415: <<"Alice">>)), 416: PushReqB = escalus:wait_for_stanza(Bob), 417: escalus:assert(is_roster_set, PushReqB), 418: escalus:send(Bob, escalus_stanza:iq_result(PushReqB)), 419: escalus:assert(is_iq_result, escalus:wait_for_stanza(Bob)), 420: 421: %% Bob sends subscribed presence 422: escalus:send(Bob, escalus_stanza:presence_direct(AliceJid, 423: <<"subscribed">>)), 424: 425: %% Alice receives subscribed 426: Stanzas = escalus:wait_for_stanzas(Alice, 2), 427: 428: check_subscription_stanzas(Stanzas, <<"subscribed">>), 429: escalus:assert(is_presence, escalus:wait_for_stanza(Alice)), 430: 431: %% Bob receives roster push 432: PushReqB1 = escalus:wait_for_stanza(Bob), 433: escalus:assert(is_roster_set, PushReqB1), 434: 435: check_roster_count(Bob, 1), 436: %% Bob sends presence 437: escalus:send(Bob, escalus_stanza:presence(<<"available">>)), 438: escalus:assert(is_presence, escalus:wait_for_stanza(Alice)), 439: 440: %% Bob sends presence 441: escalus:send(Bob, escalus_stanza:presence(<<"unavailable">>)), 442: escalus:assert(is_presence_with_type, [<<"unavailable">>], 443: escalus:wait_for_stanza(Alice)) 444: 445: end). 446: 447: subscribe_decline(Config) -> 448: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice,Bob) -> 449: BobJid = escalus_client:short_jid(Bob), 450: AliceJid = escalus_client:short_jid(Alice), 451: 452: %% add contact 453: add_sample_contact(Alice, Bob), 454: 455: %% subscribe 456: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"subscribe">>)), 457: PushReq = escalus:wait_for_stanza(Alice), 458: escalus_assert:is_roster_set(PushReq), 459: escalus:send(Alice, escalus_stanza:iq_result(PushReq)), 460: 461: %% Bob receives subscription request 462: Received = escalus:wait_for_stanza(Bob), 463: escalus:assert(is_presence_with_type, [<<"subscribe">>], Received), 464: 465: %% Bob refuses subscription 466: escalus:send(Bob, escalus_stanza:presence_direct(AliceJid, <<"unsubscribed">>)), 467: 468: %% Alice receives subscribed 469: Stanzas = escalus:wait_for_stanzas(Alice, 2), 470: 471: check_subscription_stanzas(Stanzas, <<"unsubscribed">>) 472: 473: end). 474: 475: subscribe_relog(Config) -> 476: Users = [{alice, 1}, {bob, 1}], 477: FreshConfig = escalus_fresh:create_users(Config, Users), 478: escalus:story(FreshConfig, Users, fun(Alice, Bob) -> 479: BobJid = escalus_client:short_jid(Bob), 480: AliceJid = escalus_client:short_jid(Alice), 481: 482: %% Alice adds Bob as a contact 483: add_sample_contact(Alice, Bob), 484: 485: %% She subscribes to his presences 486: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"subscribe">>)), 487: PushReq = escalus:wait_for_stanza(Alice), 488: escalus:assert(is_roster_set, PushReq), 489: escalus:send(Alice, escalus_stanza:iq_result(PushReq)), 490: 491: %% Bob receives subscription request 492: Received = escalus:wait_for_stanza(Bob), 493: escalus:assert(is_presence_with_type, [<<"subscribe">>], Received), 494: 495: %% New Bob resource connects, should receive subscription request again 496: {ok, NewBob} = escalus_client:start_for(FreshConfig, bob, <<"newbob">>), 497: escalus:send(NewBob, escalus_stanza:presence(<<"available">>)), 498: 499: escalus:assert(is_presence_with_type, [<<"available">>], 500: escalus:wait_for_stanza(Bob)), 501: 502: Stanzas = escalus:wait_for_stanzas(NewBob, 3), 503: 3 = length(Stanzas), 504: 505: escalus_new_assert:mix_match([ 506: fun(S) -> 507: escalus_pred:is_presence_with_type(<<"available">>, S) 508: andalso escalus_pred:is_stanza_from(Bob, S) 509: end, 510: fun(S) -> 511: escalus_pred:is_presence_with_type(<<"available">>, S) 512: andalso escalus_pred:is_stanza_from(NewBob, S) 513: end, 514: fun(S) -> 515: escalus_pred:is_presence_with_type(<<"subscribe">>, S) 516: andalso escalus_pred:is_stanza_from(AliceJid, S) 517: end 518: ], Stanzas), 519: 520: escalus_client:stop(Config, NewBob), 521: 522: escalus:send(Bob, escalus_stanza:presence_direct(AliceJid, <<"unsubscribed">>)) 523: 524: end). 525: 526: %% This test verifies that a subscription request doesn't remove nickname of a contact 527: %% and doesn't remove them from a group. 528: subscribe_preserves_extra_info(Config) -> 529: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 530: %% Alice adds Bob as a contact 531: add_sample_contact(Alice, Bob), 532: 533: %% Subscription without confirmation to prevent unavailable presence exchange 534: %% after the test; TODO: escalus_story should ignore them automatically 535: BobJid = escalus_client:short_jid(Bob), 536: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"subscribe">>)), 537: PushReq = escalus:wait_for_stanza(Alice), % Roster set 538: escalus:send(Alice, escalus_stanza:iq_result(PushReq)), 539: Received = escalus:wait_for_stanza(Bob), 540: escalus:assert(is_presence_with_type, [<<"subscribe">>], Received), 541: 542: %% Alice gets current roster 543: escalus:send(Alice, escalus_stanza:roster_get()), 544: RosterResult = escalus:wait_for_stanza(Alice), 545: escalus_assert:is_roster_result(RosterResult), 546: 547: %% Actual verification 548: [BobItem] = exml_query:paths(RosterResult, [{element, <<"query">>}, {element, <<"item">>}]), 549: 550: ValidName = bobs_default_name(), 551: ValidGroups = lists:sort(bobs_default_groups()), 552: 553: {ValidName, ValidGroups} 554: = {exml_query:attr(BobItem, <<"name">>), 555: lists:sort(exml_query:paths(BobItem, [{element, <<"group">>}, cdata]))} 556: end). 557: 558: unsubscribe(Config) -> 559: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 560: BobJid = escalus_client:short_jid(Bob), 561: AliceJid = escalus_client:short_jid(Alice), 562: 563: %% add contact 564: add_sample_contact(Alice, Bob), 565: 566: %% subscribe 567: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"subscribe">>)), 568: PushReq = escalus:wait_for_stanza(Alice), 569: escalus:send(Alice, escalus_stanza:iq_result(PushReq)), 570: 571: %% Bob receives subscription request 572: escalus:assert(is_presence_with_type, [<<"subscribe">>], 573: escalus:wait_for_stanza(Bob)), 574: %% Bob adds new contact to his roster 575: escalus:send(Bob, escalus_stanza:roster_add_contact(Alice, 576: [<<"enemies">>], 577: <<"Alice">>)), 578: PushReqB = escalus:wait_for_stanza(Bob), 579: escalus:send(Bob, escalus_stanza:iq_result(PushReqB)), 580: escalus:assert(is_iq_result, escalus:wait_for_stanza(Bob)), 581: 582: %% Bob sends subscribed presence 583: escalus:send(Bob, escalus_stanza:presence_direct(AliceJid, <<"subscribed">>)), 584: 585: %% Alice receives subscribed 586: Stanzas = escalus:wait_for_stanzas(Alice, 2), 587: 588: check_subscription_stanzas(Stanzas, <<"subscribed">>), 589: escalus:assert(is_presence, escalus:wait_for_stanza(Alice)), 590: 591: %% Bob receives roster push 592: PushReqB1 = escalus:wait_for_stanza(Bob), 593: escalus_assert:is_roster_set(PushReqB1), 594: 595: %% Alice sends unsubscribe 596: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"unsubscribe">>)), 597: 598: PushReqA2 = escalus:wait_for_stanza(Alice), 599: escalus_assert:is_roster_set(PushReqA2), 600: escalus:send(Alice, escalus_stanza:iq_result(PushReqA2)), 601: 602: %% Bob receives unsubscribe 603: 604: StanzasB = escalus:wait_for_stanzas(Bob, 2), 605: 606: check_subscription_stanzas(StanzasB, <<"unsubscribe">>), 607: 608: %% Alice receives unsubscribed 609: escalus:assert(is_presence_with_type, [<<"unavailable">>], 610: escalus:wait_for_stanza(Alice)) 611: end). 612: 613: remove_unsubscribe(Config) -> 614: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 615: BobJid = escalus_client:short_jid(Bob), 616: AliceJid = escalus_client:short_jid(Alice), 617: 618: %% add contact 619: add_sample_contact(Alice, Bob), 620: 621: %% subscribe 622: escalus:send(Alice, escalus_stanza:presence_direct(BobJid, <<"subscribe">>)), 623: PushReq = escalus:wait_for_stanza(Alice), 624: escalus:send(Alice, escalus_stanza:iq_result(PushReq)), 625: 626: %% Bob receives subscription request 627: escalus:assert(is_presence_with_type, [<<"subscribe">>], 628: escalus:wait_for_stanza(Bob)), 629: %% Bob adds new contact to his roster 630: escalus:send(Bob, escalus_stanza:roster_add_contact(Alice, 631: [<<"enemies">>], 632: <<"Alice">>)), 633: PushReqB = escalus:wait_for_stanza(Bob), 634: escalus:send(Bob, escalus_stanza:iq_result(PushReqB)), 635: escalus:assert(is_iq_result, escalus:wait_for_stanza(Bob)), 636: 637: %% Bob sends subscribed presence 638: escalus:send(Bob, escalus_stanza:presence_direct(AliceJid, <<"subscribed">>)), 639: 640: %% Alice receives subscribed 641: Stanzas = [escalus:wait_for_stanza(Alice), 642: escalus:wait_for_stanza(Alice)], 643: 644: check_subscription_stanzas(Stanzas, <<"subscribed">>), 645: escalus:assert(is_presence, escalus:wait_for_stanza(Alice)), 646: 647: %% Bob receives roster push 648: PushReqB1 = escalus:wait_for_stanza(Bob), 649: escalus_assert:is_roster_set(PushReqB1), 650: 651: %% remove contact 652: escalus:send(Alice, escalus_stanza:roster_remove_contact(Bob)), 653: 654: IsPresUnavailable = 655: fun(S) -> 656: escalus_pred:is_presence_with_type(<<"unavailable">>, S) 657: end, 658: escalus:assert_many([is_roster_set, is_iq_result, IsPresUnavailable], 659: escalus:wait_for_stanzas(Alice, 3)), 660: check_subscription_stanzas(escalus:wait_for_stanzas(Bob, 2), 661: <<"unsubscribe">>) 662: 663: end). 664: 665: 666: %%----------------------------------------------------------------- 667: %% Helpers 668: %%----------------------------------------------------------------- 669: 670: bobs_default_groups() -> [<<"friends">>]. 671: 672: bobs_default_name() -> <<"Bobby">>. 673: 674: add_sample_contact(Alice, Bob) -> 675: escalus:send(Alice, escalus_stanza:roster_add_contact(Bob, 676: bobs_default_groups(), 677: bobs_default_name())), 678: 679: Received = escalus:wait_for_stanzas(Alice, 2), 680: escalus:assert_many([is_roster_set, is_iq_result], Received), 681: 682: Result = hd([R || R <- Received, escalus_pred:is_roster_set(R)]), 683: escalus:assert(count_roster_items, [1], Result), 684: escalus:send(Alice, escalus_stanza:iq_result(Result)). 685: 686: check_subscription_stanzas(Stanzas, Type) -> 687: IsPresWithType = fun(S) -> 688: escalus_pred:is_presence_with_type(Type, S) 689: end, 690: escalus:assert_many([is_roster_set, IsPresWithType], Stanzas). 691: 692: remove_roster(Config, UserSpec) -> 693: [Username, Server, _Pass] = [escalus_ejabberd:unify_str_arg(Item) || 694: Item <- escalus_users:get_usp(Config, UserSpec)], 695: Mods = rpc(mim(), gen_mod, loaded_modules, [host_type()]), 696: case lists:member(mod_roster, Mods) of 697: true -> 698: Acc = mongoose_helper:new_mongoose_acc(Server), 699: Extra = #{host_type => host_type()}, 700: Params = #{jid => jid:make_bare(Username, Server)}, 701: rpc(mim(), mod_roster, remove_user, [Acc, Params, Extra]); 702: false -> 703: case lists:member(mod_roster_rdbms, Mods) of 704: true -> 705: rpc(mim(), mod_roster_rdbms, remove_user_t, [host_type(), Username, Server]); 706: false -> 707: throw(roster_not_loaded) 708: end 709: end. 710: 711: check_roster_count(User, ExpectedCount) -> 712: % the user sends get_roster iq 713: escalus_client:send(User, escalus_stanza:roster_get()), 714: Roster = escalus_client:wait_for_stanza(User), 715: ct:pal("Roster: ~p", [Roster]), 716: % Roster contains all created users excluding user 717: escalus:assert(is_roster_result, Roster), 718: escalus:assert(count_roster_items, [ExpectedCount], Roster).