1: %%============================================================================== 2: %% Copyright 2014 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_global_distrib_SUITE). 18: -compile([export_all, nowarn_export_all]). 19: -author('piotr.nosek@erlang-solutions.com'). 20: 21: -include_lib("exml/include/exml.hrl"). 22: -include("mongoose.hrl"). 23: -include("jlib.hrl"). 24: 25: -import(config_parser_helper, [mod_config/2, config/2]). 26: 27: %%-------------------------------------------------------------------- 28: %% Suite configuration 29: %%-------------------------------------------------------------------- 30: 31: all() -> 32: [{group, hook_handlers}]. 33: 34: groups() -> 35: [ 36: {hook_handlers, [], hook_handlers_tests()} 37: ]. 38: 39: hook_handlers_tests() -> 40: [ 41: missing_struct_in_message_from_user, 42: missing_struct_in_message_from_component 43: ]. 44: 45: suite() -> 46: []. 47: 48: %%-------------------------------------------------------------------- 49: %% Init & teardown 50: %%-------------------------------------------------------------------- 51: 52: init_per_suite(Config) -> 53: {ok, _} = application:ensure_all_started(jid), 54: {ok, _} = application:ensure_all_started(cache_tab), 55: Config. 56: 57: end_per_suite(Config) -> 58: Config. 59: 60: init_per_group(_GroupName, Config) -> 61: Config. 62: 63: end_per_group(_GroupName, Config) -> 64: Config. 65: 66: init_per_testcase(_CaseName, Config) -> 67: set_meck(), 68: [mongoose_config:set_opt(Key, Value) || {Key, Value} <- opts()], 69: mongoose_domain_api:init(), 70: mim_ct_sup:start_link(ejabberd_sup), 71: gen_hook:start_link(), 72: mongoose_modules:start(), 73: Config. 74: 75: end_per_testcase(_CaseName, Config) -> 76: mongoose_modules:stop(), 77: mongoose_domain_api:stop(), 78: [mongoose_config:unset_opt(Key) || {Key, _Value} <- opts()], 79: unset_meck(), 80: Config. 81: 82: opts() -> 83: [{hosts, hosts()}, 84: {host_types, []}, 85: {all_metrics_are_global, false} | 86: [{{modules, HostType}, modules(HostType)} || HostType <- hosts()]]. 87: 88: hosts() -> 89: [global_host(), local_host()]. 90: 91: modules(HostType) -> 92: gen_mod_deps:resolve_deps(HostType, #{mod_global_distrib => module_opts()}). 93: 94: module_opts() -> 95: mod_config(mod_global_distrib, #{global_host => global_host(), 96: local_host => local_host(), 97: connections => connection_opts()}). 98: 99: connection_opts() -> 100: config([modules, mod_global_distrib, connections], 101: #{endpoints => [], 102: resolved_endpoints => [], 103: advertised_endpoints => []}). 104: 105: %%-------------------------------------------------------------------- 106: %% Hook handlers tests 107: %%-------------------------------------------------------------------- 108: 109: 110: %% missing_struct_ tests verify the behaviour of packet_to_component handler, 111: %% which is supposed to update the mapping of the sender in Redis and cache. 112: %% In case of routing between nodes in single cluster AND routers being reordered 113: %% with component routers at the beginning of the chain, this hook must not fail 114: %% despite lack of global_distrib structure in Acc. 115: missing_struct_in_message_from_user(_Config) -> 116: From = jid:make(<<"user">>, global_host(), <<"resource">>), 117: {Acc, To} = fake_acc_to_component(From), 118: % The handler must not crash and return unchanged Acc 119: Acc = mod_global_distrib_mapping:packet_to_component(Acc, From, To). 120: 121: %% Update logic has two separate paths: when a packet is sent by a user or by another 122: %% component. This test covers the latter. 123: missing_struct_in_message_from_component(_Config) -> 124: From = jid:make(<<"">>, <<"from_service.", (global_host())/binary>>, <<"">>), 125: {Acc, To} = fake_acc_to_component(From), 126: % The handler must not crash and return unchanged Acc 127: Acc = mod_global_distrib_mapping:packet_to_component(Acc, From, To). 128: 129: %%-------------------------------------------------------------------- 130: %% Helpers 131: %%-------------------------------------------------------------------- 132: 133: global_host() -> 134: <<"localhost">>. 135: 136: local_host() -> 137: <<"localhost.bis">>. 138: 139: -spec fake_acc_to_component(From :: jid:jid()) -> {Acc :: mongoose_acc:t(), To :: jid:jid()}. 140: fake_acc_to_component(From) -> 141: To = jid:make(<<"">>, <<"to_service.localhost">>, <<"">>), 142: FromBin = jid:to_binary(From), 143: ToBin = jid:to_binary(To), 144: BodyEl = #xmlel{ 145: name = <<"body">>, 146: children = [#xmlcdata{ content = <<"hooks test">> }] 147: }, 148: Packet = #xmlel{ 149: name = <<"message">>, 150: attrs = [{<<"from">>, FromBin}, {<<"to">>, ToBin}, {<<"type">>, <<"chat">>}], 151: children = [BodyEl] 152: }, 153: {mongoose_acc:new(#{ location => ?LOCATION, 154: lserver => From#jid.lserver, 155: host_type => From#jid.lserver, 156: element => Packet }), To}. 157: 158: %%-------------------------------------------------------------------- 159: %% Meck 160: %%-------------------------------------------------------------------- 161: 162: set_meck() -> 163: meck:new(mongoose_metrics, [stub_all]), 164: meck:new(mod_global_distrib_mapping_backend, [stub_all]), 165: %% Simulate missing entries and inserts into Redis 166: meck:expect(mod_global_distrib_mapping_backend, get_session, fun(_) -> error end), 167: meck:expect(mod_global_distrib_mapping_backend, get_domain, fun(_) -> error end). 168: 169: unset_meck() -> 170: meck:unload(mod_global_distrib_mapping_backend), 171: meck:unload(mongoose_metrics).