rabbitmq-server/deps/rabbitmq_cli/test/rabbitmqctl_test.exs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

363 lines
10 KiB
Elixir
Raw Normal View History

## 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/.
2016-02-03 23:01:32 +08:00
##
## Copyright (c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
2016-02-03 23:01:32 +08:00
2016-02-03 22:42:45 +08:00
defmodule RabbitMQCtlTest do
2016-02-03 06:11:09 +08:00
use ExUnit.Case, async: false
import ExUnit.CaptureIO
2016-11-15 01:52:08 +08:00
import RabbitMQ.CLI.Core.ExitCodes
import TestHelper
2016-04-30 05:58:36 +08:00
setup_all do
2016-11-15 01:52:08 +08:00
RabbitMQ.CLI.Core.Distribution.start()
set_scope(:all)
2016-04-30 05:58:36 +08:00
:ok
end
#
# --help and `help [command]`
#
test "--help option prints help for the command and exits with an OK" do
command = ["status", "--help"]
2022-10-03 01:54:11 +08:00
assert capture_io(fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_ok())
end) =~ ~r/Usage/
end
test "bare --help prints general help and exits with an OK" do
command = ["--help"]
2022-10-03 01:54:11 +08:00
assert capture_io(fn ->
2022-10-03 01:54:11 +08:00
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"]
2022-10-03 01:54:11 +08:00
assert capture_io(fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_ok())
end) =~ ~r/Usage/
end
test "bare help command prints general help and exits with an OK" do
command = ["help"]
2022-10-03 01:54:11 +08:00
assert capture_io(fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_ok())
end) =~ ~r/Usage/
end
#
# Validation and Error Handling
#
test "print error message on a bad connection" do
2016-02-03 06:11:09 +08:00
command = ["status", "-n", "sandwich@pastrami"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_unavailable())
end) =~ ~r/unable to perform an operation on node 'sandwich@pastrami'/
2016-02-03 06:11:09 +08:00
end
test "when an RPC call times out, prints a timeout message" do
command = ["list_users", "-t", "0"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
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
2022-10-03 01:54:11 +08:00
add_user("kirk", "khaaaaaan")
command = ["authenticate_user", "kirk", "makeitso"]
2022-10-03 01:54:11 +08:00
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 = []
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_usage())
end) =~ ~r/usage/i
2016-02-03 06:11:09 +08:00
end
test "when invoked with only a --help, shows a generic usage message and exits with a success" do
command = ["--help"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stdio, fn ->
2022-10-03 01:54:11 +08:00
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"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stdio, fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_ok())
end) =~ ~r/usage/i
end
test "when no command name is provided, displays usage" do
command = ["-n", "sandwich@pastrami"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_usage())
end) =~ ~r/usage/i
2016-02-03 06:11:09 +08:00
end
test "short node name without the host part connects properly" do
2016-04-30 05:58:36 +08:00
command = ["status", "-n", "rabbit"]
capture_io(:stdio, fn -> error_check(command, exit_ok()) end)
2016-04-30 05:58:36 +08:00
end
test "a non-existent command results in help message displayed" do
command = ["not_real"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command, exit_usage())
end) =~ ~r/Usage/
end
2016-03-08 06:45:50 +08:00
test "a command that's been provided extra arguments exits with a reasonable error code" do
command = ["status", "extra"]
2022-10-03 01:54:11 +08:00
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"]
2022-10-03 01:54:11 +08:00
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 = ["set_vhost_tags", "voldemort", "mytag"]
capture_io(:stderr, fn -> error_check(command, exit_dataerr()) end)
end
2023-09-06 21:13:15 +08:00
test "a command with an unsupported option as the first command-line arg fails gracefully" do
command1 = ["--invalid=true", "list_permissions", "-p", "/"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command1, exit_usage())
end) =~ ~r/Invalid options for this command/
command2 = ["--node", "rabbit", "status", "quack"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command2, exit_usage())
end) =~ ~r/too many arguments./
command3 = ["--node", "rabbit", "add_user"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command3, exit_usage())
end) =~ ~r/not enough arguments./
end
2022-10-03 01:54:11 +08:00
## ------------------------- Default Flags ------------------------------------
2016-03-08 06:45:50 +08:00
test "an empty node option is filled with the default rabbit node" do
assert RabbitMQCtl.merge_all_defaults(%{})[:node] ==
2022-10-03 01:54:11 +08:00
TestHelper.get_rabbit_hostname()
2016-03-08 06:45:50 +08:00
end
test "a non-empty node option is not overwritten" do
assert RabbitMQCtl.merge_all_defaults(%{node: :jake@thedog})[:node] ==
2022-10-03 01:54:11 +08:00
:jake@thedog
2016-03-08 06:45:50 +08:00
end
test "an empty timeout option is set to infinity" do
assert RabbitMQCtl.merge_all_defaults(%{})[:timeout] == :infinity
2016-03-08 06:45:50 +08:00
end
test "a non-empty timeout option is not overridden" do
assert RabbitMQCtl.merge_all_defaults(%{timeout: 60})[:timeout] == 60
2016-03-08 06:45:50 +08:00
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"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
error_check(command1, exit_usage())
end) =~ ~r/Invalid options for this command/
command2 = ["list_permissions", "-o", "/"]
2022-10-03 01:54:11 +08:00
assert capture_io(:stderr, fn ->
2022-10-03 01:54:11 +08:00
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")
2022-10-03 01:54:11 +08:00
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")
2022-10-03 01:54:11 +08:00
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 ->
2022-10-03 01:54:11 +08:00
error_check(cmd, exit_ok())
end) == out
end
2022-10-03 01:54:11 +08:00
## ------------------------- Error formatting ---------------------------------
test "badrpc nodedown error" do
exit_code = exit_unavailable()
node = :example@node
2022-10-03 01:54:11 +08:00
{:error, ^exit_code, message} =
2022-10-03 01:54:11 +08:00
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
2022-10-03 01:54:11 +08:00
{:error, ^exit_code, message} =
2022-10-03 01:54:11 +08:00
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
2022-10-03 01:54:11 +08:00
err_msg =
"Error: operation example on node node@host timed out. Timeout value used: #{timeout}"
{:error, ^exit_code, ^err_msg} =
RabbitMQCtl.handle_command_output(
2022-10-03 01:54:11 +08:00
{:error, {:badrpc, :timeout}},
ExampleCommand,
%{timeout: timeout, node: nodename},
fn output, _, _ -> output end
)
end
test "generic error" do
exit_code = exit_unavailable()
2022-10-03 01:54:11 +08:00
{:error, ^exit_code, "Error:\nerror message"} =
RabbitMQCtl.handle_command_output(
{:error, "error message"},
2022-10-03 01:54:11 +08:00
: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)
2022-10-03 01:54:11 +08:00
{:error, ^exit_code, "Error:\n" <> ^inspected} =
RabbitMQCtl.handle_command_output(
{:error, error},
2022-10-03 01:54:11 +08:00
:no_command,
%{},
fn output, _, _ -> output end
)
end
test "atom error" do
exit_code = exit_unavailable()
2022-10-03 01:54:11 +08:00
{:error, ^exit_code, "Error:\nerror_message"} =
RabbitMQCtl.handle_command_output(
{:error, :error_message},
2022-10-03 01:54:11 +08:00
:no_command,
%{},
fn output, _, _ -> output end
)
end
2016-02-03 06:11:09 +08:00
end