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