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