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