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