1: -module(cets_disco_SUITE). 2: -compile([export_all, nowarn_export_all]). 3: 4: -import(distributed_helper, [mim/0, mim2/0, rpc/4]). 5: -include_lib("common_test/include/ct.hrl"). 6: 7: %%-------------------------------------------------------------------- 8: %% Suite configuration 9: %%-------------------------------------------------------------------- 10: 11: all() -> 12: [{group, file}, {group, rdbms}]. 13: 14: groups() -> 15: [{file, [], file_cases()}, 16: {rdbms, [], rdbms_cases()}]. 17: 18: file_cases() -> 19: [file_backend]. 20: 21: rdbms_cases() -> 22: [rdbms_backend, 23: rdbms_backend_supports_auto_cleaning]. 24: 25: suite() -> 26: distributed_helper:require_rpc_nodes([mim, mim2]) ++ escalus:suite(). 27: 28: %%-------------------------------------------------------------------- 29: %% Init & teardown 30: %%-------------------------------------------------------------------- 31: init_per_suite(Config) -> 32: escalus:init_per_suite(Config). 33: 34: end_per_suite(Config) -> 35: escalus:end_per_suite(Config). 36: 37: init_per_group(rdbms, Config) -> 38: case not ct_helper:is_ct_running() 39: orelse mongoose_helper:is_rdbms_enabled(domain_helper:host_type()) of 40: false -> {skip, rdbms_or_ct_not_running}; 41: true -> Config 42: end; 43: init_per_group(_, Config) -> 44: Config. 45: 46: end_per_group(_, Config) -> 47: Config. 48: 49: init_per_testcase(rdbms_backend_supports_auto_cleaning = CaseName, Config) -> 50: mock_timestamp(mim(), month_ago()) ++ 51: escalus:init_per_testcase(CaseName, Config); 52: init_per_testcase(CaseName, Config) -> 53: escalus:init_per_testcase(CaseName, Config). 54: 55: end_per_testcase(rdbms_backend_supports_auto_cleaning = CaseName, Config) -> 56: unmock_timestamp(mim()), 57: escalus:end_per_testcase(CaseName, Config); 58: end_per_testcase(CaseName, Config) -> 59: escalus:end_per_testcase(CaseName, Config). 60: 61: %%-------------------------------------------------------------------- 62: %% Test cases 63: %%-------------------------------------------------------------------- 64: 65: file_backend(Config) -> 66: Path = filename:join(?config(mim_data_dir, Config), "nodes.txt"), 67: Opts = #{disco_file => Path}, 68: State = rpc(mim(), cets_discovery_file, init, [Opts]), 69: {{ok, Nodes}, _} = rpc(mim(), cets_discovery_file, get_nodes, [State]), 70: ['node1@localhost', 'node2@otherhost'] = lists:sort(Nodes). 71: 72: rdbms_backend(_Config) -> 73: CN = <<"big_test">>, 74: Opts1 = #{cluster_name => CN, node_name_to_insert => <<"test1">>}, 75: Opts2 = #{cluster_name => CN, node_name_to_insert => <<"test2">>}, 76: State1 = disco_init(mim(), Opts1), 77: disco_get_nodes(mim(), State1), 78: State2 = disco_init(mim2(), Opts2), 79: {{ok, Nodes}, State2_2} = disco_get_nodes(mim2(), State2), 80: %% "test2" node can see "test1" 81: true = lists:member(test1, Nodes), 82: {{ok, _}, State2_3} = disco_get_nodes(mim2(), State2_2), 83: %% Check that we follow the right code branch 84: #{last_query_info := #{already_registered := true}} = State2_3. 85: 86: rdbms_backend_supports_auto_cleaning(Config) -> 87: ensure_mocked(Config), 88: CN = <<"big_test2">>, 89: Opts1 = #{cluster_name => CN, node_name_to_insert => <<"test1">>}, 90: Opts2 = #{cluster_name => CN, node_name_to_insert => <<"test2">>}, 91: %% test1 row is written with an old (mocked) timestamp 92: State1 = disco_init(mim(), Opts1), 93: {_, State1_2} = disco_get_nodes(mim(), State1), 94: {{ok, Nodes1}, State1_3} = disco_get_nodes(mim(), State1_2), 95: Timestamp = proplists:get_value(mocked_timestamp, Config), 96: #{last_query_info := #{timestamp := Timestamp}} = State1_3, 97: %% It is in DB 98: true = lists:member(test1, Nodes1), 99: %% test2 would clean test1 registration 100: %% We don't mock on mim2 node, so timestamps would differ 101: State2 = disco_init(mim2(), Opts2), 102: {{ok, Nodes2}, State2_2} = disco_get_nodes(mim2(), State2), 103: false = lists:member(test1, Nodes2), 104: #{last_query_info := #{run_cleaning_result := {removed, [test1]}}} = State2_2. 105: 106: %%-------------------------------------------------------------------- 107: %% Helpers 108: %%-------------------------------------------------------------------- 109: 110: disco_init(Node, Opts) -> 111: rpc(Node, mongoose_cets_discovery_rdbms, init, [Opts]). 112: 113: disco_get_nodes(Node, State) -> 114: rpc(Node, mongoose_cets_discovery_rdbms, get_nodes, [State]). 115: 116: timestamp() -> 117: os:system_time(second). 118: 119: month_ago() -> 120: timestamp() - timer:hours(24 * 30) div 1000. 121: 122: mock_timestamp(Node, Timestamp) -> 123: ok = rpc(Node, meck, new, [mongoose_rdbms_timestamp, [passthrough, no_link]]), 124: ok = rpc(Node, meck, expect, [mongoose_rdbms_timestamp, select, 0, Timestamp]), 125: %% Ensure that we mock 126: EnsureMocked = fun() -> 127: Timestamp = rpc(Node, mongoose_rdbms_timestamp, select, []) 128: end, 129: EnsureMocked(), 130: [{ensure_mocked, EnsureMocked}, {mocked_timestamp, Timestamp}]. 131: 132: ensure_mocked(Config) -> 133: EnsureMocked = proplists:get_value(ensure_mocked, Config), 134: EnsureMocked(). 135: 136: unmock_timestamp(Node) -> 137: ok = rpc(Node, meck, unload, [mongoose_rdbms_timestamp]).