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