1: -module(dynamic_domains_SUITE). 2: 3: -include_lib("exml/include/exml.hrl"). 4: 5: %% API 6: -compile([export_all, nowarn_export_all]). 7: -import(distributed_helper, [mim/0, mim2/0, rpc/4, 8: require_rpc_nodes/1, 9: subhost_pattern/1]). 10: 11: -define(TEST_NODES, [mim() | ?CLUSTER_NODES]). 12: -define(CLUSTER_NODES, [mim2()]). 13: -define(DOMAINS, [<<"example.com">>, <<"example.org">>]). 14: -define(HOST_TYPE, <<"dummy auth">>). %% preconfigured in the toml file 15: 16: suite() -> 17: require_rpc_nodes([mim, mim2]). 18: 19: all() -> 20: [can_authenticate, 21: pm_messages, 22: disconnected_on_domain_disabling, 23: auth_domain_removal_is_triggered_on_hook, 24: {group, with_mod_dynamic_domains_test}]. 25: 26: groups() -> 27: [{with_mod_dynamic_domains_test, [], [packet_handling_for_subdomain, 28: iq_handling_for_subdomain, 29: iq_handling_for_domain]}]. 30: 31: init_per_suite(Config0) -> 32: Config = cluster_nodes(?CLUSTER_NODES, Config0), 33: insert_domains(?TEST_NODES, ?DOMAINS), 34: escalus:init_per_suite(Config). 35: 36: end_per_suite(Config0) -> 37: Config = escalus:end_per_suite(Config0), 38: remove_domains(?TEST_NODES, ?DOMAINS), 39: uncluster_nodes(?CLUSTER_NODES, Config). 40: 41: init_per_group(with_mod_dynamic_domains_test, Config) -> 42: MockedModules = [mod_dynamic_domains_test, mongoose_router], 43: [ok = rpc(mim(), meck, new, [Module, [passthrough, no_link]]) 44: || Module <- MockedModules], 45: dynamic_modules:start(?HOST_TYPE, mod_dynamic_domains_test, 46: #{host1 => subhost_pattern("subdomain1.@HOST@"), 47: host2 => subhost_pattern("subdomain2.@HOST@"), 48: namespace => <<"dummy.namespace">>}), 49: [{reset_meck, MockedModules} | Config]; 50: init_per_group(_, Config) -> 51: Config. 52: 53: end_per_group(with_mod_dynamic_domains_test, Config) -> 54: dynamic_modules:stop(?HOST_TYPE, mod_dynamic_domains_test), 55: rpc(mim(), meck, unload, []), 56: Config; 57: end_per_group(_, Config) -> 58: Config. 59: 60: init_per_testcase(CN, Config) -> 61: Modules = proplists:get_value(reset_meck, Config, []), 62: [rpc(mim(), meck, reset, [M]) || M <- Modules], 63: escalus:init_per_testcase(CN, Config). 64: 65: end_per_testcase(CN, Config) -> 66: escalus:end_per_testcase(CN, Config). 67: 68: can_authenticate(Config) -> 69: UserSpecA = escalus_users:get_userspec(Config, alice3), 70: {ok, ClientA, _} = escalus_connection:start(UserSpecA), 71: UserSpecB = escalus_users:get_userspec(Config, bob3), 72: {ok, ClientB, _} = escalus_connection:start(UserSpecB), 73: escalus_connection:stop(ClientA), 74: escalus_connection:stop(ClientB). 75: 76: pm_messages(Config) -> 77: StoryFn = 78: fun(Alice, Bob) -> 79: escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"OH, HAI!">>)), 80: escalus:assert(is_chat_message, [<<"OH, HAI!">>], escalus:wait_for_stanza(Bob)), 81: escalus:send(Bob, escalus_stanza:chat_to(Alice, <<"Hello there!">>)), 82: escalus:assert(is_chat_message, [<<"Hello there!">>], escalus:wait_for_stanza(Alice)) 83: end, 84: escalus:story(Config, [{alice3, 1}, {bob3, 1}], StoryFn). 85: 86: disconnected_on_domain_disabling(Config) -> 87: StoryFn = 88: fun(Alice, Bob) -> 89: remove_domains(?TEST_NODES, ?DOMAINS), 90: escalus_connection:wait_for_close(Alice, timer:seconds(5)), 91: escalus_connection:wait_for_close(Bob, timer:seconds(5)), 92: insert_domains(?TEST_NODES, ?DOMAINS) 93: end, 94: escalus:story(Config, [{alice3, 1}, {bob3, 1}], StoryFn). 95: 96: auth_domain_removal_is_triggered_on_hook(_Config) -> 97: ok = rpc(mim(), meck, new, [ejabberd_auth_dummy, [passthrough, no_link]]), 98: Params = [?HOST_TYPE, <<"dummy.domain.name">>], 99: rpc(mim(), mongoose_hooks, remove_domain, Params), 100: 1 = rpc(mim(), meck, num_calls, [ejabberd_auth_dummy, remove_domain, Params]), 101: rpc(mim(), meck, unload, [ejabberd_auth_dummy]). 102: 103: packet_handling_for_subdomain(Config) -> 104: StoryFn = 105: fun(Alice) -> 106: NewDomain = <<"example.test">>, 107: insert_domains(?TEST_NODES, [NewDomain]), 108: Domains = [NewDomain | ?DOMAINS], 109: Subdomains = [<<"subdomain1.", Domain/binary>> || Domain <- Domains], 110: [NewSubdomain | _] = Subdomains, 111: [escalus:send(Alice, escalus_stanza:chat_to(Subdomain, <<"OH, HAI!">>)) 112: || Subdomain <- Subdomains], 113: rpc(mim(), meck, wait, [3, mod_dynamic_domains_test, process_packet, 5, 500]), 114: rpc(mim(), meck, reset, [mod_dynamic_domains_test]), 115: 116: QueryEl = escalus_stanza:query_el(<<"dummy.namespace">>, []), 117: [begin 118: IQ = escalus_stanza:iq(Subdomain, <<"get">>, [QueryEl]), 119: escalus:send(Alice, IQ) 120: end || Subdomain <- Subdomains], 121: %% check that all the IQs to any of Subdomains1 landed at process_packet/5 122: %% and no stanzas received in response 123: rpc(mim(), meck, wait, [3, mod_dynamic_domains_test, process_packet, 5, 500]), 124: 0 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_iq, 5]), 125: [] = escalus:wait_for_stanzas(Alice, 5, 500), 126: rpc(mim(), meck, reset, [mod_dynamic_domains_test]), 127: 128: %% check that subdomain is not served after the parent domain removal 129: remove_domains(?TEST_NODES, [NewDomain]), 130: rpc(mim(), meck, wait, [mongoose_router, unregister_route, [NewSubdomain], 500]), 131: IQ = escalus_stanza:iq(NewSubdomain, <<"get">>, [QueryEl]), 132: escalus:send(Alice, IQ), 133: Stanza = escalus:wait_for_stanza(Alice, 10000), 134: escalus:assert(is_error, [<<"cancel">>, <<"remote-server-not-found">>], Stanza), 135: 0 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_packet, 5]) 136: end, 137: escalus:story(Config, [{alice3, 1}], StoryFn). 138: 139: iq_handling_for_domain(Config) -> 140: StoryFn = 141: fun(Alice) -> 142: NewDomain = <<"example.test">>, 143: insert_domains(?TEST_NODES, [NewDomain]), 144: Domains = [NewDomain | ?DOMAINS], 145: QueryEl = escalus_stanza:query_el(<<"dummy.namespace">>, []), 146: [begin 147: IQ = escalus_stanza:iq(Domain, <<"get">>, [QueryEl]), 148: escalus:send_iq_and_wait_for_result(Alice, IQ) 149: end || Domain <- Domains], 150: 3 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_iq, 5]), 151: 0 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_packet, 5]), 152: %% check that process_iq/5 is called from one and the same worker process 153: History = rpc(mim(), meck, history, [mod_dynamic_domains_test]), 154: rpc(mim(), meck, reset, [mod_dynamic_domains_test]), 155: Pids = [Pid || {Pid, {_, process_iq, _}, _} <- History], 156: [_] = (lists:usort(Pids)), 157: 158: %% check that domain is not served removal 159: remove_domains(?TEST_NODES, [NewDomain]), 160: rpc(mim(), meck, wait, [mongoose_router, unregister_route, [NewDomain], 500]), 161: IQ = escalus_stanza:iq(NewDomain, <<"get">>, [QueryEl]), 162: escalus:send(Alice, IQ), 163: Stanza = escalus:wait_for_stanza(Alice, 10000), 164: escalus:assert(is_error, [<<"cancel">>, <<"remote-server-not-found">>], Stanza), 165: 0 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_iq, 5]) 166: end, 167: escalus:story(Config, [{alice3, 1}], StoryFn). 168: 169: iq_handling_for_subdomain(Config) -> 170: StoryFn = 171: fun(Alice) -> 172: NewDomain = <<"example.test">>, 173: insert_domains(?TEST_NODES, [NewDomain]), 174: Domains = [NewDomain | ?DOMAINS], 175: Subdomains = [<<"subdomain2.", Domain/binary>> || Domain <- Domains], 176: [NewSubdomain | _] = Subdomains, 177: QueryEl = escalus_stanza:query_el(<<"dummy.namespace">>, []), 178: [begin 179: IQ = escalus_stanza:iq(Subdomain, <<"get">>, [QueryEl]), 180: escalus:send_iq_and_wait_for_result(Alice, IQ) 181: end || Subdomain <- Subdomains], 182: 3 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_iq, 5]), 183: 0 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_packet, 5]), 184: %% check that process_iq/5 is called from one and the same worker process 185: History = rpc(mim(), meck, history, [mod_dynamic_domains_test]), 186: rpc(mim(), meck, reset, [mod_dynamic_domains_test]), 187: Pids = [Pid || {Pid, {_, process_iq, _}, _} <- History], 188: [_] = (lists:usort(Pids)), 189: 190: %% check that subdomain is not served after the parent domain removal 191: remove_domains(?TEST_NODES, [NewDomain]), 192: rpc(mim(), meck, wait, [mongoose_router, unregister_route, [NewSubdomain], 500]), 193: IQ = escalus_stanza:iq(NewSubdomain, <<"get">>, [QueryEl]), 194: escalus:send(Alice, IQ), 195: Stanza = escalus:wait_for_stanza(Alice, 10000), 196: escalus:assert(is_error, [<<"cancel">>, <<"remote-server-not-found">>], Stanza), 197: 0 = rpc(mim(), meck, num_calls, [mod_dynamic_domains_test, process_iq, 5]) 198: end, 199: escalus:story(Config, [{alice3, 1}], StoryFn). 200: 201: %% helper functions 202: insert_domains(Nodes, Domains) -> 203: [domain_helper:insert_domain(Node, Domain, ?HOST_TYPE) || Node <- Nodes, Domain <- Domains]. 204: 205: remove_domains(Nodes, Domains) -> 206: [domain_helper:delete_domain(Node, Domain) || Node <- Nodes, Domain <- Domains]. 207: 208: cluster_nodes([], Config) -> Config; 209: cluster_nodes([Node | T], Config) -> 210: NewConfig = distributed_helper:add_node_to_cluster(Node, Config), 211: cluster_nodes(T, NewConfig). 212: 213: uncluster_nodes([], Config) -> Config; 214: uncluster_nodes([Node | T], Config) -> 215: NewConfig = distributed_helper:remove_node_from_cluster(Node, Config), 216: cluster_nodes(T, NewConfig).