1: -module(graphql_cets_SUITE). 2: -include_lib("eunit/include/eunit.hrl"). 3: 4: -compile([export_all, nowarn_export_all]). 5: 6: -import(distributed_helper, [mim/0, mim2/0, rpc/4]). 7: -import(domain_helper, [host_type/1]). 8: -import(mongooseimctl_helper, [rpc_call/3]). 9: -import(graphql_helper, [execute_command/4, get_unauthorized/1, get_ok_value/2]). 10: 11: all() -> 12: [{group, admin_cets_cli}, 13: {group, admin_cets_http}, 14: {group, domain_admin_cets}]. 15: 16: groups() -> 17: [{admin_cets_http, [parallel], admin_cets_tests()}, 18: {admin_cets_cli, [parallel], admin_cets_tests()}, 19: {domain_admin_cets, [], domain_admin_tests()}]. 20: 21: admin_cets_tests() -> 22: [has_sm_table_in_info, 23: available_nodes, 24: unavailable_nodes, 25: joined_nodes, 26: discovered_nodes, 27: remote_nodes_without_disco, 28: remote_nodes_with_unknown_tables, 29: remote_unknown_tables, 30: remote_nodes_with_missing_tables, 31: remote_missing_tables, 32: conflict_nodes, 33: conflict_tables, 34: discovery_works]. 35: 36: domain_admin_tests() -> 37: [domain_admin_get_table_info_test, 38: domain_admin_get_system_info_test]. 39: 40: init_per_suite(Config) -> 41: case rpc_call(mongoose_config, get_opt, [[internal_databases, cets, backend], undefined]) of 42: rdbms -> 43: Config1 = escalus:init_per_suite(Config), 44: Config2 = ejabberd_node_utils:init(mim(), Config1), 45: add_bad_node(), 46: ok = rpc_call(cets_discovery, wait_for_ready, [mongoose_cets_discovery, 5000]), 47: Config2 ++ distributed_helper:require_rpc_nodes([mim, mim2]); 48: _ -> 49: {skip, "CETS is not configured with RDBMS"} 50: end. 51: 52: end_per_suite(Config) -> 53: ensure_bad_node_unregistered(), 54: escalus:end_per_suite(Config). 55: 56: init_per_group(admin_cets_http, Config) -> 57: graphql_helper:init_admin_handler(Config); 58: init_per_group(admin_cets_cli, Config) -> 59: graphql_helper:init_admin_cli(Config); 60: init_per_group(domain_admin_cets, Config) -> 61: graphql_helper:init_domain_admin_handler(Config). 62: 63: end_per_group(_, _Config) -> 64: graphql_helper:clean(), 65: escalus_fresh:clean(). 66: 67: init_per_testcase(has_sm_table_in_info, Config) -> 68: case rpc_call(ejabberd_sm, sm_backend, []) of 69: ejabberd_sm_cets -> 70: Config; 71: _ -> 72: {skip, "SM backend is not CETS"} 73: end; 74: init_per_testcase(_, Config) -> 75: Config. 76: 77: % Admin tests 78: 79: has_sm_table_in_info(Config) -> 80: Res = get_table_info(Config), 81: Tables = get_ok_value([data, cets, tableInfo], Res), 82: [T] = [T || T = #{<<"tableName">> := <<"cets_session">>} <- Tables], 83: #{<<"memory">> := Mem, <<"nodes">> := Nodes, <<"size">> := Size} = T, 84: ?assert(is_integer(Mem), T), 85: ?assert(is_integer(Size), T), 86: #{node := Node1} = mim(), 87: assert_member(atom_to_binary(Node1), Nodes). 88: 89: available_nodes(Config) -> 90: #{node := Node1} = mim(), 91: #{node := Node2} = mim2(), 92: Res = get_system_info(Config), 93: Info = get_ok_value([data, cets, systemInfo], Res), 94: #{<<"availableNodes">> := Nodes} = Info, 95: assert_member(atom_to_binary(Node1), Nodes), 96: assert_member(atom_to_binary(Node2), Nodes), 97: assert_not_member(<<"badnode@localhost">>, Nodes). 98: 99: unavailable_nodes(Config) -> 100: #{node := Node1} = mim(), 101: #{node := Node2} = mim2(), 102: Res = get_system_info(Config), 103: Info = get_ok_value([data, cets, systemInfo], Res), 104: #{<<"unavailableNodes">> := Nodes} = Info, 105: assert_member(<<"badnode@localhost">>, Nodes), 106: assert_not_member(atom_to_binary(Node1), Nodes), 107: assert_not_member(atom_to_binary(Node2), Nodes). 108: 109: joined_nodes(Config) -> 110: #{node := Node1} = mim(), 111: #{node := Node2} = mim2(), 112: Res = get_system_info(Config), 113: Info = get_ok_value([data, cets, systemInfo], Res), 114: #{<<"joinedNodes">> := Nodes} = Info, 115: assert_member(atom_to_binary(Node1), Nodes), 116: assert_member(atom_to_binary(Node2), Nodes), 117: assert_not_member(<<"badnode@localhost">>, Nodes). 118: 119: remote_nodes_without_disco(Config) -> 120: Res = get_system_info(Config), 121: Info = get_ok_value([data, cets, systemInfo], Res), 122: ?assert(is_list(maps:get(<<"remoteNodesWithoutDisco">>, Info)), Info). 123: 124: remote_nodes_with_unknown_tables(Config) -> 125: Res = get_system_info(Config), 126: Info = get_ok_value([data, cets, systemInfo], Res), 127: ?assert(is_list(maps:get(<<"remoteNodesWithUnknownTables">>, Info)), Info). 128: 129: remote_unknown_tables(Config) -> 130: Res = get_system_info(Config), 131: Info = get_ok_value([data, cets, systemInfo], Res), 132: ?assert(is_list(maps:get(<<"remoteUnknownTables">>, Info)), Info). 133: 134: remote_nodes_with_missing_tables(Config) -> 135: Res = get_system_info(Config), 136: Info = get_ok_value([data, cets, systemInfo], Res), 137: ?assert(is_list(maps:get(<<"remoteNodesWithMissingTables">>, Info)), Info). 138: 139: remote_missing_tables(Config) -> 140: Res = get_system_info(Config), 141: Info = get_ok_value([data, cets, systemInfo], Res), 142: ?assert(is_list(maps:get(<<"remoteMissingTables">>, Info)), Info). 143: 144: conflict_nodes(Config) -> 145: Res = get_system_info(Config), 146: Info = get_ok_value([data, cets, systemInfo], Res), 147: ?assertMatch(#{<<"conflictNodes">> := []}, Info). 148: 149: conflict_tables(Config) -> 150: Res = get_system_info(Config), 151: Info = get_ok_value([data, cets, systemInfo], Res), 152: ?assertMatch(#{<<"conflictTables">> := []}, Info). 153: 154: conflict_nodes_count(Config) -> 155: Res = get_system_info(Config), 156: Info = get_ok_value([data, cets, systemInfo], Res), 157: ?assertMatch(#{<<"conflictNodesCount">> := 0}, Info). 158: 159: discovered_nodes(Config) -> 160: #{node := Node1} = mim(), 161: #{node := Node2} = mim2(), 162: Res = get_system_info(Config), 163: Info = get_ok_value([data, cets, systemInfo], Res), 164: #{<<"discoveredNodes">> := Nodes} = Info, 165: assert_member(atom_to_binary(Node1), Nodes), 166: assert_member(atom_to_binary(Node2), Nodes), 167: assert_member(<<"badnode@localhost">>, Nodes). 168: 169: discovered_nodes_count(Config) -> 170: Res = get_system_info(Config), 171: Info = get_ok_value([data, cets, systemInfo], Res), 172: #{<<"discoveredNodesCount">> := Count} = Info, 173: ?assert(is_integer(Count), Info), 174: ?assert(Count > 2, Info). 175: 176: discovery_works(Config) -> 177: Res = get_system_info(Config), 178: Info = get_ok_value([data, cets, systemInfo], Res), 179: ?assertMatch(#{<<"discoveryWorks">> := true}, Info). 180: 181: % Domain admin tests 182: 183: domain_admin_get_table_info_test(Config) -> 184: get_unauthorized(get_table_info(Config)). 185: 186: domain_admin_get_system_info_test(Config) -> 187: get_unauthorized(get_system_info(Config)). 188: 189: %-------------------------------------------------------------------------------------------------- 190: % Helpers 191: %-------------------------------------------------------------------------------------------------- 192: 193: get_table_info(Config) -> 194: execute_command(<<"cets">>, <<"tableInfo">>, #{}, Config). 195: 196: get_system_info(Config) -> 197: execute_command(<<"cets">>, <<"systemInfo">>, #{}, Config). 198: 199: add_bad_node() -> 200: ensure_bad_node_unregistered(), 201: register_bad_node(), 202: force_check(), 203: wait_for_has_bad_node(). 204: 205: register_bad_node() -> 206: ClusterName = <<"mim">>, 207: Node = <<"badnode@localhost">>, 208: Num = 100, 209: Address = <<>>, 210: Timestamp = rpc(mim(), mongoose_rdbms_timestamp, select, []), 211: InsertArgs = [ClusterName, Node, Num, Address, Timestamp], 212: {updated, 1} = rpc(mim(), mongoose_cets_discovery_rdbms, insert_new, InsertArgs). 213: 214: ensure_bad_node_unregistered() -> 215: ClusterName = <<"mim">>, 216: Node = <<"badnode@localhost">>, 217: DeleteArgs = [ClusterName, Node], 218: %% Ensure the node is removed 219: {updated, _} = rpc(mim(), mongoose_cets_discovery_rdbms, delete_node_from_db, DeleteArgs). 220: 221: force_check() -> 222: Pid = rpc(mim(), erlang, whereis, [mongoose_cets_discovery]), 223: true = is_pid(Pid), 224: Pid ! check. 225: 226: has_bad_node() -> 227: #{unavailable_nodes := UnNodes} = 228: rpc(mim(), cets_discovery, system_info, [mongoose_cets_discovery]), 229: lists:member('badnode@localhost', UnNodes). 230: 231: wait_for_has_bad_node() -> 232: mongoose_helper:wait_until(fun() -> has_bad_node() end, true). 233: 234: assert_member(Elem, List) -> 235: lists:member(Elem, List) 236: orelse ct:fail({assert_member_failed, Elem, List}). 237: 238: assert_not_member(Elem, List) -> 239: lists:member(Elem, List) 240: andalso ct:fail({assert_member_failed, Elem, List}).