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(mod_blocking_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: -include_lib("eunit/include/eunit.hrl"). 24: -include_lib("escalus/include/escalus_xmlns.hrl"). 25: 26: -import(config_parser_helper, [mod_config_with_auto_backend/1]). 27: 28: -define(SLEEP_TIME, 50). 29: 30: %%-------------------------------------------------------------------- 31: %% Suite configuration 32: %%-------------------------------------------------------------------- 33: 34: all() -> 35: [ 36: {group, manage}, 37: {group, effect}, 38: {group, offline}, 39: {group, errors}, 40: {group, pushes} 41: ]. 42: 43: groups() -> 44: [ 45: {manage, [parallel], manage_test_cases()}, 46: {effect, [parallel], effect_test_cases()}, 47: {offline, [sequence], offline_test_cases()}, 48: {errors, [parallel], error_test_cases()}, 49: {pushes, [parallel], push_test_cases()}, 50: {notify, [parallel], notify_test_cases()} 51: ]. 52: 53: manage_test_cases() -> 54: [ 55: discovering_support, 56: get_block_list, 57: add_user_to_blocklist, 58: add_user_to_blocklist_with_white_spaces, 59: add_another_user_to_blocklist, 60: add_many_users_to_blocklist, 61: remove_user_from_blocklist, 62: remove_many_user_from_blocklist, 63: clear_blocklist, 64: invalid_block_request 65: ]. 66: 67: effect_test_cases() -> 68: [ 69: messages_from_blocked_user_dont_arrive, 70: messages_from_unblocked_user_arrive_again, 71: messages_from_any_blocked_resource_dont_arrive, 72: blocking_doesnt_interfere, 73: blocking_propagates_to_resources, 74: iq_reply_doesnt_crash_user_process 75: ]. 76: 77: offline_test_cases() -> 78: [ 79: messages_after_relogin, 80: messages_arrive_after_unblock_and_relogin, 81: blocking_and_relogin_many, 82: clear_list_relogin 83: ]. 84: 85: error_test_cases() -> 86: [blocker_cant_send_to_blockee]. 87: 88: push_test_cases() -> 89: [block_push_sent]. 90: 91: notify_test_cases() -> 92: [notify_blockee]. 93: 94: suite() -> 95: escalus:suite(). 96: 97: %%-------------------------------------------------------------------- 98: %% Init & teardown 99: %%-------------------------------------------------------------------- 100: 101: init_per_suite(Config0) -> 102: HostType = domain_helper:host_type(), 103: Config1 = dynamic_modules:save_modules(HostType, Config0), 104: ModConfig = [{mod_blocking, mod_config_with_auto_backend(mod_blocking)}], 105: dynamic_modules:ensure_modules(HostType, ModConfig), 106: escalus:init_per_suite(Config1). 107: 108: end_per_suite(Config) -> 109: escalus_fresh:clean(), 110: dynamic_modules:restore_modules(Config), 111: escalus:end_per_suite(Config). 112: 113: init_per_group(_GroupName, Config) -> 114: escalus_fresh:create_users(Config, escalus:get_users([alice, bob, kate, mike, john])). 115: 116: end_per_group(_GroupName, Config) -> 117: Config. 118: 119: init_per_testcase(CaseName, Config) -> 120: escalus:init_per_testcase(CaseName, Config). 121: 122: end_per_testcase(CaseName, Config) -> 123: escalus:end_per_testcase(CaseName, Config). 124: 125: %%-------------------------------------------------------------------- 126: %% Tests 127: %%-------------------------------------------------------------------- 128: 129: discovering_support(Config) -> 130: escalus:fresh_story( 131: Config, [{alice, 1}], 132: fun(User1) -> 133: Server = escalus_client:server(User1), 134: IqGet = escalus_stanza:disco_info(Server), 135: escalus_client:send(User1, IqGet), 136: Result = escalus_client:wait_for_stanza(User1), 137: escalus:assert(is_iq_result, [IqGet], Result), 138: escalus:assert(has_feature, [?NS_BLOCKING], Result) 139: end). 140: 141: 142: get_block_list(Config) -> 143: escalus:fresh_story( 144: Config, [{alice, 1}], 145: fun(User1) -> 146: Result = get_blocklist(User1), 147: escalus:assert(is_iq_result, Result), 148: escalus:assert(fun is_blocklist_result_empty/1, Result) 149: end). 150: 151: 152: add_user_to_blocklist(Config) -> 153: escalus:fresh_story( 154: Config, [{alice, 1}, {bob, 1}], 155: fun(User1, User2) -> 156: user_blocks(User1, [User2]), 157: BlockList = get_blocklist(User1), 158: blocklist_contains_jid(BlockList, User2) 159: end). 160: 161: add_user_to_blocklist_with_white_spaces(Config) -> 162: escalus:fresh_story( 163: Config, [{alice, 1}, {bob, 1}], 164: fun(User1, User2) -> 165: BlockeeJIDs = [escalus_utils:jid_to_lower(escalus_client:short_jid(B)) || B <- [User2]], 166: AddStanza = block_users_stanza_with_white_spaces(BlockeeJIDs), 167: escalus_client:send(User1, AddStanza), 168: Res = escalus:wait_for_stanza(User1), 169: escalus:assert(is_iq_result, Res) 170: end). 171: 172: add_another_user_to_blocklist(Config) -> 173: escalus:fresh_story( 174: Config, [{alice, 1}, {mike, 1}], 175: fun(User1, User2) -> 176: user_blocks(User1, [User2]), 177: BlockList = get_blocklist(User1), 178: blocklist_contains_jid(BlockList, User2) 179: end). 180: 181: add_many_users_to_blocklist(Config) -> 182: escalus:fresh_story( 183: Config, [{alice, 1}, {bob, 1}, {kate, 1}, {mike, 1}], 184: fun(User1, User2, User3, User4) -> 185: user_blocks(User1, [User2, User3, User4]), 186: BlockList = get_blocklist(User1), 187: blocklist_contains_jid(BlockList, User2), 188: blocklist_contains_jid(BlockList, User3), 189: blocklist_contains_jid(BlockList, User4) 190: end). 191: 192: remove_user_from_blocklist(Config) -> 193: escalus:fresh_story( 194: Config, [{alice, 1}, {bob, 1}], 195: fun(User1, User2) -> 196: user_blocks(User1, [User2]), 197: user_unblocks(User1, User2), 198: NewList = get_blocklist(User1), 199: blocklist_doesnt_contain_jid(NewList, User2) 200: end). 201: 202: remove_many_user_from_blocklist(Config) -> 203: escalus:fresh_story( 204: Config, [{alice, 1}, {bob, 1}, {kate, 1}], 205: fun(User1, User2, User3) -> 206: user_blocks(User1, [User2, User3]), 207: user_unblocks(User1, [User2, User3]), 208: NewList = get_blocklist(User1), 209: blocklist_doesnt_contain_jid(NewList, User2), 210: blocklist_doesnt_contain_jid(NewList, User3) 211: end). 212: 213: clear_blocklist(Config) -> 214: escalus:fresh_story( 215: Config, [{alice, 1}, {bob, 1}, {kate, 1}], 216: fun(User1, User2, User3) -> 217: user_blocks(User1, [User2, User3]), 218: user_unblocks_all(User1), 219: NewList = get_blocklist(User1), 220: blocklist_is_empty(NewList) 221: end). 222: 223: invalid_block_request(Config) -> 224: escalus:fresh_story( 225: Config, [{alice, 1}], 226: fun(User1) -> 227: St = block_users_stanza([]), 228: escalus_client:send(User1, St), 229: privacy_helper:gets_error(User1, <<"modify">>, <<"bad-request">>) 230: end). 231: 232: messages_from_blocked_user_dont_arrive(Config) -> 233: escalus:fresh_story( 234: Config, [{alice, 1}, {bob, 1}], 235: fun(User1, User2) -> 236: user_blocks(User1, [User2]), 237: message(User2, User1, <<"Hi!">>), 238: ct:sleep(100), 239: escalus_assert:has_no_stanzas(User1), 240: privacy_helper:gets_error(User2, <<"cancel">>, <<"service-unavailable">>) 241: end). 242: 243: messages_from_unblocked_user_arrive_again(Config) -> 244: escalus:fresh_story( 245: Config, [{alice, 1}, {bob, 1}], 246: fun(User1, User2) -> 247: %% given 248: user_blocks(User1, [User2]), 249: %% when 250: user_unblocks(User1, User2), 251: %% then 252: message_is_delivered(User2, User1, <<"Hello again!">>) 253: end). 254: 255: messages_from_any_blocked_resource_dont_arrive(Config) -> 256: escalus:fresh_story( 257: Config, [{alice, 3}, {bob, 1}], 258: fun(User1a, User1b, User1c, User2) -> 259: %% given 260: user_blocks(User2, [User1a]), 261: %% then 262: message_is_not_delivered(User1a, [User2], <<"roar!">>), 263: privacy_helper:gets_error(User1a, <<"cancel">>, <<"service-unavailable">>), 264: message_is_not_delivered(User1b, [User2], <<"woof!">>), 265: privacy_helper:gets_error(User1b, <<"cancel">>, <<"service-unavailable">>), 266: message_is_not_delivered(User1c, [User2], <<"grrr!">>), 267: privacy_helper:gets_error(User1c, <<"cancel">>, <<"service-unavailable">>), 268: ct:sleep(100), 269: escalus_assert:has_no_stanzas(User2) 270: end). 271: 272: blocking_doesnt_interfere(Config) -> 273: escalus:fresh_story( 274: Config, [{alice, 1}, {bob, 1}, {kate, 1}], 275: fun(User1, User2, User3) -> 276: %% given 277: user_blocks(User1, [User2]), 278: %% then 279: message_is_not_delivered(User2, [User1], <<"!@#@$@#$%">>), 280: privacy_helper:gets_error(User2, <<"cancel">>, <<"service-unavailable">>), 281: message_is_delivered(User3, [User1], <<"Ni hao.">>) 282: end). 283: 284: blocking_propagates_to_resources(Config) -> 285: escalus:fresh_story( 286: Config, [{alice, 2}, {bob, 1}], 287: fun(User1a, User1b, User2) -> 288: %% given 289: user_blocks(User1a, [User2]), 290: %% then 291: client_gets_block_iq(User1b), 292: % Alice can't send from any of her resources 293: message_is_not_delivered(User1a, [User2], <<"roar!">>), 294: client_gets_blocking_error(User1a), 295: message_is_not_delivered(User1b, [User2], <<"woof!">>), 296: client_gets_blocking_error(User1b), 297: % Bob can't send to any of Alice's resources 298: message_is_not_delivered(User2, [User1a], <<"hau!">>), 299: privacy_helper:gets_error(User2, <<"cancel">>, <<"service-unavailable">>), 300: message_is_not_delivered(User2, [User1b], <<"miau!">>), 301: privacy_helper:gets_error(User2, <<"cancel">>, <<"service-unavailable">>) 302: end). 303: 304: iq_reply_doesnt_crash_user_process(Config) -> 305: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 306: 307: QueryWithBlockingNS = escalus_stanza:query_el(?NS_BLOCKING, []), 308: %% Send IQ reply with blocking ns 309: %% Send message to check user process still alive 310: privacy_helper:does_user_process_crash(Alice, 311: Bob, 312: <<"error">>, 313: QueryWithBlockingNS, 314: <<"Hello, Bob">>), 315: 316: privacy_helper:does_user_process_crash(Bob, 317: Alice, 318: <<"result">>, 319: QueryWithBlockingNS, 320: <<"Hello, Alice">>) 321: end). 322: 323: messages_after_relogin(Config) -> 324: %% given 325: escalus:story( 326: Config, [{alice, 1}, {bob, 1}], 327: fun(User1, User2) -> 328: user_blocks(User1, [User2]) 329: end), 330: %% XXX Because alice can receive presence unavalable from alice 331: %% XXX It's a potential bug, please test it. 332: %% XXX has_stanzas_but_shouldnt 333: %% XXX reported as https://github.com/esl/MongooseIM/issues/1799 334: mongoose_helper:kick_everyone(), 335: escalus:story( 336: Config, [{alice, 1}, {bob, 1}], 337: fun(User1, User2) -> 338: message_is_not_delivered(User2, [User1], <<"Hey alice, are you there?">>), 339: message_is_delivered(User1, [User1], <<"Hey bob, carpe diem!">>) 340: end). 341: 342: messages_arrive_after_unblock_and_relogin(Config) -> 343: %% given when 344: escalus:story( 345: Config, [{alice, 1}, {bob, 1}], 346: fun(User1, User2) -> 347: user_unblocks(User1, [User2]) 348: end), 349: %% then 350: escalus:story( 351: Config, [{alice, 1}, {bob, 1}], 352: fun(User1, User2) -> 353: message_is_delivered(User2, [User1], <<"Hey bob, are you there?">>) 354: end). 355: 356: blocking_and_relogin_many(Config) -> 357: %% given 358: simple_story(Config, 359: fun(User1, User2, User3, User4, _) -> 360: user_blocks(User1, [User2, User3]), 361: user_blocks(User1, [User3, User4]) 362: end), 363: %% when 364: simple_story(Config, 365: fun(User1, User2, _, User4, User5) -> 366: user_unblocks(User1, [User4]), 367: user_unblocks(User1, [User4, User5]), 368: user_unblocks(User1, [User2, User5]) 369: end), 370: %% then 371: simple_story(Config, 372: fun(User1, User2, User3, User4, _) -> 373: message_is_delivered(User1, [User4], <<"Under the bridge!">>), 374: message_is_not_delivered(User1, [User3], <<"Cant stop">>), 375: client_gets_blocking_error(User1), 376: message_is_delivered(User1, [User2], <<"House of th rising sun">>), 377: BlockList = get_blocklist(User1), 378: blocklist_contains_jid(BlockList, User3) 379: end). 380: 381: simple_story(Config, Fun) -> 382: escalus:story( 383: Config, [{alice, 1}, {bob, 1}, {kate, 1}, {mike, 1}, {john, 1}], 384: Fun 385: ). 386: 387: clear_list_relogin(Config) -> 388: %% unexpected presence unavailable 389: mongoose_helper:kick_everyone(), 390: escalus:story( 391: Config, [{alice, 1}, {bob, 1}], 392: fun(User1, User2) -> 393: user_blocks(User1, [User2]) 394: end), 395: escalus:story( 396: Config, [{alice, 1}], 397: fun(User1) -> 398: user_unblocks_all(User1) 399: end), 400: escalus:story( 401: Config, [{alice, 1}, {bob, 1}], 402: fun(User1, User2) -> 403: message_is_delivered(User1, [User2], <<"Doom and gloom!">>) 404: end). 405: 406: blocker_cant_send_to_blockee(Config) -> 407: escalus:fresh_story( 408: Config, [{alice, 1}, {bob, 1}], 409: fun(User1, User2) -> 410: user_blocks(User1, [User2]), 411: message(User1, User2, <<"I'm not talking to you!">>), 412: client_gets_blocking_error(User1) 413: end). 414: 415: block_push_sent(Config) -> 416: %% make sure privacy list push arrives to all the user's resources 417: escalus:fresh_story( 418: Config, [{alice, 2}, {bob, 2}], 419: fun(User1a, User1b, User2a, _User2b) -> 420: user_blocks(User1a, [User2a]), 421: client_gets_block_iq(User1b) 422: end). 423: 424: notify_blockee(Config) -> 425: %% as XEP-0191 says, when we block a user he should receive 'unavailable', and a contrario. 426: escalus:fresh_story( 427: Config, [{alice, 1}, {bob, 1}], 428: fun(Alice, Bob) -> 429: %% make sure they're friends and Bob receives Alice's presences 430: subscribe(Bob, Alice), 431: escalus:send(Alice, escalus_stanza:presence(<<"available">>)), 432: escalus:assert(is_presence_with_type, [<<"available">>], 433: escalus:wait_for_stanza(Alice)), 434: escalus:assert(is_presence_with_type, [<<"available">>], 435: escalus:wait_for_stanza(Bob)), 436: user_blocks(Alice, [Bob]), 437: escalus:assert(is_presence_with_type, [<<"unavailable">>], 438: escalus:wait_for_stanza(Bob)), 439: user_unblocks(Alice, [Bob]), 440: escalus:assert(is_presence_with_type, [<<"available">>], 441: escalus:wait_for_stanza(Bob)) 442: end). 443: 444: %% common 445: 446: %% 447: get_blocklist(User) -> 448: IQGet = get_blocklist_stanza(), 449: escalus_client:send(User, IQGet), 450: escalus_client:wait_for_stanza(User). 451: 452: %% 453: %% stanza generators 454: %% 455: 456: get_blocklist_stanza() -> 457: Payload = #xmlel{name = <<"blocklist">>, 458: attrs=[{<<"xmlns">>, ?NS_BLOCKING}]}, 459: #xmlel{name = <<"iq">>, 460: attrs = [{<<"type">>, <<"get">>}], 461: children = [Payload]}. 462: 463: block_users_stanza(UsersToBlock) -> 464: Childs = [item_el(U) || U <- UsersToBlock], 465: Payload = #xmlel{name = <<"block">>, 466: attrs=[{<<"xmlns">>, ?NS_BLOCKING}], 467: children = Childs 468: }, 469: #xmlel{name = <<"iq">>, 470: attrs = [{<<"type">>, <<"set">>}], 471: children = [Payload]}. 472: 473: block_users_stanza_with_white_spaces(UsersToBlock) -> 474: Childs = [item_el(U) || U <- UsersToBlock], 475: % when client adds some white characters in blocking list 476: WhiteSpacedChilds = Childs ++ [{xmlcdata, "\n"}], 477: Payload = #xmlel{name = <<"block">>, 478: attrs=[{<<"xmlns">>, ?NS_BLOCKING}], 479: children = WhiteSpacedChilds 480: }, 481: #xmlel{name = <<"iq">>, 482: attrs = [{<<"type">>, <<"set">>}], 483: children = [Payload]}. 484: 485: 486: %%block_user_stanza(UserToBlock) -> 487: %% Payload = #xmlel{name = <<"block">>, 488: %% attrs=[{<<"xmlns">>, ?NS_BLOCKING}], 489: %% children = [item_el(UserToBlock)] 490: %% }, 491: %% #xmlel{name = <<"iq">>, 492: %% attrs = [{<<"type">>, <<"set">>}], 493: %% children = Payload}. 494: 495: unblock_user_stanza(UserToUnblock) -> 496: Payload = #xmlel{name = <<"unblock">>, 497: attrs=[{<<"xmlns">>, ?NS_BLOCKING}], 498: children = [item_el(UserToUnblock)] 499: }, 500: #xmlel{name = <<"iq">>, 501: attrs = [{<<"type">>, <<"set">>}], 502: children = [Payload]}. 503: 504: unblock_users_stanza(UsersToBlock) -> 505: Childs = [item_el(U) || U <- UsersToBlock], 506: Payload = #xmlel{name = <<"unblock">>, 507: attrs=[{<<"xmlns">>, ?NS_BLOCKING}], 508: children = Childs 509: }, 510: #xmlel{name = <<"iq">>, 511: attrs = [{<<"type">>, <<"set">>}], 512: children = [Payload]}. 513: 514: unblock_all_stanza() -> 515: Payload = #xmlel{name = <<"unblock">>, 516: attrs=[{<<"xmlns">>, ?NS_BLOCKING}], 517: children = [] 518: }, 519: #xmlel{name = <<"iq">>, 520: attrs = [{<<"type">>, <<"set">>}], 521: children = [Payload]}. 522: 523: item_el(User) when is_binary(User) -> 524: #xmlel{name = <<"item">>, 525: attrs = [{<<"jid">>, User}]}. 526: %% 527: %% predicates 528: %% 529: 530: is_xep191_not_available(#xmlel{} = Stanza) -> 531: ErrorEl = exml_query:subelement(Stanza, <<"error">>), 532: <<"error">> == exml_query:attr(Stanza, <<"type">>) 533: andalso 534: undefined =/= exml_query:subelement(ErrorEl, <<"not-acceptable">>) 535: andalso 536: undefined =/= exml_query:subelement(ErrorEl, <<"blocked">>) 537: andalso 538: <<"urn:xmpp:blocking:errors">> == 539: exml_query:path(ErrorEl, [{element, <<"blocked">>}, 540: {attr, <<"xmlns">>}]). 541: 542: 543: is_blocklist_result_empty(#xmlel{children = [#xmlel{name =Name, 544: attrs = Attrs, 545: children= Child}]} = Stanza) -> 546: true = escalus_pred:is_iq(Stanza), 547: <<"blocklist">> = Name, 548: {<<"xmlns">>, ?NS_BLOCKING} = lists:keyfind(<<"xmlns">>, 1, Attrs), 549: [] = Child, 550: true. 551: 552: blocklist_result_has(ExpectedUser, Stanza) -> 553: true = escalus_pred:is_iq(Stanza), 554: Blocklist = hd(Stanza#xmlel.children), 555: Attrs = Blocklist#xmlel.attrs, 556: Children = Blocklist#xmlel.children, 557: <<"blocklist">> = Blocklist#xmlel.name, 558: {<<"xmlns">>, ?NS_BLOCKING} = lists:keyfind(<<"xmlns">>, 1, Attrs), 559: true == lists:member(ExpectedUser, get_blocklist_items(Children)). 560: 561: is_xep191_push(Type, #xmlel{attrs = A, children = [#xmlel{name = Type, 562: attrs = Attrs}]}=Stanza) -> 563: true = escalus_pred:is_iq_set(Stanza), 564: {<<"id">>, <<"push">>} = lists:keyfind(<<"id">>, 1, A), 565: {<<"xmlns">>, ?NS_BLOCKING} = lists:keyfind(<<"xmlns">>, 1, Attrs), 566: true. 567: 568: is_xep191_push(Type, [], #xmlel{children = [#xmlel{name = Type, children = []}]}=Stanza) -> 569: is_xep191_push(Type, Stanza); 570: is_xep191_push(Type, [], #xmlel{children = [#xmlel{name = Type, children = _}]}) -> 571: false; 572: is_xep191_push(Type, JIDs, #xmlel{attrs = _, children = [#xmlel{name = Type, 573: attrs = Attrs, children = Items}]}=Stanza) -> 574: true = escalus_pred:is_iq_set(Stanza), 575: {<<"xmlns">>, ?NS_BLOCKING} = lists:keyfind(<<"xmlns">>, 1, Attrs), 576: F = fun(El) -> 577: #xmlel{name = <<"item">>, attrs = [{<<"jid">>, Value}]} = El, 578: lists:member(Value, JIDs) 579: end, 580: TrueList = lists:map(F, Items), 581: lists:all(fun(El) -> El end, TrueList); 582: is_xep191_push(_, _, _) -> 583: false. 584: 585: %% 586: %% helpers 587: %% 588: 589: bare(C) -> escalus_utils:jid_to_lower(escalus_client:short_jid(C)). 590: 591: get_blocklist_items(Items) -> 592: lists:map(fun(#xmlel{name = <<"item">>, attrs=A}) -> 593: {_, R} = lists:keyfind(<<"jid">>, 1, A), 594: R 595: end, Items). 596: 597: user_blocks(Blocker, Blockees) when is_list(Blockees) -> 598: BlockeeJIDs = [ escalus_utils:jid_to_lower(escalus_client:short_jid(B)) || B <- Blockees ], 599: AddStanza = block_users_stanza(BlockeeJIDs), 600: escalus_client:send(Blocker, AddStanza), 601: Res = escalus:wait_for_stanzas(Blocker, 2), 602: CheckPush = fun(E) -> is_xep191_push(<<"block">>, BlockeeJIDs, E) end, 603: Preds = [is_iq_result, CheckPush], 604: escalus:assert_many(Preds, Res). 605: 606: blocklist_is_empty(BlockList) -> 607: escalus:assert(is_iq_result, BlockList), 608: escalus:assert(fun is_blocklist_result_empty/1, BlockList). 609: 610: blocklist_contains_jid(BlockList, Client) -> 611: JID = escalus_utils:jid_to_lower(escalus_client:short_jid(Client)), 612: escalus:assert(fun blocklist_result_has/2, [JID], BlockList). 613: 614: user_unblocks(Unblocker, Unblockees) when is_list(Unblockees) -> 615: UnblockeeJIDs = [ escalus_utils:jid_to_lower(escalus_client:short_jid(B)) || B <- Unblockees ], 616: AddStanza = unblock_users_stanza(UnblockeeJIDs), 617: escalus_client:send(Unblocker, AddStanza), 618: Res = escalus:wait_for_stanzas(Unblocker, 2), 619: CheckPush = fun(E) -> is_xep191_push(<<"unblock">>, UnblockeeJIDs, E) end, 620: Preds = [is_iq_result, CheckPush], 621: escalus:assert_many(Preds, Res); 622: user_unblocks(Unblocker, Unblockee) -> 623: JID = escalus_utils:jid_to_lower(escalus_client:short_jid(Unblockee)), 624: escalus_client:send(Unblocker, unblock_user_stanza(JID)), 625: user_gets_remove_result(Unblocker, [JID]). 626: 627: blocklist_doesnt_contain_jid(BlockList, Client) -> 628: JID = escalus_utils:jid_to_lower(escalus_client:short_jid(Client)), 629: escalus:assert(is_iq_result, BlockList), 630: ?assertNot(blocklist_result_has(JID, BlockList)). 631: 632: user_gets_remove_result(Client, ContactList) -> 633: RemoveResult = escalus:wait_for_stanzas(Client, 2), 634: CheckPush = fun(E) -> is_xep191_push(<<"unblock">>, ContactList, E) end, 635: Preds = [is_iq_result, CheckPush], 636: escalus:assert_many(Preds, RemoveResult). 637: 638: 639: user_unblocks_all(User) -> 640: escalus_client:send(User, unblock_all_stanza()), 641: user_gets_remove_result(User, []). 642: 643: message(From, To, MsgTxt) -> 644: escalus_client:send(From, escalus_stanza:chat_to(To, MsgTxt)). 645: 646: message_is_delivered(From, [To|_] = Tos, MessageText) -> 647: BareTo = escalus_utils:jid_to_lower(escalus_client:short_jid(To)), 648: escalus:send(From, escalus_stanza:chat_to(BareTo, MessageText)), 649: [ escalus:assert(is_chat_message, [MessageText], escalus:wait_for_stanza(C)) || 650: C <- Tos ]; 651: message_is_delivered(From, To, MessageText) -> 652: BareTo = escalus_utils:jid_to_lower(escalus_client:short_jid(To)), 653: escalus:send(From, escalus_stanza:chat_to(BareTo, MessageText)), 654: escalus:assert(is_chat_message, [MessageText], escalus:wait_for_stanza(To)). 655: 656: message_is_not_delivered(From, [To|_] = Tos, MessageText) -> 657: BareTo = escalus_utils:jid_to_lower(escalus_client:short_jid(To)), 658: escalus:send(From, escalus_stanza:chat_to(BareTo, MessageText)), 659: clients_have_no_messages(Tos). 660: 661: clients_have_no_messages(Cs) when is_list (Cs) -> [ client_has_no_messages(C) || C <- Cs ]. 662: 663: client_has_no_messages(C) -> escalus_assert:has_no_stanzas(C). 664: 665: client_gets_blocking_error(C) -> 666: Stanza = escalus_client:wait_for_stanza(C), 667: escalus:assert(fun is_xep191_not_available/1, [], Stanza). 668: 669: client_gets_block_iq(C) -> 670: escalus:assert(fun is_xep191_push/2, [<<"block">>], escalus:wait_for_stanza(C)). 671: 672: flush(User) -> 673: escalus:wait_for_stanzas(User, 10, 100). 674: 675: add_sample_contact(Alice, Bob) -> 676: escalus:send(Alice, escalus_stanza:roster_add_contact(Bob, 677: [<<"friends">>], 678: <<"Bobby">>)), 679: 680: Received = escalus:wait_for_stanzas(Alice, 2), 681: escalus:assert_many([is_roster_set, is_iq_result], Received), 682: 683: Result = hd([R || R <- Received, escalus_pred:is_roster_set(R)]), 684: escalus:assert(count_roster_items, [1], Result), 685: escalus:send(Alice, escalus_stanza:iq_result(Result)). 686: 687: 688: subscribe(Bob, Alice) -> 689: %% Bob adds Alice as a contact 690: add_sample_contact(Bob, Alice), 691: %% He subscribes to her presences 692: escalus:send(Bob, escalus_stanza:presence_direct(alice, <<"subscribe">>)), 693: PushReq = escalus:wait_for_stanza(Bob), 694: escalus:assert(is_roster_set, PushReq), 695: escalus:send(Bob, escalus_stanza:iq_result(PushReq)), 696: %% Alice receives subscription request 697: Received = escalus:wait_for_stanza(Alice), 698: escalus:assert(is_presence_with_type, [<<"subscribe">>], Received), 699: %% Alice adds new contact to his roster 700: escalus:send(Alice, escalus_stanza:roster_add_contact(Bob, 701: [<<"enemies">>], 702: <<"Bob">>)), 703: PushReqB = escalus:wait_for_stanza(Alice), 704: escalus:assert(is_roster_set, PushReqB), 705: escalus:send(Alice, escalus_stanza:iq_result(PushReqB)), 706: escalus:assert(is_iq_result, escalus:wait_for_stanza(Alice)), 707: %% Alice sends subscribed presence 708: escalus:send(Alice, escalus_stanza:presence_direct(bob, <<"subscribed">>)), 709: %% Bob receives subscribed 710: Stanzas = escalus:wait_for_stanzas(Bob, 2), 711: check_subscription_stanzas(Stanzas, <<"subscribed">>), 712: escalus:assert(is_presence, escalus:wait_for_stanza(Bob)), 713: %% Alice receives roster push 714: PushReqB1 = escalus:wait_for_stanza(Alice), 715: escalus:assert(is_roster_set, PushReqB1), 716: %% Alice sends presence 717: escalus:send(Alice, escalus_stanza:presence(<<"available">>)), 718: escalus:assert(is_presence, escalus:wait_for_stanza(Bob)), 719: escalus:assert(is_presence, escalus:wait_for_stanza(Alice)), 720: ok. 721: 722: 723: check_subscription_stanzas(Stanzas, Type) -> 724: IsPresWithType = fun(S) -> escalus_pred:is_presence_with_type(Type, S) end, 725: escalus:assert_many([is_roster_set, IsPresWithType], Stanzas).