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_opts(opts()), 69: mongoose_domain_sup:start_link(), 70: mim_ct_sup:start_link(ejabberd_sup), 71: mongooseim_helper:start_link_loaded_hooks(), 72: mongoose_modules:start(), 73: Config. 74: 75: end_per_testcase(_CaseName, Config) -> 76: mongoose_modules:stop(), 77: mongoose_config:erase_opts(), 78: unset_meck(), 79: Config. 80: 81: opts() -> 82: maps:from_list([{hosts, hosts()}, 83: {host_types, []}, 84: {all_metrics_are_global, false} | 85: [{{modules, HostType}, modules(HostType)} || HostType <- hosts()]]). 86: 87: hosts() -> 88: [global_host(), local_host()]. 89: 90: modules(HostType) -> 91: gen_mod_deps:resolve_deps(HostType, #{mod_global_distrib => module_opts()}). 92: 93: module_opts() -> 94: mod_config(mod_global_distrib, #{global_host => global_host(), 95: local_host => local_host(), 96: connections => connection_opts()}). 97: 98: connection_opts() -> 99: config([modules, mod_global_distrib, connections], 100: #{endpoints => [], 101: resolved_endpoints => [], 102: advertised_endpoints => []}). 103: 104: %%-------------------------------------------------------------------- 105: %% Hook handlers tests 106: %%-------------------------------------------------------------------- 107: 108: 109: %% missing_struct_ tests verify the behaviour of packet_to_component handler, 110: %% which is supposed to update the mapping of the sender in Redis and cache. 111: %% In case of routing between nodes in single cluster AND routers being reordered 112: %% with component routers at the beginning of the chain, this hook must not fail 113: %% despite lack of global_distrib structure in Acc. 114: missing_struct_in_message_from_user(_Config) -> 115: From = jid:make(<<"user">>, global_host(), <<"resource">>), 116: {Acc, _To} = fake_acc_to_component(From), 117: % The handler must not crash and return unchanged Acc 118: {ok, Acc} = mod_global_distrib_mapping:packet_to_component(Acc, #{from => From}, #{}). 119: 120: %% Update logic has two separate paths: when a packet is sent by a user or by another 121: %% component. This test covers the latter. 122: missing_struct_in_message_from_component(_Config) -> 123: From = jid:make(<<"">>, <<"from_service.", (global_host())/binary>>, <<"">>), 124: {Acc, _To} = fake_acc_to_component(From), 125: % The handler must not crash and return unchanged Acc 126: {ok, Acc} = mod_global_distrib_mapping:packet_to_component(Acc, #{from => From}, #{}). 127: 128: %%-------------------------------------------------------------------- 129: %% Helpers 130: %%-------------------------------------------------------------------- 131: 132: global_host() -> 133: <<"localhost">>. 134: 135: local_host() -> 136: <<"localhost.bis">>. 137: 138: -spec fake_acc_to_component(From :: jid:jid()) -> {Acc :: mongoose_acc:t(), To :: jid:jid()}. 139: fake_acc_to_component(From) -> 140: To = jid:make(<<"">>, <<"to_service.localhost">>, <<"">>), 141: FromBin = jid:to_binary(From), 142: ToBin = jid:to_binary(To), 143: BodyEl = #xmlel{ 144: name = <<"body">>, 145: children = [#xmlcdata{ content = <<"hooks test">> }] 146: }, 147: Packet = #xmlel{ 148: name = <<"message">>, 149: attrs = [{<<"from">>, FromBin}, {<<"to">>, ToBin}, {<<"type">>, <<"chat">>}], 150: children = [BodyEl] 151: }, 152: {mongoose_acc:new(#{ location => ?LOCATION, 153: lserver => From#jid.lserver, 154: host_type => From#jid.lserver, 155: element => Packet }), To}. 156: 157: %%-------------------------------------------------------------------- 158: %% Meck 159: %%-------------------------------------------------------------------- 160: 161: set_meck() -> 162: meck:new(mongoose_metrics, [stub_all]), 163: meck:new(mod_global_distrib_mapping_backend, [stub_all]), 164: %% Simulate missing entries and inserts into Redis 165: meck:expect(mod_global_distrib_mapping_backend, get_session, fun(_) -> error end), 166: meck:expect(mod_global_distrib_mapping_backend, get_domain, fun(_) -> error end). 167: 168: unset_meck() -> 169: meck:unload(mod_global_distrib_mapping_backend), 170: meck:unload(mongoose_metrics).