diff options
Diffstat (limited to 'deps/rabbitmq_cli/test/rabbitmqctl_test.exs')
-rw-r--r-- | deps/rabbitmq_cli/test/rabbitmqctl_test.exs | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/deps/rabbitmq_cli/test/rabbitmqctl_test.exs b/deps/rabbitmq_cli/test/rabbitmqctl_test.exs new file mode 100644 index 0000000000..c6b085daad --- /dev/null +++ b/deps/rabbitmq_cli/test/rabbitmqctl_test.exs @@ -0,0 +1,301 @@ +## This Source Code Form is subject to the terms of the Mozilla Public +## License, v. 2.0. If a copy of the MPL was not distributed with this +## file, You can obtain one at https://mozilla.org/MPL/2.0/. +## +## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved. + + +defmodule RabbitMQCtlTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import RabbitMQ.CLI.Core.ExitCodes + import TestHelper + + + setup_all do + RabbitMQ.CLI.Core.Distribution.start() + + set_scope(:all) + + :ok + end + + # + # --help and `help [command]` + # + + test "--help option prints help for the command and exits with an OK" do + command = ["status", "--help"] + assert capture_io(fn -> + error_check(command, exit_ok()) + end) =~ ~r/Usage/ + end + + test "bare --help prints general help and exits with an OK" do + command = ["--help"] + assert capture_io(fn -> + error_check(command, exit_ok()) + end) =~ ~r/Usage/ + end + + test "help [command] prints help for the command and exits with an OK" do + command = ["help", "status"] + assert capture_io(fn -> + error_check(command, exit_ok()) + end) =~ ~r/Usage/ + end + + test "bare help command prints general help and exits with an OK" do + command = ["help"] + assert capture_io(fn -> + error_check(command, exit_ok()) + end) =~ ~r/Usage/ + end + + # + # Validation and Error Handling + # + + test "print error message on a bad connection" do + command = ["status", "-n", "sandwich@pastrami"] + assert capture_io(:stderr, fn -> + error_check(command, exit_unavailable()) + end) =~ ~r/unable to perform an operation on node 'sandwich@pastrami'/ + end + + test "when an RPC call times out, prints a timeout message" do + command = ["list_users", "-t", "0"] + assert capture_io(:stderr, fn -> + error_check(command, exit_tempfail()) + end) =~ ~r/Error: operation list_users on node #{get_rabbit_hostname()} timed out. Timeout value used: 0/ + end + + test "when authentication fails, prints an authentication error message" do + add_user "kirk", "khaaaaaan" + command = ["authenticate_user", "kirk", "makeitso"] + assert capture_io(:stderr, + fn -> error_check(command, exit_dataerr()) + end) =~ ~r/Error: failed to authenticate user \"kirk\"/ + delete_user "kirk" + end + + test "when invoked without arguments, displays a generic usage message and exits with a non-zero code" do + command = [] + assert capture_io(:stderr, fn -> + error_check(command, exit_usage()) + end) =~ ~r/usage/i + end + + test "when invoked with only a --help, shows a generic usage message and exits with a success" do + command = ["--help"] + assert capture_io(:stdio, fn -> + error_check(command, exit_ok()) + end) =~ ~r/usage/i + end + + test "when invoked with --help [command], shows a generic usage message and exits with a success" do + command = ["--help", "status"] + assert capture_io(:stdio, fn -> + error_check(command, exit_ok()) + end) =~ ~r/usage/i + end + + test "when no command name is provided, displays usage" do + command = ["-n", "sandwich@pastrami"] + assert capture_io(:stderr, fn -> + error_check(command, exit_usage()) + end) =~ ~r/usage/i + end + + test "short node name without the host part connects properly" do + command = ["status", "-n", "rabbit"] + capture_io(:stderr, fn -> error_check(command, exit_ok()) end) + end + + test "a non-existent command results in help message displayed" do + command = ["not_real"] + assert capture_io(:stderr, fn -> + error_check(command, exit_usage()) + end) =~ ~r/Usage/ + end + + test "a command that's been provided extra arguments exits with a reasonable error code" do + command = ["status", "extra"] + output = capture_io(:stderr, fn -> + error_check(command, exit_usage()) + end) + assert output =~ ~r/too many arguments/ + assert output =~ ~r/Usage/ + assert output =~ ~r/status/ + end + + test "a command that's been provided insufficient arguments exits with a reasonable error code" do + command = ["list_user_permissions"] + output = capture_io(:stderr, fn -> + error_check(command, exit_usage()) + end) + assert output =~ ~r/not enough arguments/ + assert output =~ ~r/Usage/ + assert output =~ ~r/list_user_permissions/ + end + + test "a command that's provided an invalid argument exits a reasonable error" do + command = ["set_disk_free_limit", "2097152bytes"] + capture_io(:stderr, fn -> error_check(command, exit_dataerr()) end) + end + + test "a command that fails with an error exits with a reasonable error code" do + command = ["delete_user", "voldemort"] + capture_io(:stderr, fn -> error_check(command, exit_nouser()) end) + end + + test "a mcommand with an unsupported option as the first command-line arg fails gracefully" do + command1 = ["--invalid=true", "list_permissions", "-p", "/"] + assert capture_io(:stderr, fn -> + error_check(command1, exit_usage()) + end) =~ ~r/Invalid options for this command/ + + command2 = ["--node", "rabbit", "status", "quack"] + assert capture_io(:stderr, fn -> + error_check(command2, exit_usage()) + end) =~ ~r/too many arguments./ + + command3 = ["--node", "rabbit", "add_user"] + assert capture_io(:stderr, fn -> + error_check(command3, exit_usage()) + end) =~ ~r/not enough arguments./ + end + +## ------------------------- Default Flags ------------------------------------ + + test "an empty node option is filled with the default rabbit node" do + assert RabbitMQCtl.merge_all_defaults(%{})[:node] == + TestHelper.get_rabbit_hostname() + end + + test "a non-empty node option is not overwritten" do + assert RabbitMQCtl.merge_all_defaults(%{node: :jake@thedog})[:node] == + :jake@thedog + end + + test "an empty timeout option is set to infinity" do + assert RabbitMQCtl.merge_all_defaults(%{})[:timeout] == :infinity + end + + test "a non-empty timeout option is not overridden" do + assert RabbitMQCtl.merge_all_defaults(%{timeout: 60})[:timeout] == 60 + end + + test "other parameters are not overridden by the default" do + assert RabbitMQCtl.merge_all_defaults(%{vhost: "quack"})[:vhost] == "quack" + end + + test "any flags that aren't global or command-specific cause a bad option" do + command1 = ["status", "--nod=rabbit"] + assert capture_io(:stderr, fn -> + error_check(command1, exit_usage()) + end) =~ ~r/Invalid options for this command/ + + command2 = ["list_permissions", "-o", "/"] + assert capture_io(:stderr, fn -> + error_check(command2, exit_usage()) + end) =~ ~r/Invalid options for this command/ + end + + # + # --auto-complete and `autocomplete [command]` + # + + test "--auto-complete delegates to the autocomplete command" do + # Note: these are not script name (scope) aware without --script-name + # but the actual command invoked in a shell will be + check_output(["--auto-complete", "list_q"], "list_queues\n") + check_output(["--auto-complete", "list_con", "--script-name", "rabbitmq-diagnostics"], "list_connections\nlist_consumers\n") + check_output(["--auto-complete", "--script-name", "rabbitmq-diagnostics", "mem"], "memory_breakdown\n") + check_output(["--auto-complete", "--script-name", "rabbitmq-queues", "add_m"], "add_member\n") + end + + test "autocompletion command used directly" do + # Note: these are not script name (scope) aware without --script-name + # but the actual command invoked in a shell will be + check_output(["autocomplete", "list_q"], "list_queues\n") + check_output(["autocomplete", "list_con", "--script-name", "rabbitmq-diagnostics"], "list_connections\nlist_consumers\n") + check_output(["autocomplete", "--script-name", "rabbitmq-diagnostics", "mem"], "memory_breakdown\n") + check_output(["autocomplete", "--script-name", "rabbitmq-queues", "add_m"], "add_member\n") + end + + defp check_output(cmd, out) do + assert capture_io(fn -> + error_check(cmd, exit_ok()) + end) == out + end + + +## ------------------------- Error formatting --------------------------------- + + test "badrpc nodedown error" do + exit_code = exit_unavailable() + node = :example@node + {:error, ^exit_code, message} = + RabbitMQCtl.handle_command_output( + {:error, {:badrpc, :nodedown}}, + :no_command, %{node: node}, + fn(output, _, _) -> output end) + + assert message =~ ~r/Error: unable to perform an operation on node/ + assert message =~ ~r/DIAGNOSTICS/ + assert message =~ ~r/attempted to contact/ + + localnode = :non_existent_node@localhost + {:error, ^exit_code, message} = + RabbitMQCtl.handle_command_output( + {:error, {:badrpc, :nodedown}}, + :no_command, %{node: localnode}, + fn(output, _, _) -> output end) + assert message =~ ~r/DIAGNOSTICS/ + assert message =~ ~r/attempted to contact/ + assert message =~ ~r/suggestion: start the node/ + end + + test "badrpc timeout error" do + exit_code = exit_tempfail() + timeout = 1000 + nodename = :node@host + err_msg = "Error: operation example on node node@host timed out. Timeout value used: #{timeout}" + {:error, ^exit_code, ^err_msg} = + RabbitMQCtl.handle_command_output( + {:error, {:badrpc, :timeout}}, + ExampleCommand, %{timeout: timeout, node: nodename}, + fn(output, _, _) -> output end) + end + + test "generic error" do + exit_code = exit_unavailable() + {:error, ^exit_code, "Error:\nerror message"} = + RabbitMQCtl.handle_command_output( + {:error, "error message"}, + :no_command, %{}, + fn(output, _, _) -> output end) + end + + test "inspect arbitrary error" do + exit_code = exit_unavailable() + error = %{i: [am: "arbitrary", error: 1]} + inspected = inspect(error) + {:error, ^exit_code, "Error:\n" <> ^inspected} = + RabbitMQCtl.handle_command_output( + {:error, error}, + :no_command, %{}, + fn(output, _, _) -> output end) + end + + test "atom error" do + exit_code = exit_unavailable() + {:error, ^exit_code, "Error:\nerror_message"} = + RabbitMQCtl.handle_command_output( + {:error, :error_message}, + :no_command, %{}, + fn(output, _, _) -> output end) + end + +end |