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("common_test/include/ct.hrl"). 22: -include_lib("exml/include/exml.hrl"). 23: -include("mongoose.hrl"). 24: -include("jlib.hrl"). 25: 26: %%-------------------------------------------------------------------- 27: %% Suite configuration 28: %%-------------------------------------------------------------------- 29: 30: all() -> 31: [{group, hook_handlers}]. 32: 33: groups() -> 34: [ 35: {hook_handlers, [], hook_handlers_tests()} 36: ]. 37: 38: hook_handlers_tests() -> 39: [ 40: missing_struct_in_message_from_user, 41: missing_struct_in_message_from_component 42: ]. 43: 44: suite() -> 45: []. 46: 47: %%-------------------------------------------------------------------- 48: %% Init & teardown 49: %%-------------------------------------------------------------------- 50: 51: init_per_suite(Config) -> 52: {ok, _} = application:ensure_all_started(jid), 53: Config. 54: 55: end_per_suite(Config) -> 56: Config. 57: 58: init_per_group(_GroupName, Config) -> 59: Config. 60: 61: end_per_group(_GroupName, Config) -> 62: Config. 63: 64: init_per_testcase(_CaseName, Config) -> 65: mongoose_config:set_opt(hosts, [global_host(), local_host()]), 66: set_meck(), 67: fake_start(), 68: Config. 69: 70: end_per_testcase(_CaseName, Config) -> 71: fake_stop(), 72: unset_meck(), 73: mongoose_config:unset_opt(hosts), 74: Config. 75: 76: %%-------------------------------------------------------------------- 77: %% Hook handlers tests 78: %%-------------------------------------------------------------------- 79: 80: 81: %% missing_struct_ tests verify the behaviour of packet_to_component handler, 82: %% which is supposed to update the mapping of the sender in Redis and cache. 83: %% In case of routing between nodes in single cluster AND routers being reordered 84: %% with component routers at the beginning of the chain, this hook must not fail 85: %% despite lack of global_distrib structure in Acc. 86: missing_struct_in_message_from_user(_Config) -> 87: From = jid:make(<<"user">>, global_host(), <<"resource">>), 88: {Acc, To} = fake_acc_to_component(From), 89: % The handler must not crash and return unchanged Acc 90: Acc = mod_global_distrib_mapping:packet_to_component(Acc, From, To). 91: 92: %% Update logic has two separate paths: when a packet is sent by a user or by another 93: %% component. This test covers the latter. 94: missing_struct_in_message_from_component(_Config) -> 95: From = jid:make(<<"">>, <<"from_service.", (global_host())/binary>>, <<"">>), 96: {Acc, To} = fake_acc_to_component(From), 97: % The handler must not crash and return unchanged Acc 98: Acc = mod_global_distrib_mapping:packet_to_component(Acc, From, To). 99: 100: %%-------------------------------------------------------------------- 101: %% Helpers 102: %%-------------------------------------------------------------------- 103: 104: global_host() -> 105: <<"localhost">>. 106: 107: local_host() -> 108: <<"localhost.bis">>. 109: 110: -spec fake_acc_to_component(From :: jid:jid()) -> {Acc :: mongoose_acc:t(), To :: jid:jid()}. 111: fake_acc_to_component(From) -> 112: To = jid:make(<<"">>, <<"to_service.localhost">>, <<"">>), 113: FromBin = jid:to_binary(From), 114: ToBin = jid:to_binary(To), 115: BodyEl = #xmlel{ 116: name = <<"body">>, 117: children = [#xmlcdata{ content = <<"hooks test">> }] 118: }, 119: Packet = #xmlel{ 120: name = <<"message">>, 121: attrs = [{<<"from">>, FromBin}, {<<"to">>, ToBin}, {<<"type">>, <<"chat">>}], 122: children = [BodyEl] 123: }, 124: {mongoose_acc:new(#{ location => ?LOCATION, 125: lserver => From#jid.lserver, 126: host_type => From#jid.lserver, 127: element => Packet }), To}. 128: 129: %%-------------------------------------------------------------------- 130: %% Meck & fake zone 131: %%-------------------------------------------------------------------- 132: 133: set_meck() -> 134: meck:new(mongoose_metrics, []), 135: meck:expect(mongoose_metrics, update, fun(_, _, _) -> ok end), 136: 137: meck:new(mod_global_distrib_mapping_backend, [non_strict]), 138: %% Simulate missing entries and inserts into Redis 139: meck:expect(mod_global_distrib_mapping_backend, get_session, fun(_) -> error end), 140: meck:expect(mod_global_distrib_mapping_backend, put_session, fun(_) -> ok end), 141: meck:expect(mod_global_distrib_mapping_backend, get_domain, fun(_) -> error end), 142: meck:expect(mod_global_distrib_mapping_backend, put_domain, fun(_) -> ok end). 143: 144: unset_meck() -> 145: meck:unload(mod_global_distrib_mapping_backend), 146: meck:unload(mongoose_metrics). 147: 148: %% These functions fake modules startup in order to populate ETS with options. 149: %% It is impossible to meck 'ets' modules and mecking mod_global_distrib_utils:opt/2 150: %% does not fully work as well because maybe_update_mapping/2 function does local call 151: %% to opt/2, bypassing meck. 152: fake_start() -> 153: lists:foreach( 154: fun(Mod) -> 155: mod_global_distrib_utils:start(Mod, global_host(), 156: common_fake_opts(), fun() -> ok end) 157: end, fake_start_stop_list()). 158: 159: fake_stop() -> 160: lists:foreach( 161: fun(Mod) -> 162: mod_global_distrib_utils:stop(Mod, global_host(), fun() -> ok end) 163: end, fake_start_stop_list()). 164: 165: fake_start_stop_list() -> 166: [mod_global_distrib, mod_global_distrib_mapping]. 167: 168: common_fake_opts() -> 169: [ 170: {global_host, global_host()}, 171: {local_host, local_host()} 172: ]. 173: 174: fake_tabs_info() -> 175: [ ets:info(T) || T <- fake_start_stop_list() ]. 176: