1: %%============================================================================== 2: %% Copyright 2013 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: -module(mongooseimctl_SUITE). 17: -compile([export_all, nowarn_export_all, nowarn_shadow_vars]). 18: -include_lib("escalus/include/escalus.hrl"). 19: -include_lib("common_test/include/ct.hrl"). 20: -include_lib("exml/include/exml.hrl"). 21: -include_lib("eunit/include/eunit.hrl"). 22: 23: -import(mongooseimctl_helper, [mongooseimctl/3]). 24: -import(distributed_helper, [mim/0, require_rpc_nodes/1]). 25: -import(domain_helper, [domain/0]). 26: 27: %%-------------------------------------------------------------------- 28: %% Suite configuration 29: %%-------------------------------------------------------------------- 30: 31: all() -> 32: [ 33: {group, graphql}, 34: {group, help}, 35: {group, server} 36: ]. 37: 38: groups() -> 39: [{graphql, [], graphql()}, 40: {help, [], help()}, 41: {server, [], server()}]. 42: 43: graphql() -> 44: [graphql_wrong_arguments_number, 45: can_execute_admin_queries_with_permissions, 46: can_handle_execution_error, 47: graphql_error_unknown_command_with_args, 48: graphql_error_unknown_command_without_args, 49: graphql_error_unknown_category_with_args, 50: graphql_error_unknown_category_without_args, 51: graphql_no_command, 52: graphql_error_invalid_args, 53: graphql_error_invalid_arg_value, 54: graphql_error_no_arg_value, 55: graphql_error_missing_args, 56: graphql_error_unknown_arg, 57: graphql_arg_help, 58: graphql_command]. 59: 60: help() -> 61: [default_help, 62: help_with_dual_mode, 63: help_with_long_mode]. 64: 65: server() -> 66: [server_status, 67: server_is_started]. 68: 69: suite() -> 70: require_rpc_nodes([mim]) ++ escalus:suite(). 71: 72: init_per_suite(Config) -> 73: Node = mim(), 74: Config1 = ejabberd_node_utils:init(Node, Config), 75: Config1. 76: 77: end_per_suite(_Config) -> 78: ok. 79: 80: init_per_testcase(CaseName, Config) -> 81: escalus:init_per_testcase(CaseName, Config). 82: 83: end_per_testcase(CaseName, Config) -> 84: escalus:end_per_testcase(CaseName, Config). 85: 86: %%-------------------------------------------------------------------- 87: %% mongoose_graphql tests 88: %%-------------------------------------------------------------------- 89: 90: can_execute_admin_queries_with_permissions(Config) -> 91: Query = "query { checkAuth { authStatus } }", 92: Res = mongooseimctl("graphql", [Query], Config), 93: ?assertMatch({_, 0}, Res), 94: Data = element(1, Res), 95: ?assertNotEqual(nomatch, string:find(Data, "AUTHORIZED")). 96: 97: can_handle_execution_error(Config) -> 98: Query = "{}", 99: Res = mongooseimctl("graphql", [Query], Config), 100: ?assertMatch({_, 1}, Res), 101: Data = element(1, Res), 102: ?assertNotEqual(nomatch, string:find(Data, "parser_error")). 103: 104: graphql_wrong_arguments_number(Config) -> 105: ExpectedFragment = "This command requires", 106: ResNoArgs = mongooseimctl("graphql", [], Config), 107: ?assertMatch({_, 1}, ResNoArgs), 108: Data1 = element(1, ResNoArgs), 109: ?assertNotEqual(nomatch, string:find(Data1, ExpectedFragment)), 110: 111: ResTooManyArgs = mongooseimctl("graphql", ["{}", "{}"], Config), 112: ?assertMatch({_, 1}, ResTooManyArgs), 113: Data2 = element(1, ResTooManyArgs), 114: ?assertNotEqual(nomatch, string:find(Data2, ExpectedFragment)). 115: 116: %% Generic GraphQL command tests 117: %% Specific commands are tested in graphql_*_SUITE 118: 119: graphql_error_unknown_command_with_args(Config) -> 120: {Res, 1} = mongooseimctl("account", ["makeCoffee", "--strength", "medium"], Config), 121: ?assertMatch({match, _}, re:run(Res, "Unknown command")), 122: expect_existing_commands(Res). 123: 124: graphql_error_unknown_command_without_args(Config) -> 125: {Res, 1} = mongooseimctl("account", ["makeCoffee"], Config), 126: ?assertMatch({match, _}, re:run(Res, "Unknown command")), 127: expect_existing_commands(Res). 128: 129: graphql_error_unknown_category_with_args(Config) -> 130: {Res, 1} = mongooseimctl("cafe", ["makeCoffee"], Config), 131: ?assertMatch({match, _}, re:run(Res, "Unknown category")), 132: expect_category_list(Res). 133: 134: graphql_error_unknown_category_without_args(Config) -> 135: {Res, 1} = mongooseimctl("cafe", [], Config), 136: ?assertMatch({match, _}, re:run(Res, "Unknown category")), 137: expect_category_list(Res). 138: 139: graphql_no_command(Config) -> 140: %% Not an error - lists commands in the given category 141: {Res, 0} = mongooseimctl("account", [], Config), 142: expect_existing_commands(Res). 143: 144: graphql_error_invalid_args(Config) -> 145: {Res, 1} = mongooseimctl("account", ["countUsers", "now"], Config), 146: ?assertMatch({match, _}, re:run(Res, "Could not parse")), 147: expect_command_arguments(Res). 148: 149: graphql_error_invalid_arg_value(Config) -> 150: {Res, 1} = mongooseimctl("vcard", ["setVcard", "--user", "user@host", "--vcard", "x"], Config), 151: %% vCard should be provided in JSON 152: ?assertMatch({match, _}, re:run(Res, "Invalid value 'x' of argument 'vcard'")), 153: ?assertMatch({match, _}, re:run(Res, "vcard\s+VcardInput!")). 154: 155: graphql_error_no_arg_value(Config) -> 156: {Res, 1} = mongooseimctl("account", ["countUsers", "--domain"], Config), 157: ?assertMatch({match, _}, re:run(Res, "Could not parse")), 158: expect_command_arguments(Res). 159: 160: graphql_error_missing_args(Config) -> 161: {Res, 1} = mongooseimctl("account", ["countUsers"], Config), 162: ?assertMatch({match, _}, re:run(Res, "Missing mandatory arguments")), 163: expect_command_arguments(Res). 164: 165: graphql_error_unknown_arg(Config) -> 166: {Res, 1} = mongooseimctl("account", ["countUsers", "--domain", "localhost", 167: "--x", "y"], Config), 168: ?assertMatch({match, _}, re:run(Res, "Unknown argument")), 169: expect_command_arguments(Res). 170: 171: graphql_arg_help(Config) -> 172: {Res, 0} = mongooseimctl("account", ["countUsers", "--help"], Config), 173: expect_command_arguments(Res). 174: 175: graphql_command(Config) -> 176: {ResJSON, 0} = mongooseimctl("account", ["countUsers", "--domain", "localhost"], Config), 177: #{<<"data">> := Data} = rest_helper:decode(ResJSON, #{return_maps => true}), 178: ?assertMatch(#{<<"account">> := #{<<"countUsers">> := _}}, Data). 179: 180: expect_existing_commands(Res) -> 181: ?assertMatch({match, _}, re:run(Res, "countUsers")). 182: 183: expect_command_arguments(Res) -> 184: ?assertMatch({match, _}, re:run(Res, "domain\s+DomainName!")). 185: 186: %%----------------------------------------------------------------- 187: %% Help tests 188: %%----------------------------------------------------------------- 189: 190: default_help(Config) -> 191: #{node := Node} = mim(), 192: CtlCmd = distributed_helper:ctl_path(Node, Config), 193: {Res, 2} = mongooseimctl_helper:run(CtlCmd, []), 194: expect_category_list(Res). 195: 196: help_with_dual_mode(Config) -> 197: {Res1, 2} = mongooseimctl("help", ["--dual"], Config), 198: expect_category_list(Res1), 199: {Res2, 2} = mongooseimctl("help", ["--nonexistent"], Config), 200: expect_category_list(Res2), 201: {Res3, 2} = mongooseimctl("help", [], Config), 202: expect_category_list(Res3). 203: 204: help_with_long_mode(Config) -> 205: {Res, 2} = mongooseimctl("help", ["--long"], Config), 206: io:format("Res: ~p", [Res]), 207: ?assertMatch({match, _}, re:run(Res, "Usage")), 208: ?assertMatch({match, _}, re:run(Res, "account \n\s+Account management")). 209: 210: %%----------------------------------------------------------------- 211: %% Server management tests 212: %%----------------------------------------------------------------- 213: 214: server_status(Config) -> 215: {Res, 0} = mongooseimctl("status", [], Config), 216: ?assertMatch({match, _}, re:run(Res, "Erlang VM status: started")). 217: 218: server_is_started(Config) -> 219: %% Wait for the server to start, but it is already running 220: {Res, 0} = mongooseimctl("started", [], Config), 221: %% Expect only whitespace 222: ?assertMatch(nomatch, re:run(Res, "\S")). 223: 224: %%----------------------------------------------------------------- 225: %% Helpers 226: %%----------------------------------------------------------------- 227: 228: expect_category_list(Res) -> 229: ?assertMatch({match, _}, re:run(Res, "Usage")), 230: ?assertMatch({match, _}, re:run(Res, "account\s+Account management")).