1: -module(domain_isolation_SUITE). 2: 3: -include_lib("common_test/include/ct.hrl"). 4: -include_lib("eunit/include/eunit.hrl"). 5: 6: -compile([export_all, nowarn_export_all]). 7: -import(distributed_helper, [mim/0, require_rpc_nodes/1, rpc/4, subhost_pattern/1]). 8: -import(domain_helper, [host_type/0, secondary_host_type/0]). 9: 10: suite() -> 11: require_rpc_nodes([mim]). 12: 13: all() -> 14: [{group, two_domains}]. 15: 16: groups() -> 17: [{two_domains, [parallel], cases()}]. 18: 19: cases() -> 20: [routing_one2one_message_inside_one_domain_works, 21: routing_one2one_message_to_another_domain_gets_dropped, 22: routing_one2one_message_to_another_domain_results_in_service_unavailable, 23: routing_to_yours_subdomain_gets_passed_to_muc_module, 24: routing_to_foreign_subdomain_results_in_service_unavailable]. 25: 26: host_types() -> 27: %% This suite tests domain isolation. 28: %% But two domains could be on the same host type, and still should be isolated. 29: %% So, we could need to init modules only once. 30: lists:usort([host_type(), secondary_host_type()]). 31: 32: %%-------------------------------------------------------------------- 33: %% Init & teardown 34: %%-------------------------------------------------------------------- 35: 36: init_per_suite(Config) -> 37: escalus:init_per_suite(Config). 38: 39: end_per_suite(Config) -> 40: escalus:end_per_suite(Config). 41: 42: modules() -> 43: MucHost = subhost_pattern(muc_helper:muc_host_pattern()), 44: [{mod_domain_isolation, []}, 45: {mod_muc_light, [{host, MucHost}]}]. 46: 47: init_per_group(two_domains, Config) -> 48: Config2 = dynamic_modules:save_modules(host_types(), Config), 49: [dynamic_modules:ensure_modules(HostType, modules()) || HostType <- host_types()], 50: Config2. 51: 52: end_per_group(two_domains, Config) -> 53: escalus_fresh:clean(), 54: dynamic_modules:restore_modules(Config), 55: Config. 56: 57: init_per_testcase(Testcase, Config) -> 58: escalus:init_per_testcase(Testcase, Config). 59: 60: end_per_testcase(Testcase, Config) -> 61: escalus:end_per_testcase(Testcase, Config). 62: 63: %%-------------------------------------------------------------------- 64: %% Tests 65: %%-------------------------------------------------------------------- 66: 67: routing_one2one_message_inside_one_domain_works(Config) -> 68: F = fun(Alice, Bob) -> 69: %% WHEN Routed inside the same domain 70: escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Hello">>)), 71: %% THEN Message gets delivered 72: Stanza = escalus:wait_for_stanza(Alice), 73: escalus:assert(is_chat_message, [<<"Hello">>], Stanza) 74: end, 75: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], F). 76: 77: routing_one2one_message_to_another_domain_gets_dropped(Config) -> 78: F = fun(Alice, Bob, Bis) -> 79: %% GIVEN Alice and Bis are on different domains 80: %% WHEN A stanza is sent to another domain 81: escalus_client:send(Bis, escalus_stanza:chat_to(Alice, <<"Hello">>)), 82: %% THEN Receiver does not receive a message 83: verify_alice_has_no_pending_messages(Alice, Bob) 84: end, 85: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}, {alice_bis, 1}], F). 86: 87: routing_one2one_message_to_another_domain_results_in_service_unavailable(Config) -> 88: F = fun(Alice, Bis) -> 89: %% GIVEN Alice and Bis are on different domains 90: %% WHEN A stanza is sent to another domain 91: escalus_client:send(Bis, escalus_stanza:chat_to(Alice, <<"Hello">>)), 92: %% THEN Sender receives an error 93: receives_service_unavailable(Bis) 94: end, 95: escalus:fresh_story(Config, [{alice, 1}, {alice_bis, 1}], F). 96: 97: routing_to_yours_subdomain_gets_passed_to_muc_module(Config) -> 98: F = fun(Alice) -> 99: %% GIVEN Alice is on the same domain 100: %% WHEN Alice routes a stanza 101: escalus_client:send(Alice, invalid_muc_stanza()), 102: %% THEN Alice receives an error from mod_muc, 103: %% like if there is no mod_domain_isolation. 104: receives_muc_bad_request(Alice) 105: end, 106: escalus:fresh_story(Config, [{alice, 1}], F). 107: 108: routing_to_foreign_subdomain_results_in_service_unavailable(Config) -> 109: F = fun(Alice) -> 110: %% GIVEN Alice is on another domain 111: %% WHEN Alice routes a stanza 112: escalus_client:send(Alice, invalid_muc_stanza()), 113: %% THEN Sender receives an error about the drop 114: receives_service_unavailable(Alice) 115: end, 116: escalus:fresh_story(Config, [{alice_bis, 1}], F). 117: 118: %%-------------------------------------------------------------------- 119: %% Helpers 120: %%-------------------------------------------------------------------- 121: 122: get_error_text(Err) -> 123: exml_query:path(Err, [{element, <<"error">>}, {element, <<"text">>}, cdata]). 124: 125: invalid_muc_address() -> 126: MucHost = muc_helper:muc_host(), 127: <<MucHost/binary, "/wow_resource_not_so_empty">>. 128: 129: invalid_muc_stanza() -> 130: escalus_stanza:chat_to(invalid_muc_address(), <<"Hi muc!">>). 131: 132: receives_service_unavailable(Alice) -> 133: Err = escalus:wait_for_stanza(Alice), 134: escalus:assert(is_error, [<<"cancel">>, <<"service-unavailable">>], Err), 135: <<"Filtered by the domain isolation">> = get_error_text(Err). 136: 137: receives_muc_bad_request(Alice) -> 138: Err = escalus:wait_for_stanza(Alice), 139: escalus:assert(is_error, [<<"modify">>, <<"bad-request">>], Err), 140: %% This error is generated by mod_muc: 141: <<"Resource expected to be empty">> = get_error_text(Err). 142: 143: %% Verify than there is no unreceived messages by Alice by routing a message from Bob. 144: %% Bob should be able to send messages to Alice. 145: %% If the Bob's message gets received - there is no pending messages. 146: verify_alice_has_no_pending_messages(Alice, Bob) -> 147: escalus_client:send(Bob, escalus_stanza:chat_to(Alice, <<"Forces to flush">>)), 148: Stanza = escalus:wait_for_stanza(Alice), 149: escalus:assert(is_chat_message, [<<"Forces to flush">>], Stanza).