From 1abf9622f232086a2c4990ff9ead4b2168092d31 Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Thu, 5 May 2016 11:05:11 +0100 Subject: [PATCH 01/39] list_* commands --- deps/rabbitmq_cli/lib/info_keys.ex | 16 +++++ .../rabbitmq_cli/lib/list_bindings_command.ex | 49 +++++++++++++ .../rabbitmq_cli/lib/list_channels_command.ex | 45 ++++++++++++ .../lib/list_connections_command.ex | 48 +++++++++++++ .../lib/list_consumers_command.ex | 29 ++++++++ .../lib/list_exchanges_command.ex | 46 ++++++++++++ deps/rabbitmq_cli/lib/list_queues_command.ex | 72 +++++++++++++++++++ deps/rabbitmq_cli/lib/parser.ex | 5 +- deps/rabbitmq_cli/lib/rpc_stream.ex | 47 ++++++++++++ 9 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 deps/rabbitmq_cli/lib/info_keys.ex create mode 100644 deps/rabbitmq_cli/lib/list_bindings_command.ex create mode 100644 deps/rabbitmq_cli/lib/list_channels_command.ex create mode 100644 deps/rabbitmq_cli/lib/list_connections_command.ex create mode 100644 deps/rabbitmq_cli/lib/list_consumers_command.ex create mode 100644 deps/rabbitmq_cli/lib/list_exchanges_command.ex create mode 100644 deps/rabbitmq_cli/lib/list_queues_command.ex create mode 100644 deps/rabbitmq_cli/lib/rpc_stream.ex diff --git a/deps/rabbitmq_cli/lib/info_keys.ex b/deps/rabbitmq_cli/lib/info_keys.ex new file mode 100644 index 0000000000..c1fcf0919e --- /dev/null +++ b/deps/rabbitmq_cli/lib/info_keys.ex @@ -0,0 +1,16 @@ +defmodule InfoKeys do + def with_valid_info_keys(args, valid_keys, fun) do + info_keys = Enum.map(args, &String.to_atom/1) + case invalid_info_keys(info_keys, valid_keys) do + [_|_] = bad_info_keys -> + {:error, {:bad_info_key, bad_info_keys}} + [] -> fun.(info_keys) + end + end + + defp invalid_info_keys(info_keys, valid_keys) do + # Difference between enums. + # It's faster than converting to sets for small lists + for key <- info_keys, not Enum.member?(valid_keys, key), do: key + end +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_bindings_command.ex b/deps/rabbitmq_cli/lib/list_bindings_command.ex new file mode 100644 index 0000000000..94fedd9fa1 --- /dev/null +++ b/deps/rabbitmq_cli/lib/list_bindings_command.ex @@ -0,0 +1,49 @@ +defmodule ListBindingsCommand do + @behaviour Command + + @info_keys ~w(source_name source_kind destination_name destination_kind routing_key arguments)a + + def flags() do + [:param] + end + + def usage() do + "list_bindings [-p ] [ ...]" + end + + def usage_additional() do + " must be a member of the list ["<> + Enum.join(@info_keys, ", ") <>"]." + end + + def run([], opts) do + run(~w(source_name source_kind + destination_name destination_kind + routing_key arguments), + opts) + end + def run([_|_] = args, %{node: node_name, timeout: timeout, param: vhost} = opts) do + info_keys = Enum.map(args, &String.to_atom/1) + InfoKeys.with_valid_info_keys(args, @info_keys, + fn(info_keys) -> + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_binding, :info_all, + [vhost, info_keys], + timeout, + info_keys) + end) + end + def run([_|_] = args, %{node: node_name, timeout: timeout} = opts) do + run(args, Map.merge(default_opts, opts)) + end + + defp default_opts() do + %{param: "/"} + end + + defp info(%{quiet: true}), do: nil + defp info(_), do: IO.puts "Listing bindings ..." + +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_channels_command.ex b/deps/rabbitmq_cli/lib/list_channels_command.ex new file mode 100644 index 0000000000..b6344104cf --- /dev/null +++ b/deps/rabbitmq_cli/lib/list_channels_command.ex @@ -0,0 +1,45 @@ +defmodule ListChannelsCommand do + @behaviour CommandBehaviour + + @info_keys ~w(pid connection name number user vhost transactional + confirm consumer_count messages_unacknowledged + messages_uncommitted acks_uncommitted messages_unconfirmed + prefetch_count global_prefetch_count)a + + def flags() do + [] + end + + def usage() do + "list_channels [ ...]" + end + + def usage_additional() do + " must be a member of the list ["<> + Enum.join(@info_keys, ", ") <>"]." + end + + def run([], opts) do + run(~w(pid user consumer_count messages_unacknowledged), opts) + end + def run([_|_] = args, %{node: node_name, timeout: timeout} = opts) do + info_keys = Enum.map(args, &String.to_atom/1) + InfoKeys.with_valid_info_keys(args, @info_keys, + fn(info_keys) -> + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_channel, :info_all, + [info_keys], + timeout, + info_keys) + end) + end + + defp default_opts() do + %{} + end + + defp info(%{quiet: true}), do: nil + defp info(_), do: IO.puts "Listing channels ..." +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_connections_command.ex b/deps/rabbitmq_cli/lib/list_connections_command.ex new file mode 100644 index 0000000000..763fe98687 --- /dev/null +++ b/deps/rabbitmq_cli/lib/list_connections_command.ex @@ -0,0 +1,48 @@ +defmodule ListConnectionsCommand do + @behaviour CommandBehaviour + + @info_keys ~w(pid name port host peer_port peer_host ssl ssl_protocol + ssl_key_exchange ssl_cipher ssl_hash peer_cert_subject + peer_cert_issuer peer_cert_validity state + channels protocol auth_mechanism user vhost timeout frame_max + channel_max client_properties recv_oct recv_cnt send_oct + send_cnt send_pend connected_at)a + + def flags() do + [] + end + + def usage() do + "list_connections [ ...]" + end + + def usage_additional() do + " must be a member of the list ["<> + Enum.join(@info_keys, ", ") <>"]." + end + + def run([], opts) do + run(~w(user peer_host peer_port state), opts) + end + def run([_|_] = args, %{node: node_name, timeout: timeout} = opts) do + info_keys = Enum.map(args, &String.to_atom/1) + InfoKeys.with_valid_info_keys(args, @info_keys, + fn(info_keys) -> + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_networking, + :connection_info_all, + [info_keys], + timeout, + info_keys) + end) + end + + defp default_opts() do + %{} + end + + defp info(%{quiet: true}), do: nil + defp info(_), do: IO.puts "Listing connections ..." +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_consumers_command.ex b/deps/rabbitmq_cli/lib/list_consumers_command.ex new file mode 100644 index 0000000000..9135783a7d --- /dev/null +++ b/deps/rabbitmq_cli/lib/list_consumers_command.ex @@ -0,0 +1,29 @@ +defmodule ListConsumersCommand do + @behaviour CommandBehaviour + + def flags() do + [] + end + + def usage() do + "list_consumers [-p vhost]" + end + + def run(_args, %{node: node_name, timeout: timeout, param: vhost} = opts) do + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_amqqueue, :consumers_all, + [vhost], timeout, []) + end + def run(args, %{node: node_name, timeout: timeout} = opts) do + run(args, Map.merge(default_opts, opts)) + end + + defp default_opts() do + %{param: "/"} + end + + defp info(%{quiet: true}), do: nil + defp info(_), do: IO.puts "Listing channels ..." +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_exchanges_command.ex b/deps/rabbitmq_cli/lib/list_exchanges_command.ex new file mode 100644 index 0000000000..c2c9e5137b --- /dev/null +++ b/deps/rabbitmq_cli/lib/list_exchanges_command.ex @@ -0,0 +1,46 @@ +defmodule ListExchangesCommand do + @behaviour CommandBehaviour + + @info_keys ~w(name type durable auto_delete internal arguments policy)a + + def flags() do + [:param] + end + + def usage() do + "list_exchanges [-p ] [ ...]" + end + + def usage_additional() do + " must be a member of the list ["<> + Enum.join(@info_keys, ", ") <>"]." + end + + def run([], opts) do + run(~w(name type), opts) + end + def run([_|_] = args, %{node: node_name, timeout: timeout, param: vhost} = opts) do + info_keys = Enum.map(args, &String.to_atom/1) + InfoKeys.with_valid_info_keys(args, @info_keys, + fn(info_keys) -> + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_exchange, :info_all, + [vhost, info_keys], + timeout, + info_keys) + end) + end + def run([_|_] = args, %{node: node_name, timeout: timeout} = opts) do + run(args, Map.merge(default_opts, opts)) + end + + defp default_opts() do + %{param: "/"} + end + + defp info(%{quiet: true}), do: nil + defp info(_), do: IO.puts "Listing exchanges ..." + +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_queues_command.ex b/deps/rabbitmq_cli/lib/list_queues_command.ex new file mode 100644 index 0000000000..33f786309f --- /dev/null +++ b/deps/rabbitmq_cli/lib/list_queues_command.ex @@ -0,0 +1,72 @@ +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is GoPivotal, Inc. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + +defmodule ListQueuesCommand do + @behaviour CommandBehaviour + + @info_keys ~w(name durable auto_delete + arguments policy pid owner_pid exclusive exclusive_consumer_pid + exclusive_consumer_tag messages_ready messages_unacknowledged messages + messages_ready_ram messages_unacknowledged_ram messages_ram + messages_persistent message_bytes message_bytes_ready + message_bytes_unacknowledged message_bytes_ram message_bytes_persistent + head_message_timestamp disk_reads disk_writes consumers + consumer_utilisation memory slave_pids synchronised_slave_pids state)a + + def flags() do + [:param, :offline, :online] + end + + def usage() do + "list_queues [-p ] [--online] [--offline] [ ...]" + end + + def usage_additional() do + " must be a member of the list ["<> + Enum.join(@info_keys, ", ") <>"]." + end + + def run([], opts) do + run(~w(name messages), opts) + end + def run([_|_] = args, %{node: node_name, timeout: timeout, param: vhost, + online: online_opt, offline: offline_opt} = opts) do + {online, offline} = case {online_opt, offline_opt} do + {false, false} -> {true, true}; + other -> other + end + InfoKeys.with_valid_info_keys(args, @info_keys, + fn(info_keys) -> + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_amqqueue, :info_all, + [vhost, info_keys, online, offline], + timeout, + info_keys) + end) + end + def run([_|_] = args, opts) do + run(args, Map.merge(default_opts, opts)) + end + + defp default_opts() do + %{param: "/", offline: false, online: false} + end + + defp info(%{quiet: true}), do: nil + defp info(_), do: IO.puts "Listing queues ..." +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/parser.ex b/deps/rabbitmq_cli/lib/parser.ex index d40d32ac03..aef8ec203e 100644 --- a/deps/rabbitmq_cli/lib/parser.ex +++ b/deps/rabbitmq_cli/lib/parser.ex @@ -17,12 +17,13 @@ defmodule Parser do # Input: A list of strings - # Output: A 2-tuple of lists: one containing the command, + # Output: A 2-tuple of lists: one containing the command, # one containing flagged options. def parse(command) do {options, cmd, invalid} = OptionParser.parse( command, - switches: [node: :atom, quiet: :boolean, timeout: :integer], + switches: [node: :atom, quiet: :boolean, timeout: :integer, + online: :boolean, offline: :boolean], aliases: [p: :param, n: :node, q: :quiet, t: :timeout] ) {clear_on_empty_command(cmd), options_map(options, invalid)} diff --git a/deps/rabbitmq_cli/lib/rpc_stream.ex b/deps/rabbitmq_cli/lib/rpc_stream.ex new file mode 100644 index 0000000000..b6f422444d --- /dev/null +++ b/deps/rabbitmq_cli/lib/rpc_stream.ex @@ -0,0 +1,47 @@ +defmodule RpcStream do + def receive_list_items(node, mod, fun, args, timeout, info_keys) do + pid = Kernel.self + ref = Kernel.make_ref + init_items_stream(node, mod, fun, args, timeout, pid, ref) + Stream.unfold(:continue, + fn + :finished -> nil; + :continue -> + receive do + {ref, :finished} -> nil; + {ref, {:timeout, t}} -> Kernel.exit({:error, {:timeout, (t / 1000)}}); + {ref, result, :continue} -> {result, :continue}; + {:error, error} -> {error, :finished}; + other -> Kernel.exit({:unexpected_message_in_items_stream, other}) + end + end) + |> info_for_keys(info_keys) + end + + defp init_items_stream(node, mod, fun, args, timeout, pid, ref) do + Kernel.spawn_link( + fn() -> + case :rabbit_misc.rpc_call(node, mod, fun, args, ref, pid, timeout) do + {:error, _} = error -> send(pid, {:error, error}); + {:bad_argument, _} = error -> send(pid, {:error, error}); + _ -> :ok + end + end) + set_stream_timeout(pid, ref, timeout) + end + + defp set_stream_timeout(_, _, :infinity) do + :ok + end + defp set_stream_timeout(pid, ref, timeout) do + Process.send_after(pid, {ref, {:timeout, timeout}}, timeout) + end + + defp info_for_keys(items, []) do + items + end + defp info_for_keys(items, info_keys) do + Enum.map(items, + &Enum.filter(&1, fn({k,_}) -> Enum.member?(info_keys, k) end)) + end +end \ No newline at end of file From b1b90b7131eb5c3bc2122326bff4c9bc3b0bceaa Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Thu, 5 May 2016 15:29:45 +0100 Subject: [PATCH 02/39] wip. testing queues command --- deps/rabbitmq_cli/lib/info_keys.ex | 23 ++++ .../rabbitmq_cli/lib/list_bindings_command.ex | 16 +++ .../rabbitmq_cli/lib/list_channels_command.ex | 17 +++ .../lib/list_connections_command.ex | 16 +++ .../lib/list_consumers_command.ex | 16 +++ .../lib/list_exchanges_command.ex | 16 +++ deps/rabbitmq_cli/lib/rpc_stream.ex | 33 ++--- deps/rabbitmq_cli/mix.exs | 11 ++ .../test/list_queues_command_test.exs | 119 ++++++++++++++++++ deps/rabbitmq_cli/test/test_helper.exs | 13 ++ 10 files changed, 266 insertions(+), 14 deletions(-) create mode 100644 deps/rabbitmq_cli/test/list_queues_command_test.exs diff --git a/deps/rabbitmq_cli/lib/info_keys.ex b/deps/rabbitmq_cli/lib/info_keys.ex index c1fcf0919e..3cf12aabbe 100644 --- a/deps/rabbitmq_cli/lib/info_keys.ex +++ b/deps/rabbitmq_cli/lib/info_keys.ex @@ -1,4 +1,10 @@ defmodule InfoKeys do + require Record + + Record.defrecord(:resource, :resource, + Record.extract(:resource, + from_lib: "rabbit_common/include/rabbit.hrl")) + def with_valid_info_keys(args, valid_keys, fun) do info_keys = Enum.map(args, &String.to_atom/1) case invalid_info_keys(info_keys, valid_keys) do @@ -13,4 +19,21 @@ defmodule InfoKeys do # It's faster than converting to sets for small lists for key <- info_keys, not Enum.member?(valid_keys, key), do: key end + + def info_for_keys(item, []) do + item + end + def info_for_keys(item, info_keys) do + Enum.filter_map(item, + fn({k, _}) -> Enum.member?(info_keys, k) end, + fn({k, v}) -> {k, format_info_item(v)} end) + end + + defp format_info_item(res) when Record.is_record(res, :resource) do + rec = resource() + resource(res, :name) + end + defp format_info_item(any) do + any + end end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_bindings_command.ex b/deps/rabbitmq_cli/lib/list_bindings_command.ex index 94fedd9fa1..fcd7e95187 100644 --- a/deps/rabbitmq_cli/lib/list_bindings_command.ex +++ b/deps/rabbitmq_cli/lib/list_bindings_command.ex @@ -1,3 +1,19 @@ +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is GoPivotal, Inc. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + defmodule ListBindingsCommand do @behaviour Command diff --git a/deps/rabbitmq_cli/lib/list_channels_command.ex b/deps/rabbitmq_cli/lib/list_channels_command.ex index b6344104cf..2c5f3f8d3b 100644 --- a/deps/rabbitmq_cli/lib/list_channels_command.ex +++ b/deps/rabbitmq_cli/lib/list_channels_command.ex @@ -1,3 +1,20 @@ +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is GoPivotal, Inc. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. +## + + defmodule ListChannelsCommand do @behaviour CommandBehaviour diff --git a/deps/rabbitmq_cli/lib/list_connections_command.ex b/deps/rabbitmq_cli/lib/list_connections_command.ex index 763fe98687..9efd06a63a 100644 --- a/deps/rabbitmq_cli/lib/list_connections_command.ex +++ b/deps/rabbitmq_cli/lib/list_connections_command.ex @@ -1,3 +1,19 @@ +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is GoPivotal, Inc. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + defmodule ListConnectionsCommand do @behaviour CommandBehaviour diff --git a/deps/rabbitmq_cli/lib/list_consumers_command.ex b/deps/rabbitmq_cli/lib/list_consumers_command.ex index 9135783a7d..cfc077d245 100644 --- a/deps/rabbitmq_cli/lib/list_consumers_command.ex +++ b/deps/rabbitmq_cli/lib/list_consumers_command.ex @@ -1,3 +1,19 @@ +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is GoPivotal, Inc. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + defmodule ListConsumersCommand do @behaviour CommandBehaviour diff --git a/deps/rabbitmq_cli/lib/list_exchanges_command.ex b/deps/rabbitmq_cli/lib/list_exchanges_command.ex index c2c9e5137b..782c02fce2 100644 --- a/deps/rabbitmq_cli/lib/list_exchanges_command.ex +++ b/deps/rabbitmq_cli/lib/list_exchanges_command.ex @@ -1,3 +1,19 @@ +## The contents of this file are subject to the Mozilla Public License +## Version 1.1 (the "License"); you may not use this file except in +## compliance with the License. You may obtain a copy of the License +## at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" +## basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +## the License for the specific language governing rights and +## limitations under the License. +## +## The Original Code is RabbitMQ. +## +## The Initial Developer of the Original Code is GoPivotal, Inc. +## Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved. + + defmodule ListExchangesCommand do @behaviour CommandBehaviour diff --git a/deps/rabbitmq_cli/lib/rpc_stream.ex b/deps/rabbitmq_cli/lib/rpc_stream.ex index b6f422444d..a593d56d84 100644 --- a/deps/rabbitmq_cli/lib/rpc_stream.ex +++ b/deps/rabbitmq_cli/lib/rpc_stream.ex @@ -1,4 +1,8 @@ defmodule RpcStream do + def receive_list_items(_node, _mod, _fun, _args, 0, _info_keys) do + #It will timeout anyway, so we don't waste broker resources + [{:badrpc, {:timeout, 0.0}}] + end def receive_list_items(node, mod, fun, args, timeout, info_keys) do pid = Kernel.self ref = Kernel.make_ref @@ -8,14 +12,21 @@ defmodule RpcStream do :finished -> nil; :continue -> receive do - {ref, :finished} -> nil; - {ref, {:timeout, t}} -> Kernel.exit({:error, {:timeout, (t / 1000)}}); - {ref, result, :continue} -> {result, :continue}; - {:error, error} -> {error, :finished}; - other -> Kernel.exit({:unexpected_message_in_items_stream, other}) + {^ref, :finished} -> nil; + {^ref, {:timeout, t}} -> {{:error, {:badrpc, {:timeout, (t / 1000)}}}, :finished}; + {^ref, result, :continue} -> {result, :continue}; + {:error, _} = error -> {error, :finished}; + other -> Kernel.exit({:unexpected_message_in_items_stream, other}) end end) - |> info_for_keys(info_keys) + |> display_list_items(info_keys) + end + + defp display_list_items(items, info_keys) do + Enum.map(items, fn({:error, error}) -> error; + (item) -> + InfoKeys.info_for_keys(item, info_keys) + end) end defp init_items_stream(node, mod, fun, args, timeout, pid, ref) do @@ -24,9 +35,11 @@ defmodule RpcStream do case :rabbit_misc.rpc_call(node, mod, fun, args, ref, pid, timeout) do {:error, _} = error -> send(pid, {:error, error}); {:bad_argument, _} = error -> send(pid, {:error, error}); + {:badrpc, _} = error -> send(pid, {:error, error}); _ -> :ok end end) + IO.puts("set Stream timeout") set_stream_timeout(pid, ref, timeout) end @@ -36,12 +49,4 @@ defmodule RpcStream do defp set_stream_timeout(pid, ref, timeout) do Process.send_after(pid, {ref, {:timeout, timeout}}, timeout) end - - defp info_for_keys(items, []) do - items - end - defp info_for_keys(items, info_keys) do - Enum.map(items, - &Enum.filter(&1, fn({k,_}) -> Enum.member?(info_keys, k) end)) - end end \ No newline at end of file diff --git a/deps/rabbitmq_cli/mix.exs b/deps/rabbitmq_cli/mix.exs index 714ea93281..d777c1a4ab 100644 --- a/deps/rabbitmq_cli/mix.exs +++ b/deps/rabbitmq_cli/mix.exs @@ -52,6 +52,17 @@ defmodule RabbitMQCtl.Mixfile do :rabbit_common, git: "https://github.com/rabbitmq/rabbitmq-common.git", branch: "stable" + }, + { + :amqp_client, + git: "https://github.com/rabbitmq/rabbitmq-erlang-client.git", + branch: "stable", + override: true + }, + { + :amqp, + git: "https://github.com/pma/amqp.git", + branch: "master" } ] end diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs new file mode 100644 index 0000000000..f2d622096b --- /dev/null +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -0,0 +1,119 @@ +defmodule ListQueuesCommandTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import TestHelper + + @vhost "test1" + @user "guest" + @root "/" + @default_timeout :infinity + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + add_vhost @vhost + set_permissions @user, @vhost, [".*", ".*", ".*"] + on_exit(fn -> + delete_vhost @vhost + end) + { + :ok, + opts: %{ + node: get_rabbit_hostname, + timeout: context[:test_timeout] || @default_timeout, + param: @vhost + } + } + end + + @tag test_timeout: :infinity + test "return bad_info_key on a single bad arg", context do + capture_io(fn -> + assert ListQueuesCommand.run(["quack"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + end) + end + + @tag test_timeout: :infinity + test "multiple bad args return a list of bad info key values", context do + capture_io(fn -> + assert ListQueuesCommand.run(["quack", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:quack, :oink]}} + end) + end + + @tag test_timeout: :infinity + test "return bad_info_key on mix of good and bad args", context do + capture_io(fn -> + assert ListQueuesCommand.run(["quack", "messages"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + assert ListQueuesCommand.run(["name", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + assert ListQueuesCommand.run(["name", "oink", "messages"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + end) + end + + @tag test_timeout: 0 + test "zero timeout causes command to return a bad RPC", context do + # capture_io(fn -> + assert ListQueuesCommand.run([], context[:opts]) == + [{:badrpc, {:timeout, 0.0}}] + # end) + end + + @tag test_timeout: 1 + test "command timeout return badrpc", context do + # We hope that broker will be unable to list 1000 queues in 1 millisecond. + for i <- 1..1000 do + declare_queue("test_queue_" <> Integer.to_string(i), @vhost) + end + # capture_io(fn -> + assert ListQueuesCommand.run([], context[:opts]) == + [{:badrpc, {:timeout, 0.001}}] + # end) + end + + test "no info keys returns names and message count", context do + queue_name = "test_queue" + message_count = 3 + declare_queue(queue_name, @vhost) + publish_messages(queue_name, 3) + # capture_io(fn -> + assert ListQueuesCommand.run([], context[:opts]) == + [[name: queue_name, messages: message_count]] + # end) + end + + test "return multiple queues", context do + declare_queue("test_queue_1", @vhost) + publish_messages("test_queue_1", 3) + declare_queue("test_queue_2", @vhost) + publish_messages("test_queue_2", 1) + # capture_io(fn -> + assert ListQueuesCommand.run([], context[:opts]) == + [[name: "test_queue_1", messages: 3], + [name: "test_queue_2", messages: 1]] + # end) + end + + def publish_messages(name, count) do + with_channel(@vhost, fn(channel) -> + for i <- 1..count do + AMQP.Basic.publish(channel, "", name, + "test_message" <> Integer.to_string(i)) + end + end) + end + +end diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 55a81df392..4be7d4525d 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -79,6 +79,12 @@ defmodule TestHelper do :rpc.call(get_rabbit_hostname, :rabbit_auth_backend_internal, :set_permissions, [user, vhost, conf, write, read]) end + def declare_queue(name, vhost, durable \\ false, auto_delete \\ false, args \\ [], owner \\ :none) do + queue_name = :rabbit_misc.r(vhost, :queue, name) + :rpc.call(get_rabbit_hostname, :rabbit_amqqueue, :declare, + [queue_name, durable, auto_delete, args, owner]) + end + def list_permissions(vhost) do :rpc.call( get_rabbit_hostname, @@ -100,4 +106,11 @@ defmodule TestHelper do def error_check(cmd_line, code) do assert catch_exit(RabbitMQCtl.main(cmd_line)) == {:shutdown, code} end + + def with_channel(vhost, fun) do + {:ok, conn} = AMQP.Connection.open(virtual_host: vhost) + {:ok, chan} = AMQP.Channel.open(conn) + fun.(chan) + AMQP.Connection.close(conn) + end end From 670e7bbe47d71843a396abca4afa5473ff083866 Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Mon, 9 May 2016 12:33:10 +0100 Subject: [PATCH 03/39] RpcStream tests --- deps/rabbitmq_cli/lib/info_keys.ex | 2 +- deps/rabbitmq_cli/lib/rpc_stream.ex | 5 -- .../test/list_queues_command_test.exs | 45 ++++++++++--- deps/rabbitmq_cli/test/rpc_stream_test.exs | 67 +++++++++++++++++++ deps/rabbitmq_cli/test/test_helper.exs | 9 +++ 5 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 deps/rabbitmq_cli/test/rpc_stream_test.exs diff --git a/deps/rabbitmq_cli/lib/info_keys.ex b/deps/rabbitmq_cli/lib/info_keys.ex index 3cf12aabbe..4aa7cf498c 100644 --- a/deps/rabbitmq_cli/lib/info_keys.ex +++ b/deps/rabbitmq_cli/lib/info_keys.ex @@ -17,7 +17,7 @@ defmodule InfoKeys do defp invalid_info_keys(info_keys, valid_keys) do # Difference between enums. # It's faster than converting to sets for small lists - for key <- info_keys, not Enum.member?(valid_keys, key), do: key + info_keys -- valid_keys end def info_for_keys(item, []) do diff --git a/deps/rabbitmq_cli/lib/rpc_stream.ex b/deps/rabbitmq_cli/lib/rpc_stream.ex index a593d56d84..38b0393939 100644 --- a/deps/rabbitmq_cli/lib/rpc_stream.ex +++ b/deps/rabbitmq_cli/lib/rpc_stream.ex @@ -1,8 +1,4 @@ defmodule RpcStream do - def receive_list_items(_node, _mod, _fun, _args, 0, _info_keys) do - #It will timeout anyway, so we don't waste broker resources - [{:badrpc, {:timeout, 0.0}}] - end def receive_list_items(node, mod, fun, args, timeout, info_keys) do pid = Kernel.self ref = Kernel.make_ref @@ -39,7 +35,6 @@ defmodule RpcStream do _ -> :ok end end) - IO.puts("set Stream timeout") set_stream_timeout(pid, ref, timeout) end diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index f2d622096b..c183b9c06f 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -29,6 +29,7 @@ defmodule ListQueuesCommandTest do { :ok, opts: %{ + quiet: true, node: get_rabbit_hostname, timeout: context[:test_timeout] || @default_timeout, param: @vhost @@ -65,17 +66,17 @@ defmodule ListQueuesCommandTest do end @tag test_timeout: 0 - test "zero timeout causes command to return a bad RPC", context do + test "zero timeout causes command to return badrpc", context do # capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == - [{:badrpc, {:timeout, 0.0}}] + [{:badrpc, :timeout}] # end) end @tag test_timeout: 1 - test "command timeout return badrpc", context do - # We hope that broker will be unable to list 1000 queues in 1 millisecond. - for i <- 1..1000 do + test "command timeout (10000 msg in 1ms) return badrpc with timeout value in seconds", context do + # We hope that broker will be unable to list 10000 queues in 1 millisecond. + for i <- 1..10000 do declare_queue("test_queue_" <> Integer.to_string(i), @vhost) end # capture_io(fn -> @@ -90,7 +91,7 @@ defmodule ListQueuesCommandTest do declare_queue(queue_name, @vhost) publish_messages(queue_name, 3) # capture_io(fn -> - assert ListQueuesCommand.run([], context[:opts]) == + assert ListQueuesCommand.run([], context[:opts]) == [[name: queue_name, messages: message_count]] # end) end @@ -101,16 +102,42 @@ defmodule ListQueuesCommandTest do declare_queue("test_queue_2", @vhost) publish_messages("test_queue_2", 1) # capture_io(fn -> - assert ListQueuesCommand.run([], context[:opts]) == + assert ListQueuesCommand.run([], context[:opts]) == [[name: "test_queue_1", messages: 3], [name: "test_queue_2", messages: 1]] # end) end + test "info keys filter single key", context do + declare_queue("test_queue_1", @vhost) + publish_messages("test_queue_1", 3) + declare_queue("test_queue_2", @vhost) + publish_messages("test_queue_2", 1) + # capture_io(fn -> + assert ListQueuesCommand.run(["name"], context[:opts]) == + [[name: "test_queue_1"], + [name: "test_queue_2"]] + # end) + end + + + test "info keys add additional keys", context do + declare_queue("durable_queue", @vhost, true) + publish_messages("durable_queue", 3) + declare_queue("auto_delete_queue", @vhost, false, true) + publish_messages("auto_delete_queue", 1) + # capture_io(fn -> + assert Keyword.equal?(ListQueuesCommand.run(["name", "messages", "durable", "auto_delete"], context[:opts]), + [[name: "durable_queue", messages: 3, durable: true, auto_delete: false], + [name: "auto_delete_queue", messages: 1, durable: false, auto_delete: true]]) + # end) + end + + def publish_messages(name, count) do with_channel(@vhost, fn(channel) -> - for i <- 1..count do - AMQP.Basic.publish(channel, "", name, + for i <- 1..count do + AMQP.Basic.publish(channel, "", name, "test_message" <> Integer.to_string(i)) end end) diff --git a/deps/rabbitmq_cli/test/rpc_stream_test.exs b/deps/rabbitmq_cli/test/rpc_stream_test.exs new file mode 100644 index 0000000000..962993f776 --- /dev/null +++ b/deps/rabbitmq_cli/test/rpc_stream_test.exs @@ -0,0 +1,67 @@ +defmodule RpcStreamTest do + use ExUnit.Case, async: false + + setup_all do + :rabbit_control_misc.start_distribution() + :ok + end + + test "emit empty list" do + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [[]], :infinity, []) + + assert [] == items + end + + test "emit list without filters" do + list = [:one, :two, :three] + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [list], :infinity, []) + + assert list == items + end + + + test "emit list with filters" do + list = [[one: 1, two: 2, three: 3], [one: 11, two: 12, three: 13]] + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [list], :infinity, [:one, :two]) + + assert [[one: 1, two: 2], [one: 11, two: 12]] == items + end + + + test "emission timeout 0 return badrpc" do + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [[]], 0, []) + + assert [{:badrpc, :timeout}] == items + end + + test "emission timeout return badrpc with timeout value in seconds" do + timeout_fun = fn(x) -> :timer.sleep(1000); x end + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list_map, [[1,2,3], timeout_fun], 100, []) + assert [{:badrpc, {:timeout, 0.1}}] == items + end + + test "emission timeout in progress return badrpc with timeout value in seconds as last element" do + timeout_fun = fn(x) -> :timer.sleep(100); x end + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list_map, [[1,2,3], timeout_fun], 200, []) + assert [1, {:badrpc, {:timeout, 0.2}}] == items + end + + + test "parallel emission do not mix values" do + {:ok, agent} = Agent.start_link(fn() -> :init end) + list1 = [:one, :two, :three] + list2 = [:dog, :cat, :pig] + # Adding timeout to make sure emissions are executed in parallel + timeout_fun = fn(x) -> :timer.sleep(10); x end + Agent.update(agent, + fn(:init) -> + RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list_map, [list2, timeout_fun], :infinity, []) + end) + items1 = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list_map, [list1, timeout_fun], :infinity, []) + items2 = Agent.get(agent, fn(x) -> x end) + + assert items1 == list1 + assert items2 == list2 + end + +end diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 4be7d4525d..2db40c2ab9 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -113,4 +113,13 @@ defmodule TestHelper do fun.(chan) AMQP.Connection.close(conn) end + + def emit_list(list, ref, pid) do + emit_list_map(list, &(&1), ref, pid) + end + + def emit_list_map(list, fun, ref, pid) do + :rabbit_control_misc.emitting_map(pid, ref, fun, list) + end + end From 7c16aa321470eb2d78677bd446f54fc33441aafa Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Mon, 9 May 2016 14:51:20 +0100 Subject: [PATCH 04/39] List excahnges command test --- .../test/list_exchanges_command_test.exs | 170 ++++++++++++++++++ .../test/list_queues_command_test.exs | 94 +++++++--- deps/rabbitmq_cli/test/test_helper.exs | 12 +- 3 files changed, 247 insertions(+), 29 deletions(-) create mode 100644 deps/rabbitmq_cli/test/list_exchanges_command_test.exs diff --git a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs new file mode 100644 index 0000000000..2d1ff06859 --- /dev/null +++ b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs @@ -0,0 +1,170 @@ +defmodule ListExchangesCommandTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import TestHelper + + @vhost "test1" + @user "guest" + @root "/" + @default_timeout :infinity + @default_exchanges [{"amq.direct", :direct}, + {"amq.fanout", :fanout}, + {"amq.match", :headers}, + {"amq.rabbitmq.trace", :topic}, + {"amq.headers", :headers}, + {"amq.topic", :topic}, + {"", :direct}] + + defp default_exchange_names() do + {names, _types} = Enum.unzip(@default_exchanges) + names + end + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + add_vhost @vhost + set_permissions @user, @vhost, [".*", ".*", ".*"] + on_exit(fn -> + delete_vhost @vhost + end) + { + :ok, + opts: %{ + quiet: true, + node: get_rabbit_hostname, + timeout: context[:test_timeout] || @default_timeout, + param: @vhost + } + } + end + + @tag test_timeout: :infinity + test "return bad_info_key on a single bad arg", context do + capture_io(fn -> + assert ListExchangesCommand.run(["quack"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + end) + end + + @tag test_timeout: :infinity + test "multiple bad args return a list of bad info key values", context do + capture_io(fn -> + assert ListExchangesCommand.run(["quack", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:quack, :oink]}} + end) + end + + @tag test_timeout: :infinity + test "return bad_info_key on mix of good and bad args", context do + capture_io(fn -> + assert ListExchangesCommand.run(["quack", "type"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + assert ListExchangesCommand.run(["name", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + assert ListExchangesCommand.run(["name", "oink", "type"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + end) + end + + @tag test_timeout: 0 + test "zero timeout causes command to return badrpc", context do + capture_io(fn -> + assert ListExchangesCommand.run([], context[:opts]) == + [{:badrpc, :timeout}] + end) + end + + test "show default exchanges by default", context do + capture_io(fn -> + assert MapSet.new(ListExchangesCommand.run(["name"], context[:opts])) == + MapSet.new(for {ex_name, ex_type} <- @default_exchanges, do: [name: ex_name]) + end) + end + + test "no info keys returns name and type", context do + exchange_name = "test_exchange" + declare_exchange(exchange_name, @vhost) + capture_io(fn -> + assert MapSet.new(ListExchangesCommand.run([], context[:opts])) == + MapSet.new( + for({ex_name, ex_type} <- @default_exchanges, do: [name: ex_name, type: ex_type]) ++ + [[name: exchange_name, type: :direct]]) + end) + end + + test "list multiple excahnges", context do + declare_exchange("test_exchange_1", @vhost, :direct) + declare_exchange("test_exchange_2", @vhost, :fanout) + capture_io(fn -> + non_default_exchanges = ListExchangesCommand.run(["name", "type"], context[:opts]) + |> without_default_exchanges + assert non_default_exchanges == + [[name: "test_exchange_1", type: :direct], + [name: "test_exchange_2", type: :fanout]] + end) + end + + test "info keys filter single key", context do + declare_exchange("test_exchange_1", @vhost) + declare_exchange("test_exchange_2", @vhost) + capture_io(fn -> + non_default_exchanges = ListExchangesCommand.run(["name"], context[:opts]) + |> without_default_exchanges + assert non_default_exchanges == + [[name: "test_exchange_1"], + [name: "test_exchange_2"]] + end) + end + + + test "info keys add additional keys", context do + declare_exchange("durable_exchange", @vhost, :direct, true) + declare_exchange("auto_delete_exchange", @vhost, :fanout, false, true) + capture_io(fn -> + non_default_exchanges = ListExchangesCommand.run(["name", "type", "durable", "auto_delete"], context[:opts]) + |> without_default_exchanges + assert non_default_exchanges == + [[name: "auto_delete_exchange", type: :fanout, durable: false, auto_delete: true], + [name: "durable_exchange", type: :direct, durable: true, auto_delete: false]] + end) + end + + test "specifying a vhost returns the targeted vhost exchanges", context do + other_vhost = "other_vhost" + add_vhost other_vhost + on_exit(fn -> + delete_vhost other_vhost + end) + declare_exchange("test_exchange_1", @vhost) + declare_exchange("test_exchange_2", other_vhost) + capture_io(fn -> + non_default_exchanges1 = ListExchangesCommand.run(["name"], context[:opts]) + |> without_default_exchanges + + non_default_exchanges2 = ListExchangesCommand.run(["name"], %{context[:opts] | :param => other_vhost}) + |> without_default_exchanges + + assert non_default_exchanges1 == [[name: "test_exchange_1"]] + assert non_default_exchanges2 == [[name: "test_exchange_2"]] + end) + end + + defp without_default_exchanges(xs) do + Enum.filter(xs, + fn(x) -> + not Enum.member?(default_exchange_names(), x[:name]) + end) + end + +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index c183b9c06f..51aa6c6d1d 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -67,10 +67,10 @@ defmodule ListQueuesCommandTest do @tag test_timeout: 0 test "zero timeout causes command to return badrpc", context do - # capture_io(fn -> + capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == [{:badrpc, :timeout}] - # end) + end) end @tag test_timeout: 1 @@ -79,10 +79,10 @@ defmodule ListQueuesCommandTest do for i <- 1..10000 do declare_queue("test_queue_" <> Integer.to_string(i), @vhost) end - # capture_io(fn -> + capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == [{:badrpc, {:timeout, 0.001}}] - # end) + end) end test "no info keys returns names and message count", context do @@ -90,10 +90,10 @@ defmodule ListQueuesCommandTest do message_count = 3 declare_queue(queue_name, @vhost) publish_messages(queue_name, 3) - # capture_io(fn -> - assert ListQueuesCommand.run([], context[:opts]) == - [[name: queue_name, messages: message_count]] - # end) + capture_io(fn -> + assert ListQueuesCommand.run([], context[:opts]) == + [[name: queue_name, messages: message_count]] + end) end test "return multiple queues", context do @@ -101,11 +101,11 @@ defmodule ListQueuesCommandTest do publish_messages("test_queue_1", 3) declare_queue("test_queue_2", @vhost) publish_messages("test_queue_2", 1) - # capture_io(fn -> - assert ListQueuesCommand.run([], context[:opts]) == - [[name: "test_queue_1", messages: 3], - [name: "test_queue_2", messages: 1]] - # end) + capture_io(fn -> + assert ListQueuesCommand.run([], context[:opts]) == + [[name: "test_queue_1", messages: 3], + [name: "test_queue_2", messages: 1]] + end) end test "info keys filter single key", context do @@ -113,11 +113,11 @@ defmodule ListQueuesCommandTest do publish_messages("test_queue_1", 3) declare_queue("test_queue_2", @vhost) publish_messages("test_queue_2", 1) - # capture_io(fn -> - assert ListQueuesCommand.run(["name"], context[:opts]) == - [[name: "test_queue_1"], - [name: "test_queue_2"]] - # end) + capture_io(fn -> + assert ListQueuesCommand.run(["name"], context[:opts]) == + [[name: "test_queue_1"], + [name: "test_queue_2"]] + end) end @@ -126,20 +126,60 @@ defmodule ListQueuesCommandTest do publish_messages("durable_queue", 3) declare_queue("auto_delete_queue", @vhost, false, true) publish_messages("auto_delete_queue", 1) - # capture_io(fn -> - assert Keyword.equal?(ListQueuesCommand.run(["name", "messages", "durable", "auto_delete"], context[:opts]), - [[name: "durable_queue", messages: 3, durable: true, auto_delete: false], - [name: "auto_delete_queue", messages: 1, durable: false, auto_delete: true]]) - # end) + capture_io(fn -> + assert Keyword.equal?( + ListQueuesCommand.run(["name", "messages", "durable", "auto_delete"], context[:opts]), + [[name: "durable_queue", messages: 3, durable: true, auto_delete: false], + [name: "auto_delete_queue", messages: 1, durable: false, auto_delete: true]]) + end) end + test "specifying a vhost returns the targeted vhost queues", context do + other_vhost = "other_vhost" + add_vhost other_vhost + on_exit(fn -> + delete_vhost other_vhost + end) + declare_queue("test_queue_1", @vhost) + declare_queue("test_queue_2", other_vhost) + capture_io(fn -> + assert ListQueuesCommand.run(["name"], context[:opts]) == [[name: "test_queue_1"]] + assert ListQueuesCommand.run(["name"], %{context[:opts] | :param => other_vhost}) == [[name: "test_queue_2"]] + end) + end + + # TODO: list online/offline queues. Require cluster add/remove + # test "list online queues do not show offline queues", context do + # other_node = @secondary_node + # declare_queue("online_queue", @vhost, true) + # publish_messages("online_queue", 3) + # #declare on another node + # declare_queue_on_node(other_node, "offline_queue", @vhost, true) + # publish_messages("offline_queue", 3) + # stop_node(other_node) + + # assert ListQueuesCommand.run(["name"], %{context[:opts] | online: true}) == [[name: "online_queue"]] + # end + + # test "list offline queues do not show online queues", context do + # other_node = @secondary_node + # declare_queue("online_queue", @vhost, true) + # publish_messages("online_queue", 3) + # #declare on another node + # declare_queue_on_node(other_node, "offline_queue", @vhost, true) + # publish_messages("offline_queue", 3) + # stop_node(other_node) + + # assert ListQueuesCommand.run(["name"], %{context[:opts] | offline: true}) == [[name: "offline_queue"]] + # end + def publish_messages(name, count) do with_channel(@vhost, fn(channel) -> - for i <- 1..count do - AMQP.Basic.publish(channel, "", name, - "test_message" <> Integer.to_string(i)) - end + for i <- 1..count do + AMQP.Basic.publish(channel, "", name, + "test_message" <> Integer.to_string(i)) + end end) end diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 2db40c2ab9..74f3310102 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -81,8 +81,16 @@ defmodule TestHelper do def declare_queue(name, vhost, durable \\ false, auto_delete \\ false, args \\ [], owner \\ :none) do queue_name = :rabbit_misc.r(vhost, :queue, name) - :rpc.call(get_rabbit_hostname, :rabbit_amqqueue, :declare, - [queue_name, durable, auto_delete, args, owner]) + :rpc.call(get_rabbit_hostname, + :rabbit_amqqueue, :declare, + [queue_name, durable, auto_delete, args, owner]) + end + + def declare_exchange(name, vhost, type \\ :direct, durable \\ false, auto_delete \\ false, internal \\ false, args \\ []) do + exchange_name = :rabbit_misc.r(vhost, :exchange, name) + :rpc.call(get_rabbit_hostname, + :rabbit_exchange, :declare, + [exchange_name, type, durable, auto_delete, internal, args]) end def list_permissions(vhost) do From e41659852421f266f151b57b60892323e7aa75c2 Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Mon, 9 May 2016 15:49:52 +0100 Subject: [PATCH 05/39] List connections command test --- .../test/list_connections_command_test.exs | 98 +++++++++++++++++++ deps/rabbitmq_cli/test/test_helper.exs | 18 +++- 2 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 deps/rabbitmq_cli/test/list_connections_command_test.exs diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs new file mode 100644 index 0000000000..ba637b5e1f --- /dev/null +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -0,0 +1,98 @@ +defmodule ListConnectionsCommandTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import TestHelper + + @vhost "test1" + @user "guest" + @root "/" + @default_timeout :infinity + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + add_vhost @vhost + set_permissions @user, @vhost, [".*", ".*", ".*"] + on_exit(fn -> + delete_vhost @vhost + end) + { + :ok, + opts: %{ + quiet: true, + node: get_rabbit_hostname, + timeout: context[:test_timeout] || @default_timeout, + param: @vhost + } + } + end + + test "return bad_info_key on a single bad arg", context do + capture_io(fn -> + assert ListConnectionsCommand.run(["quack"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + end) + end + + test "multiple bad args return a list of bad info key values", context do + capture_io(fn -> + assert ListConnectionsCommand.run(["quack", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:quack, :oink]}} + end) + end + + test "return bad_info_key on mix of good and bad args", context do + capture_io(fn -> + assert ListConnectionsCommand.run(["quack", "peer_host"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + assert ListConnectionsCommand.run(["user", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + assert ListConnectionsCommand.run(["user", "oink", "peer_host"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + end) + end + + @tag test_timeout: 0 + test "zero timeout causes command to return badrpc", context do + capture_io(fn -> + assert ListConnectionsCommand.run([], context[:opts]) == + [{:badrpc, :timeout}] + end) + end + + test "no connections by default", context do + capture_io(fn -> + assert [] == ListConnectionsCommand.run([], context[:opts]) + end) + end + + test "user, peer_host, peer_port and state by default", context do + capture_io(fn -> + with_connection(@vhost, fn(conn) -> + conns = ListConnectionsCommand.run([], context[:opts]) + assert Enum.map(conns, &Keyword.keys/1) == [[:user, :peer_host, :peer_port, :state]] + end) + end) + end + + test "filter single key", context do + capture_io(fn -> + with_connection(@vhost, fn(conn) -> + conns = ListConnectionsCommand.run(["name"], context[:opts]) + assert Enum.map(conns, &Keyword.keys/1) == [[:name]] + end) + end) + end + + +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 74f3310102..d19b8959a5 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -116,9 +116,23 @@ defmodule TestHelper do end def with_channel(vhost, fun) do + with_connection(vhost, + fn(conn) -> + {:ok, chan} = AMQP.Channel.open(conn) + fun.(chan) + end) + end + + def with_connection(vhost, fun) do {:ok, conn} = AMQP.Connection.open(virtual_host: vhost) - {:ok, chan} = AMQP.Channel.open(conn) - fun.(chan) + ExUnit.Callbacks.on_exit(fn -> + try do + AMQP.Connection.close(conn) + catch + :exit, _ -> :ok + end + end) + fun.(conn) AMQP.Connection.close(conn) end From c222351f9d4ee0e225f3b3dcac43afb0da473aad Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Mon, 9 May 2016 16:09:21 +0100 Subject: [PATCH 06/39] Connection test show vhost --- .../test/list_connections_command_test.exs | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index ba637b5e1f..64a14a0ff2 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -3,9 +3,7 @@ defmodule ListConnectionsCommandTest do import ExUnit.CaptureIO import TestHelper - @vhost "test1" @user "guest" - @root "/" @default_timeout :infinity setup_all do @@ -21,18 +19,11 @@ defmodule ListConnectionsCommandTest do end setup context do - add_vhost @vhost - set_permissions @user, @vhost, [".*", ".*", ".*"] - on_exit(fn -> - delete_vhost @vhost - end) { :ok, opts: %{ - quiet: true, node: get_rabbit_hostname, - timeout: context[:test_timeout] || @default_timeout, - param: @vhost + timeout: context[:test_timeout] || @default_timeout } } end @@ -78,7 +69,7 @@ defmodule ListConnectionsCommandTest do test "user, peer_host, peer_port and state by default", context do capture_io(fn -> - with_connection(@vhost, fn(conn) -> + with_connection("/", fn(conn) -> conns = ListConnectionsCommand.run([], context[:opts]) assert Enum.map(conns, &Keyword.keys/1) == [[:user, :peer_host, :peer_port, :state]] end) @@ -87,12 +78,27 @@ defmodule ListConnectionsCommandTest do test "filter single key", context do capture_io(fn -> - with_connection(@vhost, fn(conn) -> + with_connection("/", fn(conn) -> conns = ListConnectionsCommand.run(["name"], context[:opts]) assert Enum.map(conns, &Keyword.keys/1) == [[:name]] end) end) end + test "show connection vhost", context do + vhost = "custom_vhost" + add_vhost vhost + set_permissions @user, vhost, [".*", ".*", ".*"] + on_exit(fn -> + delete_vhost @vhost + end) + capture_io(fn -> + with_connection(vhost, fn(conn) -> + conns = ListConnectionsCommand.run(["vhost"], context[:opts]) + assert conns == [[vhost: vhost]] + end) + end) + end + end \ No newline at end of file From 52a9aa2c965bdc8065015738cfdbbd8e130233ac Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Mon, 9 May 2016 18:38:46 +0100 Subject: [PATCH 07/39] More broker display tests --- deps/rabbitmq_cli/lib/info_keys.ex | 5 +- .../rabbitmq_cli/lib/list_bindings_command.ex | 7 +- .../lib/list_consumers_command.ex | 28 ++-- deps/rabbitmq_cli/lib/rpc_stream.ex | 90 ++++++------ .../test/list_bindings_command_test.exs | 102 +++++++++++++ .../test/list_channels_command_test.exs | 121 ++++++++++++++++ .../test/list_connections_command_test.exs | 2 +- .../test/list_consumers_command_test.exs | 136 ++++++++++++++++++ .../test/list_queues_command_test.exs | 13 ++ deps/rabbitmq_cli/test/rpc_stream_test.exs | 7 + 10 files changed, 454 insertions(+), 57 deletions(-) create mode 100644 deps/rabbitmq_cli/test/list_bindings_command_test.exs create mode 100644 deps/rabbitmq_cli/test/list_channels_command_test.exs create mode 100644 deps/rabbitmq_cli/test/list_consumers_command_test.exs diff --git a/deps/rabbitmq_cli/lib/info_keys.ex b/deps/rabbitmq_cli/lib/info_keys.ex index 4aa7cf498c..32b2d395f4 100644 --- a/deps/rabbitmq_cli/lib/info_keys.ex +++ b/deps/rabbitmq_cli/lib/info_keys.ex @@ -20,10 +20,13 @@ defmodule InfoKeys do info_keys -- valid_keys end + + def info_for_keys(item, []) do item end - def info_for_keys(item, info_keys) do + + def info_for_keys([{_,_}|_] = item, info_keys) do Enum.filter_map(item, fn({k, _}) -> Enum.member?(info_keys, k) end, fn({k, v}) -> {k, format_info_item(v)} end) diff --git a/deps/rabbitmq_cli/lib/list_bindings_command.ex b/deps/rabbitmq_cli/lib/list_bindings_command.ex index fcd7e95187..0558c7c7d0 100644 --- a/deps/rabbitmq_cli/lib/list_bindings_command.ex +++ b/deps/rabbitmq_cli/lib/list_bindings_command.ex @@ -15,7 +15,7 @@ defmodule ListBindingsCommand do - @behaviour Command + @behaviour CommandBehaviour @info_keys ~w(source_name source_kind destination_name destination_kind routing_key arguments)a @@ -39,7 +39,6 @@ defmodule ListBindingsCommand do opts) end def run([_|_] = args, %{node: node_name, timeout: timeout, param: vhost} = opts) do - info_keys = Enum.map(args, &String.to_atom/1) InfoKeys.with_valid_info_keys(args, @info_keys, fn(info_keys) -> info(opts) @@ -51,7 +50,7 @@ defmodule ListBindingsCommand do info_keys) end) end - def run([_|_] = args, %{node: node_name, timeout: timeout} = opts) do + def run([_|_] = args, %{node: _node_name, timeout: _timeout} = opts) do run(args, Map.merge(default_opts, opts)) end @@ -60,6 +59,6 @@ defmodule ListBindingsCommand do end defp info(%{quiet: true}), do: nil - defp info(_), do: IO.puts "Listing bindings ..." + defp info(%{param: vhost}), do: IO.puts "Listing bindings for vhost #{vhost} ..." end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/list_consumers_command.ex b/deps/rabbitmq_cli/lib/list_consumers_command.ex index cfc077d245..793d0a8ab4 100644 --- a/deps/rabbitmq_cli/lib/list_consumers_command.ex +++ b/deps/rabbitmq_cli/lib/list_consumers_command.ex @@ -17,6 +17,9 @@ defmodule ListConsumersCommand do @behaviour CommandBehaviour + @info_keys ~w(queue_name channel_pid consumer_tag + ack_required prefetch_count arguments)a + def flags() do [] end @@ -25,14 +28,21 @@ defmodule ListConsumersCommand do "list_consumers [-p vhost]" end - def run(_args, %{node: node_name, timeout: timeout, param: vhost} = opts) do - info(opts) - node_name - |> Helpers.parse_node - |> RpcStream.receive_list_items(:rabbit_amqqueue, :consumers_all, - [vhost], timeout, []) + def run([], opts) do + run(Enum.map(@info_keys, &Atom.to_string/1), opts) end - def run(args, %{node: node_name, timeout: timeout} = opts) do + + def run([_|_] = args, %{node: node_name, timeout: timeout, param: vhost} = opts) do + InfoKeys.with_valid_info_keys(args, @info_keys, + fn(info_keys) -> + info(opts) + node_name + |> Helpers.parse_node + |> RpcStream.receive_list_items(:rabbit_amqqueue, :consumers_all, + [vhost], timeout, info_keys) + end) + end + def run(args, %{node: _node_name, timeout: _timeout} = opts) do run(args, Map.merge(default_opts, opts)) end @@ -40,6 +50,6 @@ defmodule ListConsumersCommand do %{param: "/"} end - defp info(%{quiet: true}), do: nil - defp info(_), do: IO.puts "Listing channels ..." + defp info(%{quiet: true}), do: nil + defp info(%{param: vhost}), do: IO.puts "Listing channels on vhost #{vhost} ..." end \ No newline at end of file diff --git a/deps/rabbitmq_cli/lib/rpc_stream.ex b/deps/rabbitmq_cli/lib/rpc_stream.ex index 38b0393939..3de6a43f20 100644 --- a/deps/rabbitmq_cli/lib/rpc_stream.ex +++ b/deps/rabbitmq_cli/lib/rpc_stream.ex @@ -1,47 +1,53 @@ defmodule RpcStream do - def receive_list_items(node, mod, fun, args, timeout, info_keys) do - pid = Kernel.self - ref = Kernel.make_ref - init_items_stream(node, mod, fun, args, timeout, pid, ref) - Stream.unfold(:continue, - fn - :finished -> nil; - :continue -> - receive do - {^ref, :finished} -> nil; - {^ref, {:timeout, t}} -> {{:error, {:badrpc, {:timeout, (t / 1000)}}}, :finished}; - {^ref, result, :continue} -> {result, :continue}; - {:error, _} = error -> {error, :finished}; - other -> Kernel.exit({:unexpected_message_in_items_stream, other}) - end - end) - |> display_list_items(info_keys) - end + def receive_list_items(node, mod, fun, args, timeout, info_keys) do + pid = Kernel.self + ref = Kernel.make_ref + init_items_stream(node, mod, fun, args, timeout, pid, ref) + Stream.unfold(:continue, + fn + :finished -> nil; + :continue -> + receive do + {^ref, :finished} -> nil; + {^ref, {:timeout, t}} -> {{:error, {:badrpc, {:timeout, (t / 1000)}}}, :finished}; + {^ref, result, :continue} -> {result, :continue}; + {:error, _} = error -> {error, :finished} + end + end) + |> display_list_items(info_keys) + end - defp display_list_items(items, info_keys) do - Enum.map(items, fn({:error, error}) -> error; - (item) -> - InfoKeys.info_for_keys(item, info_keys) - end) - end - defp init_items_stream(node, mod, fun, args, timeout, pid, ref) do - Kernel.spawn_link( - fn() -> - case :rabbit_misc.rpc_call(node, mod, fun, args, ref, pid, timeout) do - {:error, _} = error -> send(pid, {:error, error}); - {:bad_argument, _} = error -> send(pid, {:error, error}); - {:badrpc, _} = error -> send(pid, {:error, error}); - _ -> :ok - end - end) - set_stream_timeout(pid, ref, timeout) - end + defp display_list_items(items, info_keys) do + items + |> Stream.filter(fn([]) -> false; (_) -> true end) + |> Enum.map( + fn({:error, error}) -> error; + # if item is list of keyword lists: + ([[{_,_}|_]|_] = item) -> + Enum.map(item, fn(i) -> InfoKeys.info_for_keys(i, info_keys) end); + (item) -> + InfoKeys.info_for_keys(item, info_keys) + end) + end - defp set_stream_timeout(_, _, :infinity) do - :ok - end - defp set_stream_timeout(pid, ref, timeout) do - Process.send_after(pid, {ref, {:timeout, timeout}}, timeout) - end + defp init_items_stream(node, mod, fun, args, timeout, pid, ref) do + Kernel.spawn_link( + fn() -> + case :rabbit_misc.rpc_call(node, mod, fun, args, ref, pid, timeout) do + {:error, _} = error -> send(pid, {:error, error}); + {:bad_argument, _} = error -> send(pid, {:error, error}); + {:badrpc, _} = error -> send(pid, {:error, error}); + _ -> :ok + end + end) + set_stream_timeout(pid, ref, timeout) + end + + defp set_stream_timeout(_, _, :infinity) do + :ok + end + defp set_stream_timeout(pid, ref, timeout) do + Process.send_after(pid, {ref, {:timeout, timeout}}, timeout) + end end \ No newline at end of file diff --git a/deps/rabbitmq_cli/test/list_bindings_command_test.exs b/deps/rabbitmq_cli/test/list_bindings_command_test.exs new file mode 100644 index 0000000000..8e627dde90 --- /dev/null +++ b/deps/rabbitmq_cli/test/list_bindings_command_test.exs @@ -0,0 +1,102 @@ +defmodule ListBindingsCommandTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import TestHelper + + @vhost "test1" + @user "guest" + @root "/" + @default_timeout :infinity + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + add_vhost @vhost + set_permissions @user, @vhost, [".*", ".*", ".*"] + on_exit(fn -> + delete_vhost @vhost + end) + { + :ok, + opts: %{ + node: get_rabbit_hostname, + timeout: context[:test_timeout] || @default_timeout, + param: @vhost + } + } + end + + @tag test_timeout: :infinity + test "return bad_info_key on a single bad arg", context do + capture_io(fn -> + assert ListBindingsCommand.run(["quack"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + end) + end + + @tag test_timeout: :infinity + test "multiple bad args return a list of bad info key values", context do + capture_io(fn -> + assert ListBindingsCommand.run(["quack", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:quack, :oink]}} + end) + end + + @tag test_timeout: :infinity + test "return bad_info_key on mix of good and bad args", context do + capture_io(fn -> + assert ListBindingsCommand.run(["quack", "source_name"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + assert ListBindingsCommand.run(["source_name", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + assert ListBindingsCommand.run(["source_kind", "oink", "source_name"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + end) + end + + @tag test_timeout: 0 + test "zero timeout causes command to return badrpc", context do + capture_io(fn -> + assert ListBindingsCommand.run([], context[:opts]) == + [{:badrpc, :timeout}] + end) + end + + test "no bindings for no queues", context do + capture_io(fn -> + [] = ListBindingsCommand.run([], context[:opts]) + end) + end + + test "by default returns all info keys", context do + default_keys = ~w(source_name source_kind destination_name destination_kind routing_key arguments)a + capture_io(fn -> + declare_queue("test_queue", @vhost) + :timer.sleep(100) + + [binding] = ListBindingsCommand.run([], context[:opts]) + assert default_keys == Keyword.keys(binding) + end) + end + + test "can filter info keys", context do + wanted_keys = ~w(source_name destination_name routing_key) + capture_io(fn -> + declare_queue("test_queue", @vhost) + assert ListBindingsCommand.run(wanted_keys, context[:opts]) == + [[source_name: "", destination_name: "test_queue", routing_key: "test_queue"]] + + end) + end + +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/test/list_channels_command_test.exs b/deps/rabbitmq_cli/test/list_channels_command_test.exs new file mode 100644 index 0000000000..ea9dc6a14c --- /dev/null +++ b/deps/rabbitmq_cli/test/list_channels_command_test.exs @@ -0,0 +1,121 @@ +defmodule ListChannelsCommandTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import TestHelper + + @user "guest" + @default_timeout :infinity + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + { + :ok, + opts: %{ + node: get_rabbit_hostname, + timeout: context[:test_timeout] || @default_timeout + } + } + end + + test "return bad_info_key on a single bad arg", context do + capture_io(fn -> + assert ListChannelsCommand.run(["quack"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + end) + end + + test "multiple bad args return a list of bad info key values", context do + capture_io(fn -> + assert ListChannelsCommand.run(["quack", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:quack, :oink]}} + end) + end + + test "return bad_info_key on mix of good and bad args", context do + capture_io(fn -> + assert ListChannelsCommand.run(["quack", "pid"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + assert ListChannelsCommand.run(["user", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + assert ListChannelsCommand.run(["user", "oink", "pid"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + end) + end + + @tag test_timeout: 0 + test "zero timeout causes command to return badrpc", context do + capture_io(fn -> + assert ListChannelsCommand.run([], context[:opts]) == + [{:badrpc, :timeout}] + end) + end + + test "no channels by default", context do + capture_io(fn -> + assert [] == ListChannelsCommand.run([], context[:opts]) + end) + end + + test "default channel info keys are pid, user, consumer_count, and messages_unacknowledged", context do + capture_io(fn -> + with_channel("/", fn(_channel) -> + [chan] = ListChannelsCommand.run([], context[:opts]) + assert Keyword.keys(chan) == ~w(pid user consumer_count messages_unacknowledged)a + assert [user: "guest", consumer_count: 0, messages_unacknowledged: 0] == Keyword.delete(chan, :pid) + end) + end) + end + + test "multiple channels on multiple connections", context do + capture_io(fn -> + with_channel("/", fn(_channel1) -> + with_channel("/", fn(_channel2) -> + [chan1, chan2] = ListChannelsCommand.run(["pid", "user", "connection"], context[:opts]) + assert Keyword.keys(chan1) == ~w(pid user connection)a + assert Keyword.keys(chan2) == ~w(pid user connection)a + assert "guest" == chan1[:user] + assert "guest" == chan2[:user] + assert chan1[:pid] !== chan2[:pid] + assert chan1[:connection] !== chan2[:connection] + end) + end) + end) + end + + test "multiple channels on single connection", context do + capture_io(fn -> + with_connection("/", fn(conn) -> + {:ok, _} = AMQP.Channel.open(conn) + {:ok, _} = AMQP.Channel.open(conn) + + [chan1, chan2] = ListChannelsCommand.run(["pid", "user", "connection"], context[:opts]) + assert Keyword.keys(chan1) == ~w(pid user connection)a + assert Keyword.keys(chan2) == ~w(pid user connection)a + assert "guest" == chan1[:user] + assert "guest" == chan2[:user] + assert chan1[:pid] !== chan2[:pid] + assert chan1[:connection] == chan2[:connection] + end) + end) + end + + test "info keys order is preserved", context do + capture_io(fn -> + with_channel("/", fn(_channel) -> + [chan] = ListChannelsCommand.run(~w(connection vhost name pid number user), context[:opts]) + assert Keyword.keys(chan) == ~w(connection vhost name pid number user)a + end) + end) + end +end \ No newline at end of file diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index 64a14a0ff2..6dd808fa3a 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -90,7 +90,7 @@ defmodule ListConnectionsCommandTest do add_vhost vhost set_permissions @user, vhost, [".*", ".*", ".*"] on_exit(fn -> - delete_vhost @vhost + delete_vhost vhost end) capture_io(fn -> with_connection(vhost, fn(conn) -> diff --git a/deps/rabbitmq_cli/test/list_consumers_command_test.exs b/deps/rabbitmq_cli/test/list_consumers_command_test.exs new file mode 100644 index 0000000000..d9cded1d36 --- /dev/null +++ b/deps/rabbitmq_cli/test/list_consumers_command_test.exs @@ -0,0 +1,136 @@ +defmodule ListConsumersCommandTest do + use ExUnit.Case, async: false + import ExUnit.CaptureIO + import TestHelper + + @vhost "test1" + @user "guest" + @default_timeout :infinity + + setup_all do + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + + :ok + end + + setup context do + add_vhost @vhost + set_permissions @user, @vhost, [".*", ".*", ".*"] + on_exit(fn -> + delete_vhost @vhost + end) + { + :ok, + opts: %{ + node: get_rabbit_hostname, + timeout: context[:test_timeout] || @default_timeout, + param: @vhost + } + } + end + + @tag test_timeout: :infinity + test "return bad_info_key on a single bad arg", context do + capture_io(fn -> + assert ListConsumersCommand.run(["quack"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + end) + end + + @tag test_timeout: :infinity + test "multiple bad args return a list of bad info key values", context do + capture_io(fn -> + assert ListConsumersCommand.run(["quack", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:quack, :oink]}} + end) + end + + @tag test_timeout: :infinity + test "return bad_info_key on mix of good and bad args", context do + capture_io(fn -> + assert ListConsumersCommand.run(["quack", "queue_name"], context[:opts]) == + {:error, {:bad_info_key, [:quack]}} + assert ListConsumersCommand.run(["queue_name", "oink"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + assert ListConsumersCommand.run(["channel_pid", "oink", "queue_name"], context[:opts]) == + {:error, {:bad_info_key, [:oink]}} + end) + end + + @tag test_timeout: 0 + test "zero timeout causes command to return badrpc", context do + capture_io(fn -> + assert ListConsumersCommand.run([], context[:opts]) == + [{:badrpc, :timeout}] + end) + end + + test "no consumers for no queues", context do + capture_io(fn -> + [] = ListConsumersCommand.run([], context[:opts]) + end) + end + + test "all info keys by default", context do + queue_name = "test_queue1" + consumer_tag = "i_am_consumer" + info_keys = ~w(queue_name channel_pid consumer_tag ack_required prefetch_count arguments)a + capture_io(fn -> + declare_queue(queue_name, @vhost) + with_channel(@vhost, fn(channel) -> + {:ok, _} = AMQP.Basic.consume(channel, queue_name, nil, [consumer_tag: consumer_tag]) + [[consumer]] = ListConsumersCommand.run([], context[:opts]) + assert info_keys == Keyword.keys(consumer) + assert consumer[:consumer_tag] == consumer_tag + assert consumer[:queue_name] == queue_name + assert Keyword.delete(consumer, :channel_pid) == + [queue_name: queue_name, consumer_tag: consumer_tag, + ack_required: true, prefetch_count: 0, arguments: []] + + end) + end) + end + + test "consumers are grouped by queues (single consumer per queue)", context do + queue_name1 = "test_queue1" + queue_name2 = "test_queue2" + capture_io(fn -> + declare_queue("test_queue1", @vhost) + declare_queue("test_queue2", @vhost) + with_channel(@vhost, fn(channel) -> + {:ok, tag1} = AMQP.Basic.consume(channel, queue_name1) + {:ok, tag2} = AMQP.Basic.consume(channel, queue_name2) + [[consumer1], [consumer2]] = ListConsumersCommand.run(["queue_name", "consumer_tag"], context[:opts]) + assert [queue_name: queue_name1, consumer_tag: tag1] == consumer1 + assert [queue_name: queue_name2, consumer_tag: tag2] == consumer2 + end) + end) + end + + test "consumers are grouped by queues (multiple consumer per queue)", context do + queue_name1 = "test_queue1" + queue_name2 = "test_queue2" + capture_io(fn -> + declare_queue("test_queue1", @vhost) + declare_queue("test_queue2", @vhost) + with_channel(@vhost, fn(channel) -> + {:ok, tag1} = AMQP.Basic.consume(channel, queue_name1) + {:ok, tag2} = AMQP.Basic.consume(channel, queue_name2) + {:ok, tag3} = AMQP.Basic.consume(channel, queue_name2) + consumers = ListConsumersCommand.run(["queue_name", "consumer_tag"], context[:opts]) + {[[consumer1]], [consumers2]} = Enum.partition(consumers, fn([_]) -> true; ([_,_]) -> false end) + assert [queue_name: queue_name1, consumer_tag: tag1] == consumer1 + assert Keyword.equal?([{tag2, queue_name2}, {tag3, queue_name2}], + for([queue_name: q, consumer_tag: t] <- consumers2, do: {t, q})) + end) + end) + end + + +end diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 51aa6c6d1d..5ad6d9df40 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -134,6 +134,19 @@ defmodule ListQueuesCommandTest do end) end + test "info keys order is preserved", context do + declare_queue("durable_queue", @vhost, true) + publish_messages("durable_queue", 3) + declare_queue("auto_delete_queue", @vhost, false, true) + publish_messages("auto_delete_queue", 1) + capture_io(fn -> + assert Keyword.equal?( + ListQueuesCommand.run(["messages", "durable", "name", "auto_delete"], context[:opts]), + [[messages: 3, durable: true, name: "durable_queue", auto_delete: false], + [messages: 1, durable: false, name: "auto_delete_queue", auto_delete: true]]) + end) + end + test "specifying a vhost returns the targeted vhost queues", context do other_vhost = "other_vhost" add_vhost other_vhost diff --git a/deps/rabbitmq_cli/test/rpc_stream_test.exs b/deps/rabbitmq_cli/test/rpc_stream_test.exs index 962993f776..089b46a782 100644 --- a/deps/rabbitmq_cli/test/rpc_stream_test.exs +++ b/deps/rabbitmq_cli/test/rpc_stream_test.exs @@ -27,6 +27,13 @@ defmodule RpcStreamTest do assert [[one: 1, two: 2], [one: 11, two: 12]] == items end + test "emit list of lists with filters" do + list = [[[one: 1, two: 2, three: 3], [one: 11, two: 12, three: 13]], + [[one: 21, two: 22, three: 23], [one: 31, two: 32, three: 33]]] + items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [list], :infinity, [:one, :two]) + + assert [[[one: 1, two: 2], [one: 11, two: 12]], [[one: 21, two: 22], [one: 31, two: 32]]] == items + end test "emission timeout 0 return badrpc" do items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [[]], 0, []) From 46b5279a1477cb729314d82e49c1f9a5967b3700 Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Tue, 10 May 2016 10:04:31 +0100 Subject: [PATCH 08/39] Mention consumerinfoitems in usage --- deps/rabbitmq_cli/lib/list_consumers_command.ex | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/deps/rabbitmq_cli/lib/list_consumers_command.ex b/deps/rabbitmq_cli/lib/list_consumers_command.ex index 793d0a8ab4..7a030f9697 100644 --- a/deps/rabbitmq_cli/lib/list_consumers_command.ex +++ b/deps/rabbitmq_cli/lib/list_consumers_command.ex @@ -25,7 +25,12 @@ defmodule ListConsumersCommand do end def usage() do - "list_consumers [-p vhost]" + "list_consumers [-p vhost] [ ...]" + end + + def usage_additional() do + " must be a member of the list ["<> + Enum.join(@info_keys, ", ") <>"]." end def run([], opts) do @@ -51,5 +56,5 @@ defmodule ListConsumersCommand do end defp info(%{quiet: true}), do: nil - defp info(%{param: vhost}), do: IO.puts "Listing channels on vhost #{vhost} ..." + defp info(%{param: vhost}), do: IO.puts "Listing consumers on vhost #{vhost} ..." end \ No newline at end of file From e3648fb8cbd2582f147a29d25a770620acba3d0a Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Thu, 12 May 2016 10:00:39 +0100 Subject: [PATCH 09/39] Fix tests --- .../test/list_exchanges_command_test.exs | 19 +++++++++++++------ deps/rabbitmq_cli/test/rpc_stream_test.exs | 10 +++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs index 2d1ff06859..b14326c320 100644 --- a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs +++ b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs @@ -109,21 +109,27 @@ defmodule ListExchangesCommandTest do capture_io(fn -> non_default_exchanges = ListExchangesCommand.run(["name", "type"], context[:opts]) |> without_default_exchanges - assert non_default_exchanges == + assert_set_equal( + non_default_exchanges, [[name: "test_exchange_1", type: :direct], - [name: "test_exchange_2", type: :fanout]] + [name: "test_exchange_2", type: :fanout]]) end) end + def assert_set_equal(one, two) do + assert MapSet.new(one) == MapSet.new(two) + end + test "info keys filter single key", context do declare_exchange("test_exchange_1", @vhost) declare_exchange("test_exchange_2", @vhost) capture_io(fn -> non_default_exchanges = ListExchangesCommand.run(["name"], context[:opts]) |> without_default_exchanges - assert non_default_exchanges == + assert_set_equal( + non_default_exchanges, [[name: "test_exchange_1"], - [name: "test_exchange_2"]] + [name: "test_exchange_2"]]) end) end @@ -134,9 +140,10 @@ defmodule ListExchangesCommandTest do capture_io(fn -> non_default_exchanges = ListExchangesCommand.run(["name", "type", "durable", "auto_delete"], context[:opts]) |> without_default_exchanges - assert non_default_exchanges == + assert_set_equal( + non_default_exchanges, [[name: "auto_delete_exchange", type: :fanout, durable: false, auto_delete: true], - [name: "durable_exchange", type: :direct, durable: true, auto_delete: false]] + [name: "durable_exchange", type: :direct, durable: true, auto_delete: false]]) end) end diff --git a/deps/rabbitmq_cli/test/rpc_stream_test.exs b/deps/rabbitmq_cli/test/rpc_stream_test.exs index 089b46a782..be8870b5b2 100644 --- a/deps/rabbitmq_cli/test/rpc_stream_test.exs +++ b/deps/rabbitmq_cli/test/rpc_stream_test.exs @@ -2,8 +2,16 @@ defmodule RpcStreamTest do use ExUnit.Case, async: false setup_all do - :rabbit_control_misc.start_distribution() + :net_kernel.start([:rabbitmqctl, :shortnames]) + :net_kernel.connect_node(get_rabbit_hostname) + + on_exit([], fn -> + :erlang.disconnect_node(get_rabbit_hostname) + :net_kernel.stop() + end) + :ok + end test "emit empty list" do From d83f5761549f3f4ae881def427e7cca94cb7819d Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 17:21:55 +0300 Subject: [PATCH 10/39] Squash a few compilation warnings --- deps/rabbitmq_cli/test/list_connections_command_test.exs | 6 +++--- deps/rabbitmq_cli/test/list_exchanges_command_test.exs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index 6dd808fa3a..931961f605 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -69,7 +69,7 @@ defmodule ListConnectionsCommandTest do test "user, peer_host, peer_port and state by default", context do capture_io(fn -> - with_connection("/", fn(conn) -> + with_connection("/", fn(_conn) -> conns = ListConnectionsCommand.run([], context[:opts]) assert Enum.map(conns, &Keyword.keys/1) == [[:user, :peer_host, :peer_port, :state]] end) @@ -78,7 +78,7 @@ defmodule ListConnectionsCommandTest do test "filter single key", context do capture_io(fn -> - with_connection("/", fn(conn) -> + with_connection("/", fn(_conn) -> conns = ListConnectionsCommand.run(["name"], context[:opts]) assert Enum.map(conns, &Keyword.keys/1) == [[:name]] end) @@ -93,7 +93,7 @@ defmodule ListConnectionsCommandTest do delete_vhost vhost end) capture_io(fn -> - with_connection(vhost, fn(conn) -> + with_connection(vhost, fn(_conn) -> conns = ListConnectionsCommand.run(["vhost"], context[:opts]) assert conns == [[vhost: vhost]] end) diff --git a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs index b14326c320..21a0897f01 100644 --- a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs +++ b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs @@ -88,7 +88,7 @@ defmodule ListExchangesCommandTest do test "show default exchanges by default", context do capture_io(fn -> assert MapSet.new(ListExchangesCommand.run(["name"], context[:opts])) == - MapSet.new(for {ex_name, ex_type} <- @default_exchanges, do: [name: ex_name]) + MapSet.new(for {ex_name, _ex_type} <- @default_exchanges, do: [name: ex_name]) end) end From b2be6b4158637840020c0c06c9eb8dadacaf9577 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 17:23:52 +0300 Subject: [PATCH 11/39] Add a missing import --- deps/rabbitmq_cli/test/rpc_stream_test.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/rpc_stream_test.exs b/deps/rabbitmq_cli/test/rpc_stream_test.exs index be8870b5b2..20a21977cd 100644 --- a/deps/rabbitmq_cli/test/rpc_stream_test.exs +++ b/deps/rabbitmq_cli/test/rpc_stream_test.exs @@ -1,6 +1,8 @@ defmodule RpcStreamTest do use ExUnit.Case, async: false + import TestHelper + setup_all do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) @@ -68,7 +70,7 @@ defmodule RpcStreamTest do list2 = [:dog, :cat, :pig] # Adding timeout to make sure emissions are executed in parallel timeout_fun = fn(x) -> :timer.sleep(10); x end - Agent.update(agent, + Agent.update(agent, fn(:init) -> RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list_map, [list2, timeout_fun], :infinity, []) end) From 8064334911ced67b0355d89e5e16f4b38aa79f68 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 17:35:57 +0300 Subject: [PATCH 12/39] Make the test suite a bit more robust Deletes a test that wasn't really testing grouping along the way. A test next to it does, so we do not reduce our coverage. --- .../test/list_consumers_command_test.exs | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_consumers_command_test.exs b/deps/rabbitmq_cli/test/list_consumers_command_test.exs index d9cded1d36..3e40ba1530 100644 --- a/deps/rabbitmq_cli/test/list_consumers_command_test.exs +++ b/deps/rabbitmq_cli/test/list_consumers_command_test.exs @@ -85,34 +85,19 @@ defmodule ListConsumersCommandTest do declare_queue(queue_name, @vhost) with_channel(@vhost, fn(channel) -> {:ok, _} = AMQP.Basic.consume(channel, queue_name, nil, [consumer_tag: consumer_tag]) + :timer.sleep(100) [[consumer]] = ListConsumersCommand.run([], context[:opts]) assert info_keys == Keyword.keys(consumer) assert consumer[:consumer_tag] == consumer_tag assert consumer[:queue_name] == queue_name - assert Keyword.delete(consumer, :channel_pid) == - [queue_name: queue_name, consumer_tag: consumer_tag, + assert Keyword.delete(consumer, :channel_pid) == + [queue_name: queue_name, consumer_tag: consumer_tag, ack_required: true, prefetch_count: 0, arguments: []] end) end) end - test "consumers are grouped by queues (single consumer per queue)", context do - queue_name1 = "test_queue1" - queue_name2 = "test_queue2" - capture_io(fn -> - declare_queue("test_queue1", @vhost) - declare_queue("test_queue2", @vhost) - with_channel(@vhost, fn(channel) -> - {:ok, tag1} = AMQP.Basic.consume(channel, queue_name1) - {:ok, tag2} = AMQP.Basic.consume(channel, queue_name2) - [[consumer1], [consumer2]] = ListConsumersCommand.run(["queue_name", "consumer_tag"], context[:opts]) - assert [queue_name: queue_name1, consumer_tag: tag1] == consumer1 - assert [queue_name: queue_name2, consumer_tag: tag2] == consumer2 - end) - end) - end - test "consumers are grouped by queues (multiple consumer per queue)", context do queue_name1 = "test_queue1" queue_name2 = "test_queue2" @@ -123,10 +108,11 @@ defmodule ListConsumersCommandTest do {:ok, tag1} = AMQP.Basic.consume(channel, queue_name1) {:ok, tag2} = AMQP.Basic.consume(channel, queue_name2) {:ok, tag3} = AMQP.Basic.consume(channel, queue_name2) + :timer.sleep(100) consumers = ListConsumersCommand.run(["queue_name", "consumer_tag"], context[:opts]) {[[consumer1]], [consumers2]} = Enum.partition(consumers, fn([_]) -> true; ([_,_]) -> false end) assert [queue_name: queue_name1, consumer_tag: tag1] == consumer1 - assert Keyword.equal?([{tag2, queue_name2}, {tag3, queue_name2}], + assert Keyword.equal?([{tag2, queue_name2}, {tag3, queue_name2}], for([queue_name: q, consumer_tag: t] <- consumers2, do: {t, q})) end) end) From 50b9294f42d0a96617e8e9892a12c3350b705a9b Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 17:46:28 +0300 Subject: [PATCH 13/39] Use publisher confirms --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 5ad6d9df40..01a1898047 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -189,10 +189,12 @@ defmodule ListQueuesCommandTest do def publish_messages(name, count) do with_channel(@vhost, fn(channel) -> + AMQP.Confirm.select(channel) for i <- 1..count do AMQP.Basic.publish(channel, "", name, "test_message" <> Integer.to_string(i)) end + AMQP.Confirm.wait_for_confirms_or_die(channel, 10000) end) end From ac19b90e6640200c55a9c5747b1eb2f81e1cb9ae Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 17:46:36 +0300 Subject: [PATCH 14/39] Squash a couple of warnings --- deps/rabbitmq_cli/lib/list_exchanges_command.ex | 2 +- deps/rabbitmq_cli/lib/status_print.ex | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/deps/rabbitmq_cli/lib/list_exchanges_command.ex b/deps/rabbitmq_cli/lib/list_exchanges_command.ex index 782c02fce2..546dbe318f 100644 --- a/deps/rabbitmq_cli/lib/list_exchanges_command.ex +++ b/deps/rabbitmq_cli/lib/list_exchanges_command.ex @@ -48,7 +48,7 @@ defmodule ListExchangesCommand do info_keys) end) end - def run([_|_] = args, %{node: node_name, timeout: timeout} = opts) do + def run([_|_] = args, %{node: node_name, timeout: _timeout} = opts) do run(args, Map.merge(default_opts, opts)) end diff --git a/deps/rabbitmq_cli/lib/status_print.ex b/deps/rabbitmq_cli/lib/status_print.ex index e93efe79d5..014744a769 100644 --- a/deps/rabbitmq_cli/lib/status_print.ex +++ b/deps/rabbitmq_cli/lib/status_print.ex @@ -15,7 +15,6 @@ defmodule StatusPrint do - import Helpers import TablePrint @otp_version_tag "otp_version" From 9e8f354ff2d9d33d2111e748240ae22befc5fccb Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 17:50:26 +0300 Subject: [PATCH 15/39] This timeout should be in seconds --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 01a1898047..98cb5c2760 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -194,7 +194,7 @@ defmodule ListQueuesCommandTest do AMQP.Basic.publish(channel, "", name, "test_message" <> Integer.to_string(i)) end - AMQP.Confirm.wait_for_confirms_or_die(channel, 10000) + AMQP.Confirm.wait_for_confirms_or_die(channel, 15) end) end From 7f3d08915dc8639f62efbd69a18884f40eb228bd Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 18:57:19 +0300 Subject: [PATCH 16/39] This test doesn't need to publish any messages --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 2 -- 1 file changed, 2 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 98cb5c2760..f3775e346f 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -110,9 +110,7 @@ defmodule ListQueuesCommandTest do test "info keys filter single key", context do declare_queue("test_queue_1", @vhost) - publish_messages("test_queue_1", 3) declare_queue("test_queue_2", @vhost) - publish_messages("test_queue_2", 1) capture_io(fn -> assert ListQueuesCommand.run(["name"], context[:opts]) == [[name: "test_queue_1"], From 8bf840e6a28944882b254f11d377f65ef17d61b8 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 20 May 2016 18:59:49 +0300 Subject: [PATCH 17/39] 5K queues seems sufficient here --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index f3775e346f..6553ab8e0e 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -74,9 +74,9 @@ defmodule ListQueuesCommandTest do end @tag test_timeout: 1 - test "command timeout (10000 msg in 1ms) return badrpc with timeout value in seconds", context do - # We hope that broker will be unable to list 10000 queues in 1 millisecond. - for i <- 1..10000 do + test "command timeout (5K queues in 1ms) return badrpc with timeout value in seconds", context do + # We hope that broker will be unable to list 1K queues in 1 millisecond. + for i <- 1..5000 do declare_queue("test_queue_" <> Integer.to_string(i), @vhost) end capture_io(fn -> From 52a548802598d2f01f793939ceb4e3065294a921 Mon Sep 17 00:00:00 2001 From: Daniil Fedotov Date: Fri, 20 May 2016 18:16:35 +0100 Subject: [PATCH 18/39] Made all timeout errors return timeout in seconds --- deps/rabbitmq_cli/lib/rpc_stream.ex | 1 + deps/rabbitmq_cli/test/list_bindings_command_test.exs | 2 +- deps/rabbitmq_cli/test/list_channels_command_test.exs | 2 +- deps/rabbitmq_cli/test/list_connections_command_test.exs | 2 +- deps/rabbitmq_cli/test/list_consumers_command_test.exs | 2 +- deps/rabbitmq_cli/test/list_exchanges_command_test.exs | 2 +- deps/rabbitmq_cli/test/list_queues_command_test.exs | 2 +- deps/rabbitmq_cli/test/rpc_stream_test.exs | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/deps/rabbitmq_cli/lib/rpc_stream.ex b/deps/rabbitmq_cli/lib/rpc_stream.ex index 3de6a43f20..c8ad952d09 100644 --- a/deps/rabbitmq_cli/lib/rpc_stream.ex +++ b/deps/rabbitmq_cli/lib/rpc_stream.ex @@ -37,6 +37,7 @@ defmodule RpcStream do case :rabbit_misc.rpc_call(node, mod, fun, args, ref, pid, timeout) do {:error, _} = error -> send(pid, {:error, error}); {:bad_argument, _} = error -> send(pid, {:error, error}); + {:badrpc, :timeout} -> send(pid, {:timeout, timeout}); {:badrpc, _} = error -> send(pid, {:error, error}); _ -> :ok end diff --git a/deps/rabbitmq_cli/test/list_bindings_command_test.exs b/deps/rabbitmq_cli/test/list_bindings_command_test.exs index 8e627dde90..9029d4c5a5 100644 --- a/deps/rabbitmq_cli/test/list_bindings_command_test.exs +++ b/deps/rabbitmq_cli/test/list_bindings_command_test.exs @@ -68,7 +68,7 @@ defmodule ListBindingsCommandTest do test "zero timeout causes command to return badrpc", context do capture_io(fn -> assert ListBindingsCommand.run([], context[:opts]) == - [{:badrpc, :timeout}] + [{:badrpc, {:timeout, 0.0}}] end) end diff --git a/deps/rabbitmq_cli/test/list_channels_command_test.exs b/deps/rabbitmq_cli/test/list_channels_command_test.exs index ea9dc6a14c..30ea811c01 100644 --- a/deps/rabbitmq_cli/test/list_channels_command_test.exs +++ b/deps/rabbitmq_cli/test/list_channels_command_test.exs @@ -57,7 +57,7 @@ defmodule ListChannelsCommandTest do test "zero timeout causes command to return badrpc", context do capture_io(fn -> assert ListChannelsCommand.run([], context[:opts]) == - [{:badrpc, :timeout}] + [{:badrpc, {:timeout, 0.0}}] end) end diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index 931961f605..dcf7587f68 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -57,7 +57,7 @@ defmodule ListConnectionsCommandTest do test "zero timeout causes command to return badrpc", context do capture_io(fn -> assert ListConnectionsCommand.run([], context[:opts]) == - [{:badrpc, :timeout}] + [{:badrpc, {:timeout, 0.0}}] end) end diff --git a/deps/rabbitmq_cli/test/list_consumers_command_test.exs b/deps/rabbitmq_cli/test/list_consumers_command_test.exs index 3e40ba1530..a407bdb70b 100644 --- a/deps/rabbitmq_cli/test/list_consumers_command_test.exs +++ b/deps/rabbitmq_cli/test/list_consumers_command_test.exs @@ -67,7 +67,7 @@ defmodule ListConsumersCommandTest do test "zero timeout causes command to return badrpc", context do capture_io(fn -> assert ListConsumersCommand.run([], context[:opts]) == - [{:badrpc, :timeout}] + [{:badrpc, {:timeout, 0.0}}] end) end diff --git a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs index 21a0897f01..f86cb5f8f0 100644 --- a/deps/rabbitmq_cli/test/list_exchanges_command_test.exs +++ b/deps/rabbitmq_cli/test/list_exchanges_command_test.exs @@ -81,7 +81,7 @@ defmodule ListExchangesCommandTest do test "zero timeout causes command to return badrpc", context do capture_io(fn -> assert ListExchangesCommand.run([], context[:opts]) == - [{:badrpc, :timeout}] + [{:badrpc, {:timeout, 0.0}}] end) end diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 6553ab8e0e..012c165d6b 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -69,7 +69,7 @@ defmodule ListQueuesCommandTest do test "zero timeout causes command to return badrpc", context do capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == - [{:badrpc, :timeout}] + [{:badrpc, {:timeout, 0.0}}] end) end diff --git a/deps/rabbitmq_cli/test/rpc_stream_test.exs b/deps/rabbitmq_cli/test/rpc_stream_test.exs index 20a21977cd..6168b27880 100644 --- a/deps/rabbitmq_cli/test/rpc_stream_test.exs +++ b/deps/rabbitmq_cli/test/rpc_stream_test.exs @@ -48,7 +48,7 @@ defmodule RpcStreamTest do test "emission timeout 0 return badrpc" do items = RpcStream.receive_list_items(Kernel.node, TestHelper, :emit_list, [[]], 0, []) - assert [{:badrpc, :timeout}] == items + assert [{:badrpc, {:timeout, 0.0}}] == items end test "emission timeout return badrpc with timeout value in seconds" do From c5348032a16ca442ccff2142069a2e9e3413c869 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 12:20:44 +0300 Subject: [PATCH 19/39] Don't use infinite timeouts; enable confirms on temp channels --- .../test/list_connections_command_test.exs | 2 +- .../test/list_queues_command_test.exs | 24 +++++++++++-------- deps/rabbitmq_cli/test/test_helper.exs | 1 + 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index dcf7587f68..bd1a7de7ee 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -4,7 +4,7 @@ defmodule ListConnectionsCommandTest do import TestHelper @user "guest" - @default_timeout :infinity + @default_timeout 15000 setup_all do :net_kernel.start([:rabbitmqctl, :shortnames]) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 012c165d6b..41a69ca5d7 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -6,7 +6,7 @@ defmodule ListQueuesCommandTest do @vhost "test1" @user "guest" @root "/" - @default_timeout :infinity + @default_timeout 15000 setup_all do :net_kernel.start([:rabbitmqctl, :shortnames]) @@ -37,7 +37,7 @@ defmodule ListQueuesCommandTest do } end - @tag test_timeout: :infinity + @tag test_timeout: 30000 test "return bad_info_key on a single bad arg", context do capture_io(fn -> assert ListQueuesCommand.run(["quack"], context[:opts]) == @@ -45,7 +45,7 @@ defmodule ListQueuesCommandTest do end) end - @tag test_timeout: :infinity + @tag test_timeout: 30000 test "multiple bad args return a list of bad info key values", context do capture_io(fn -> assert ListQueuesCommand.run(["quack", "oink"], context[:opts]) == @@ -53,7 +53,7 @@ defmodule ListQueuesCommandTest do end) end - @tag test_timeout: :infinity + @tag test_timeout: 30000 test "return bad_info_key on mix of good and bad args", context do capture_io(fn -> assert ListQueuesCommand.run(["quack", "messages"], context[:opts]) == @@ -74,9 +74,9 @@ defmodule ListQueuesCommandTest do end @tag test_timeout: 1 - test "command timeout (5K queues in 1ms) return badrpc with timeout value in seconds", context do - # We hope that broker will be unable to list 1K queues in 1 millisecond. - for i <- 1..5000 do + test "command timeout (8K queues in 1ms) return badrpc with timeout value in seconds", context do + # we assume it will take longer than 1 ms to list thousands of queues + for i <- 1..8000 do declare_queue("test_queue_" <> Integer.to_string(i), @vhost) end capture_io(fn -> @@ -85,6 +85,7 @@ defmodule ListQueuesCommandTest do end) end + @tag test_timeout: 5000 test "no info keys returns names and message count", context do queue_name = "test_queue" message_count = 3 @@ -96,6 +97,7 @@ defmodule ListQueuesCommandTest do end) end + @tag test_timeout: 5000 test "return multiple queues", context do declare_queue("test_queue_1", @vhost) publish_messages("test_queue_1", 3) @@ -108,6 +110,7 @@ defmodule ListQueuesCommandTest do end) end + @tag test_timeout: 5000 test "info keys filter single key", context do declare_queue("test_queue_1", @vhost) declare_queue("test_queue_2", @vhost) @@ -118,7 +121,7 @@ defmodule ListQueuesCommandTest do end) end - + @tag test_timeout: 5000 test "info keys add additional keys", context do declare_queue("durable_queue", @vhost, true) publish_messages("durable_queue", 3) @@ -132,6 +135,7 @@ defmodule ListQueuesCommandTest do end) end + @tag test_timeout: 5000 test "info keys order is preserved", context do declare_queue("durable_queue", @vhost, true) publish_messages("durable_queue", 3) @@ -145,6 +149,7 @@ defmodule ListQueuesCommandTest do end) end + @tag test_timeout: 5000 test "specifying a vhost returns the targeted vhost queues", context do other_vhost = "other_vhost" add_vhost other_vhost @@ -187,12 +192,11 @@ defmodule ListQueuesCommandTest do def publish_messages(name, count) do with_channel(@vhost, fn(channel) -> - AMQP.Confirm.select(channel) for i <- 1..count do AMQP.Basic.publish(channel, "", name, "test_message" <> Integer.to_string(i)) end - AMQP.Confirm.wait_for_confirms_or_die(channel, 15) + AMQP.Confirm.wait_for_confirms(channel, 30) end) end diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index d19b8959a5..959969ba49 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -119,6 +119,7 @@ defmodule TestHelper do with_connection(vhost, fn(conn) -> {:ok, chan} = AMQP.Channel.open(conn) + AMQP.Confirm.select(chan) fun.(chan) end) end From 68d417ee6bdcaf6b864acb3da0a5cff170a7c772 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 13:14:44 +0300 Subject: [PATCH 20/39] Add a helper that closes all connections to a node --- deps/rabbitmq_cli/mix.exs | 6 ++++++ deps/rabbitmq_cli/test/test_helper.exs | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/deps/rabbitmq_cli/mix.exs b/deps/rabbitmq_cli/mix.exs index d777c1a4ab..1688301b6f 100644 --- a/deps/rabbitmq_cli/mix.exs +++ b/deps/rabbitmq_cli/mix.exs @@ -53,6 +53,12 @@ defmodule RabbitMQCtl.Mixfile do git: "https://github.com/rabbitmq/rabbitmq-common.git", branch: "stable" }, + # for test helper(s) that close connections and so on + { + :rabbit, + git: "https://github.com/rabbitmq/rabbitmq-server.git", + branch: "stable" + }, { :amqp_client, git: "https://github.com/rabbitmq/rabbitmq-erlang-client.git", diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 959969ba49..269452d499 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -137,6 +137,16 @@ defmodule TestHelper do AMQP.Connection.close(conn) end + def close_all_connections() do + # we intentionally use connections_local/0 here because connections/0, + # the cluster-wide version, loads some bits around cluster membership + # that are not normally ready with a single node. MK. + # + # when/if we decide to test + # this project against a cluster of nodes this will need revisiting. MK. + for pid <- :rabbit_networking.connections_local(), do: :rabbit_networking.close_connection(pid, :force_closed) + end + def emit_list(list, ref, pid) do emit_list_map(list, &(&1), ref, pid) end From bf311914356ed58f23fed2190c2f3195aafa949a Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 13:15:09 +0300 Subject: [PATCH 21/39] Make this test depend less on node state Specifically what connections may be open. --- .../test/list_connections_command_test.exs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index bd1a7de7ee..41480f7ee5 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -10,7 +10,10 @@ defmodule ListConnectionsCommandTest do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + close_all_connections() + on_exit([], fn -> + close_all_connections() :erlang.disconnect_node(get_rabbit_hostname) :net_kernel.stop() end) @@ -61,26 +64,31 @@ defmodule ListConnectionsCommandTest do end) end + # see TestHelper.close_all_connections test "no connections by default", context do + close_all_connections() capture_io(fn -> assert [] == ListConnectionsCommand.run([], context[:opts]) end) end test "user, peer_host, peer_port and state by default", context do + vhost = "/" capture_io(fn -> - with_connection("/", fn(_conn) -> + with_connection(vhost, fn(_conn) -> conns = ListConnectionsCommand.run([], context[:opts]) - assert Enum.map(conns, &Keyword.keys/1) == [[:user, :peer_host, :peer_port, :state]] + assert Enum.any?(conns, fn(conn) -> conn[:state] == :running end) end) end) end test "filter single key", context do + vhost = "/" capture_io(fn -> - with_connection("/", fn(_conn) -> + with_connection(vhost, fn(_conn) -> conns = ListConnectionsCommand.run(["name"], context[:opts]) - assert Enum.map(conns, &Keyword.keys/1) == [[:name]] + assert (Enum.map(conns, &Keyword.keys/1) |> Enum.uniq) == [[:name]] + assert Enum.any?(conns, fn(conn) -> conn[:name] != nil end) end) end) end @@ -95,7 +103,8 @@ defmodule ListConnectionsCommandTest do capture_io(fn -> with_connection(vhost, fn(_conn) -> conns = ListConnectionsCommand.run(["vhost"], context[:opts]) - assert conns == [[vhost: vhost]] + assert (Enum.map(conns, &Keyword.keys/1) |> Enum.uniq) == [[:vhost]] + assert Enum.any?(conns, fn(conn) -> conn[:vhost] == vhost end) end) end) end From 4f4a0bf3071580d48bb12bf22921c12402554792 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 13:55:03 +0300 Subject: [PATCH 22/39] Make this test less dependent on node state and less likely to run into alarms --- .../test/list_queues_command_test.exs | 11 +++++++++-- deps/rabbitmq_cli/test/test_helper.exs | 18 ++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 41a69ca5d7..79253ffdc6 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -12,7 +12,10 @@ defmodule ListQueuesCommandTest do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + close_all_connections() + on_exit([], fn -> + close_all_connections() :erlang.disconnect_node(get_rabbit_hostname) :net_kernel.stop() end) @@ -74,15 +77,18 @@ defmodule ListQueuesCommandTest do end @tag test_timeout: 1 - test "command timeout (8K queues in 1ms) return badrpc with timeout value in seconds", context do + test "command timeout (several thousands queues in 1ms) return badrpc with timeout value in seconds", context do # we assume it will take longer than 1 ms to list thousands of queues - for i <- 1..8000 do + for i <- 1..5000 do declare_queue("test_queue_" <> Integer.to_string(i), @vhost) end capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == [{:badrpc, {:timeout, 0.001}}] end) + for i <- 1..5000 do + delete_queue("test_queue_" <> Integer.to_string(i), @vhost) + end end @tag test_timeout: 5000 @@ -192,6 +198,7 @@ defmodule ListQueuesCommandTest do def publish_messages(name, count) do with_channel(@vhost, fn(channel) -> + AMQP.Queue.purge(channel, name) for i <- 1..count do AMQP.Basic.publish(channel, "", name, "test_message" <> Integer.to_string(i)) diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 269452d499..46176d19d8 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -86,6 +86,13 @@ defmodule TestHelper do [queue_name, durable, auto_delete, args, owner]) end + def delete_queue(name, vhost) do + queue_name = :rabbit_misc.r(vhost, :queue, name) + :rpc.call(get_rabbit_hostname, + :rabbit_amqqueue, :delete_immediately, + [queue_name]) + end + def declare_exchange(name, vhost, type \\ :direct, durable \\ false, auto_delete \\ false, internal \\ false, args \\ []) do exchange_name = :rabbit_misc.r(vhost, :exchange, name) :rpc.call(get_rabbit_hostname, @@ -128,13 +135,12 @@ defmodule TestHelper do {:ok, conn} = AMQP.Connection.open(virtual_host: vhost) ExUnit.Callbacks.on_exit(fn -> try do - AMQP.Connection.close(conn) + :amqp_connection.close(conn, 5000) catch :exit, _ -> :ok end end) fun.(conn) - AMQP.Connection.close(conn) end def close_all_connections() do @@ -147,6 +153,14 @@ defmodule TestHelper do for pid <- :rabbit_networking.connections_local(), do: :rabbit_networking.close_connection(pid, :force_closed) end + def delete_all_queues() do + for q <- :rabbit_amqqueue.list(), do: :rabbit_amqueue.delete_immediately(q) + end + + def delete_all_queues(vhost) do + for q <- :rabbit_amqqueue.list(vhost), do: :rabbit_amqueue.delete_immediately(q) + end + def emit_list(list, ref, pid) do emit_list_map(list, &(&1), ref, pid) end From beba04e5b13e995d37d0f444a33f71666dd0f843 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 13:55:35 +0300 Subject: [PATCH 23/39] Ensure there are actually no queues --- deps/rabbitmq_cli/test/list_consumers_command_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_consumers_command_test.exs b/deps/rabbitmq_cli/test/list_consumers_command_test.exs index a407bdb70b..2e3802992e 100644 --- a/deps/rabbitmq_cli/test/list_consumers_command_test.exs +++ b/deps/rabbitmq_cli/test/list_consumers_command_test.exs @@ -72,6 +72,8 @@ defmodule ListConsumersCommandTest do end test "no consumers for no queues", context do + close_all_connections + delete_all_queues capture_io(fn -> [] = ListConsumersCommand.run([], context[:opts]) end) @@ -117,6 +119,4 @@ defmodule ListConsumersCommandTest do end) end) end - - end From 5476d25eabcb2775083e390177f9a158a7ce7eeb Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 13:55:54 +0300 Subject: [PATCH 24/39] Depend less on node state --- deps/rabbitmq_cli/test/list_connections_command_test.exs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index 41480f7ee5..2941ece36b 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -64,14 +64,6 @@ defmodule ListConnectionsCommandTest do end) end - # see TestHelper.close_all_connections - test "no connections by default", context do - close_all_connections() - capture_io(fn -> - assert [] == ListConnectionsCommand.run([], context[:opts]) - end) - end - test "user, peer_host, peer_port and state by default", context do vhost = "/" capture_io(fn -> From b0c80c3dac8a4ad91a575a9d5f58f3ef88eba104 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 13:56:00 +0300 Subject: [PATCH 25/39] Ditto --- .../test/list_channels_command_test.exs | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_channels_command_test.exs b/deps/rabbitmq_cli/test/list_channels_command_test.exs index 30ea811c01..f6b167f57e 100644 --- a/deps/rabbitmq_cli/test/list_channels_command_test.exs +++ b/deps/rabbitmq_cli/test/list_channels_command_test.exs @@ -10,7 +10,10 @@ defmodule ListChannelsCommandTest do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + close_all_connections() + on_exit([], fn -> + close_all_connections() :erlang.disconnect_node(get_rabbit_hostname) :net_kernel.stop() end) @@ -61,16 +64,12 @@ defmodule ListChannelsCommandTest do end) end - test "no channels by default", context do - capture_io(fn -> - assert [] == ListChannelsCommand.run([], context[:opts]) - end) - end - test "default channel info keys are pid, user, consumer_count, and messages_unacknowledged", context do + close_all_connections() capture_io(fn -> with_channel("/", fn(_channel) -> - [chan] = ListChannelsCommand.run([], context[:opts]) + channels = ListChannelsCommand.run([], context[:opts]) + chan = Enum.at(channels, 0) assert Keyword.keys(chan) == ~w(pid user consumer_count messages_unacknowledged)a assert [user: "guest", consumer_count: 0, messages_unacknowledged: 0] == Keyword.delete(chan, :pid) end) @@ -78,42 +77,47 @@ defmodule ListChannelsCommandTest do end test "multiple channels on multiple connections", context do + close_all_connections() capture_io(fn -> with_channel("/", fn(_channel1) -> with_channel("/", fn(_channel2) -> - [chan1, chan2] = ListChannelsCommand.run(["pid", "user", "connection"], context[:opts]) + channels = ListChannelsCommand.run(["pid", "user", "connection"], context[:opts]) + chan1 = Enum.at(channels, 0) + chan2 = Enum.at(channels, 1) assert Keyword.keys(chan1) == ~w(pid user connection)a assert Keyword.keys(chan2) == ~w(pid user connection)a assert "guest" == chan1[:user] assert "guest" == chan2[:user] assert chan1[:pid] !== chan2[:pid] - assert chan1[:connection] !== chan2[:connection] end) end) end) end test "multiple channels on single connection", context do + close_all_connections() capture_io(fn -> with_connection("/", fn(conn) -> {:ok, _} = AMQP.Channel.open(conn) {:ok, _} = AMQP.Channel.open(conn) - - [chan1, chan2] = ListChannelsCommand.run(["pid", "user", "connection"], context[:opts]) + channels = ListChannelsCommand.run(["pid", "user", "connection"], context[:opts]) + chan1 = Enum.at(channels, 0) + chan2 = Enum.at(channels, 1) assert Keyword.keys(chan1) == ~w(pid user connection)a assert Keyword.keys(chan2) == ~w(pid user connection)a assert "guest" == chan1[:user] assert "guest" == chan2[:user] assert chan1[:pid] !== chan2[:pid] - assert chan1[:connection] == chan2[:connection] end) end) end test "info keys order is preserved", context do + close_all_connections() capture_io(fn -> with_channel("/", fn(_channel) -> - [chan] = ListChannelsCommand.run(~w(connection vhost name pid number user), context[:opts]) + channels = ListChannelsCommand.run(~w(connection vhost name pid number user), context[:opts]) + chan = Enum.at(channels, 0) assert Keyword.keys(chan) == ~w(connection vhost name pid number user)a end) end) From 38fac6adae75bad4b6ddb4418513328fc1615fb2 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:26:29 +0300 Subject: [PATCH 26/39] Correctly delete queues --- deps/rabbitmq_cli/test/test_helper.exs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 46176d19d8..4c3ee95381 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -89,8 +89,8 @@ defmodule TestHelper do def delete_queue(name, vhost) do queue_name = :rabbit_misc.r(vhost, :queue, name) :rpc.call(get_rabbit_hostname, - :rabbit_amqqueue, :delete_immediately, - [queue_name]) + :rabbit_amqqueue, :delete, + [queue_name, false, false]) end def declare_exchange(name, vhost, type \\ :direct, durable \\ false, auto_delete \\ false, internal \\ false, args \\ []) do @@ -135,7 +135,7 @@ defmodule TestHelper do {:ok, conn} = AMQP.Connection.open(virtual_host: vhost) ExUnit.Callbacks.on_exit(fn -> try do - :amqp_connection.close(conn, 5000) + :amqp_connection.close(conn, 1000) catch :exit, _ -> :ok end @@ -154,11 +154,21 @@ defmodule TestHelper do end def delete_all_queues() do - for q <- :rabbit_amqqueue.list(), do: :rabbit_amqueue.delete_immediately(q) + immediately_delete_all_queues(:rabbit_amqqueue.list()) end def delete_all_queues(vhost) do - for q <- :rabbit_amqqueue.list(vhost), do: :rabbit_amqueue.delete_immediately(q) + immediately_delete_all_queues(:rabbit_amqqueue.list(vhost)) + end + + def immediately_delete_all_queues(qs) do + for q <- qs do + try do + :rabbit_amqueue.delete(q, false, false) + catch + _, _ -> :ok + end + end end def emit_list(list, ref, pid) do From 72d487f514bf90a0813a5a47da700d6070d5c828 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:26:46 +0300 Subject: [PATCH 27/39] Cancel consumers at the end of the test --- .../test/list_consumers_command_test.exs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_consumers_command_test.exs b/deps/rabbitmq_cli/test/list_consumers_command_test.exs index 2e3802992e..0d2b968337 100644 --- a/deps/rabbitmq_cli/test/list_consumers_command_test.exs +++ b/deps/rabbitmq_cli/test/list_consumers_command_test.exs @@ -71,9 +71,8 @@ defmodule ListConsumersCommandTest do end) end - test "no consumers for no queues", context do + test "no consumers for no open connections", context do close_all_connections - delete_all_queues capture_io(fn -> [] = ListConsumersCommand.run([], context[:opts]) end) @@ -87,7 +86,7 @@ defmodule ListConsumersCommandTest do declare_queue(queue_name, @vhost) with_channel(@vhost, fn(channel) -> {:ok, _} = AMQP.Basic.consume(channel, queue_name, nil, [consumer_tag: consumer_tag]) - :timer.sleep(100) + :timer.sleep(100) [[consumer]] = ListConsumersCommand.run([], context[:opts]) assert info_keys == Keyword.keys(consumer) assert consumer[:consumer_tag] == consumer_tag @@ -111,11 +110,17 @@ defmodule ListConsumersCommandTest do {:ok, tag2} = AMQP.Basic.consume(channel, queue_name2) {:ok, tag3} = AMQP.Basic.consume(channel, queue_name2) :timer.sleep(100) - consumers = ListConsumersCommand.run(["queue_name", "consumer_tag"], context[:opts]) - {[[consumer1]], [consumers2]} = Enum.partition(consumers, fn([_]) -> true; ([_,_]) -> false end) - assert [queue_name: queue_name1, consumer_tag: tag1] == consumer1 - assert Keyword.equal?([{tag2, queue_name2}, {tag3, queue_name2}], - for([queue_name: q, consumer_tag: t] <- consumers2, do: {t, q})) + try do + consumers = ListConsumersCommand.run(["queue_name", "consumer_tag"], context[:opts]) + {[[consumer1]], [consumers2]} = Enum.partition(consumers, fn([_]) -> true; ([_,_]) -> false end) + assert [queue_name: queue_name1, consumer_tag: tag1] == consumer1 + assert Keyword.equal?([{tag2, queue_name2}, {tag3, queue_name2}], + for([queue_name: q, consumer_tag: t] <- consumers2, do: {t, q})) + after + AMQP.Basic.cancel(channel, tag1) + AMQP.Basic.cancel(channel, tag2) + AMQP.Basic.cancel(channel, tag3) + end end) end) end From 3fa66a5ab9246a9bdca9365eef8cc2abb548f4e8 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:27:00 +0300 Subject: [PATCH 28/39] Don't assume connections are in a particular state --- deps/rabbitmq_cli/test/list_connections_command_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/list_connections_command_test.exs b/deps/rabbitmq_cli/test/list_connections_command_test.exs index 2941ece36b..5ad04362c5 100644 --- a/deps/rabbitmq_cli/test/list_connections_command_test.exs +++ b/deps/rabbitmq_cli/test/list_connections_command_test.exs @@ -69,7 +69,7 @@ defmodule ListConnectionsCommandTest do capture_io(fn -> with_connection(vhost, fn(_conn) -> conns = ListConnectionsCommand.run([], context[:opts]) - assert Enum.any?(conns, fn(conn) -> conn[:state] == :running end) + assert Enum.any?(conns, fn(conn) -> conn[:state] != nil end) end) end) end From 05ee8884f9b40c79bc109c8ff4e3b3896779cd65 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:27:17 +0300 Subject: [PATCH 29/39] Reset VM memory watermark during setup and tear down Otherwise connections in other tests may end up being blocked, which in turn means functions that close network connections time out. --- .../test/set_vm_memory_high_watermark_command_test.exs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs index c08b98fe6d..66e554281c 100644 --- a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs +++ b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs @@ -24,8 +24,11 @@ defmodule SetVmMemoryHighWatermarkCommandTest do setup_all do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + :vm_memory_monitor.set_vm_memory_high_watermark(0.4) on_exit([], fn -> + :vm_memory_monitor.set_vm_memory_high_watermark(0.4) + :erlang.disconnect_node(get_rabbit_hostname) :net_kernel.stop() end) From 1a81d9d0fc1def362cd1209784f122703a5dc5f9 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:29:30 +0300 Subject: [PATCH 30/39] Don't mess with VM watermark during setup --- .../test/set_vm_memory_high_watermark_command_test.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs index 66e554281c..d037c0371d 100644 --- a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs +++ b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs @@ -24,7 +24,6 @@ defmodule SetVmMemoryHighWatermarkCommandTest do setup_all do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) - :vm_memory_monitor.set_vm_memory_high_watermark(0.4) on_exit([], fn -> :vm_memory_monitor.set_vm_memory_high_watermark(0.4) From 5abd098ed3b4cadc53312a025f3875fbac655063 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:40:10 +0300 Subject: [PATCH 31/39] Untangle a few more test inter-dependencies --- .../test/list_queues_command_test.exs | 7 +++---- ..._vm_memory_high_watermark_command_test.exs | 1 + deps/rabbitmq_cli/test/test_helper.exs | 20 +++++++++++++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 79253ffdc6..555fb496df 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -12,9 +12,11 @@ defmodule ListQueuesCommandTest do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + delete_all_queues() close_all_connections() on_exit([], fn -> + delete_all_queues() close_all_connections() :erlang.disconnect_node(get_rabbit_hostname) :net_kernel.stop() @@ -85,10 +87,7 @@ defmodule ListQueuesCommandTest do capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == [{:badrpc, {:timeout, 0.001}}] - end) - for i <- 1..5000 do - delete_queue("test_queue_" <> Integer.to_string(i), @vhost) - end + end) end @tag test_timeout: 5000 diff --git a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs index d037c0371d..0fa759978d 100644 --- a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs +++ b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs @@ -24,6 +24,7 @@ defmodule SetVmMemoryHighWatermarkCommandTest do setup_all do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + reset_vm_memory_high_watermark() on_exit([], fn -> :vm_memory_monitor.set_vm_memory_high_watermark(0.4) diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index 4c3ee95381..d62018ee03 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -154,11 +154,19 @@ defmodule TestHelper do end def delete_all_queues() do - immediately_delete_all_queues(:rabbit_amqqueue.list()) + try do + immediately_delete_all_queues(:rabbit_amqqueue.list()) + catch + _, _ -> :ok + end end def delete_all_queues(vhost) do - immediately_delete_all_queues(:rabbit_amqqueue.list(vhost)) + try do + immediately_delete_all_queues(:rabbit_amqqueue.list(vhost)) + catch + _, _ -> :ok + end end def immediately_delete_all_queues(qs) do @@ -171,6 +179,14 @@ defmodule TestHelper do end end + def reset_vm_memory_high_watermark() do + try do + :vm_memory_monitor.set_vm_memory_high_watermark(0.4) + catch + _, _ -> :ok + end + end + def emit_list(list, ref, pid) do emit_list_map(list, &(&1), ref, pid) end From 718252832d5c9aa6b6b0e2d4b1cd464a8e67139b Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 14:53:52 +0300 Subject: [PATCH 32/39] Explicitly delete queues in this test --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 555fb496df..5220534098 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -81,13 +81,17 @@ defmodule ListQueuesCommandTest do @tag test_timeout: 1 test "command timeout (several thousands queues in 1ms) return badrpc with timeout value in seconds", context do # we assume it will take longer than 1 ms to list thousands of queues - for i <- 1..5000 do + n = 5000 + for i <- 1..n do declare_queue("test_queue_" <> Integer.to_string(i), @vhost) end capture_io(fn -> assert ListQueuesCommand.run([], context[:opts]) == [{:badrpc, {:timeout, 0.001}}] - end) + end) + for i <- 1..n do + delete_queue("test_queue_" <> Integer.to_string(i), @vhost) + end end @tag test_timeout: 5000 From 87e6c8ab5b49fe41a6040c6b05020ff2ce48e159 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 15:02:21 +0300 Subject: [PATCH 33/39] Use rpc:call/5 in these helpers --- deps/rabbitmq_cli/test/test_helper.exs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/deps/rabbitmq_cli/test/test_helper.exs b/deps/rabbitmq_cli/test/test_helper.exs index d62018ee03..50e43c1665 100644 --- a/deps/rabbitmq_cli/test/test_helper.exs +++ b/deps/rabbitmq_cli/test/test_helper.exs @@ -172,7 +172,13 @@ defmodule TestHelper do def immediately_delete_all_queues(qs) do for q <- qs do try do - :rabbit_amqueue.delete(q, false, false) + :rpc.call( + get_rabbit_hostname, + :rabbit_amqeueue, + :delete, + [q, false, false], + 5000 + ) catch _, _ -> :ok end @@ -181,7 +187,13 @@ defmodule TestHelper do def reset_vm_memory_high_watermark() do try do - :vm_memory_monitor.set_vm_memory_high_watermark(0.4) + :rpc.call( + get_rabbit_hostname, + :vm_memory_monitor, + :set_vm_memory_high_watermark, + [0.4], + 5000 + ) catch _, _ -> :ok end From 50b65e4fb18360211b936c3970eedc22c1ee0396 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 15:19:00 +0300 Subject: [PATCH 34/39] Makes tests pass 10 times in a row --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 2 ++ .../test/set_vm_memory_high_watermark_command_test.exs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index 5220534098..bc74acd6da 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -12,6 +12,7 @@ defmodule ListQueuesCommandTest do :net_kernel.start([:rabbitmqctl, :shortnames]) :net_kernel.connect_node(get_rabbit_hostname) + reset_vm_memory_high_watermark() delete_all_queues() close_all_connections() @@ -207,6 +208,7 @@ defmodule ListQueuesCommandTest do "test_message" <> Integer.to_string(i)) end AMQP.Confirm.wait_for_confirms(channel, 30) + :timer.sleep(200) end) end diff --git a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs index 0fa759978d..3e9cb23ef2 100644 --- a/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs +++ b/deps/rabbitmq_cli/test/set_vm_memory_high_watermark_command_test.exs @@ -27,7 +27,7 @@ defmodule SetVmMemoryHighWatermarkCommandTest do reset_vm_memory_high_watermark() on_exit([], fn -> - :vm_memory_monitor.set_vm_memory_high_watermark(0.4) + reset_vm_memory_high_watermark() :erlang.disconnect_node(get_rabbit_hostname) :net_kernel.stop() From 496fb7ef0388e77ed0db1c4ab746acf8428e0d23 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 15:32:29 +0300 Subject: [PATCH 35/39] Expect standard users in the result set, not the other way around Makes it possible to run this test case against a node that also has non-standard users. --- deps/rabbitmq_cli/test/list_users_command_test.exs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_users_command_test.exs b/deps/rabbitmq_cli/test/list_users_command_test.exs index 39e79b478c..92baaaf89e 100644 --- a/deps/rabbitmq_cli/test/list_users_command_test.exs +++ b/deps/rabbitmq_cli/test/list_users_command_test.exs @@ -56,8 +56,8 @@ defmodule ListUsersCommandTest do capture_io(fn -> matches_found = ListUsersCommand.run([], context[:opts]) - assert Enum.all?(matches_found, fn(user) -> - Enum.find(context[:std_result], fn(found) -> found == user end) + assert Enum.all?(context[:std_result], fn(user) -> + Enum.find(matches_found, fn(found) -> found == user end) end) end) end @@ -74,8 +74,8 @@ defmodule ListUsersCommandTest do capture_io(fn -> matches_found = ListUsersCommand.run([], context[:opts]) - assert Enum.all?(matches_found, fn(user) -> - Enum.find(context[:std_result], fn(found) -> found == user end) + assert Enum.all?(context[:std_result], fn(user) -> + Enum.find(matches_found, fn(found) -> found == user end) end) end) end From 0f472110805581b2094f7c6e51d6f7d01570a5b9 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 15:32:42 +0300 Subject: [PATCH 36/39] Infinity? Come on. --- deps/rabbitmq_cli/test/list_users_command_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/list_users_command_test.exs b/deps/rabbitmq_cli/test/list_users_command_test.exs index 92baaaf89e..cfcf72861b 100644 --- a/deps/rabbitmq_cli/test/list_users_command_test.exs +++ b/deps/rabbitmq_cli/test/list_users_command_test.exs @@ -51,7 +51,7 @@ defmodule ListUsersCommandTest do assert ListUsersCommand.run(["extra"], %{}) == {:too_many_args, ["extra"]} end - @tag test_timeout: :infinity + @tag test_timeout: 15 test "On a successful query, return an array of lists of tuples", context do capture_io(fn -> matches_found = ListUsersCommand.run([], context[:opts]) From 5f2eaf16ce713c2294bea8c94f9e8362e73a0c3b Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 15:36:01 +0300 Subject: [PATCH 37/39] Ditto for list_user_permissions --- .../test/list_user_permissions_command_test.exs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_user_permissions_command_test.exs b/deps/rabbitmq_cli/test/list_user_permissions_command_test.exs index e0cb723534..91b6492a5b 100644 --- a/deps/rabbitmq_cli/test/list_user_permissions_command_test.exs +++ b/deps/rabbitmq_cli/test/list_user_permissions_command_test.exs @@ -64,8 +64,10 @@ defmodule ListUserPermissionsCommandTest do @tag test_timeout: :infinity, username: "guest" test "valid user returns a list of permissions", context do capture_io(fn -> - assert(ListUserPermissionsCommand.run( - [context[:username]], context[:opts]) == context[:result]) + results = ListUserPermissionsCommand.run([context[:username]], context[:opts]) + assert Enum.all?(context[:result], fn(perm) -> + Enum.find(results, fn(found) -> found == perm end) + end) end) end @@ -92,10 +94,10 @@ defmodule ListUserPermissionsCommandTest do @tag test_timeout: 30, username: "guest" test "long user-defined timeout doesn't interfere with operation", context do capture_io(fn -> - assert ListUserPermissionsCommand.run( - [context[:username]], - context[:opts] - ) == context[:result] + results = ListUserPermissionsCommand.run([context[:username]], context[:opts]) + Enum.all?(context[:result], fn(perm) -> + Enum.find(results, fn(found) -> found == perm end) + end) end) end From ccd86c7acdc4e1decb5f35196657638b358c856b Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 15:46:44 +0300 Subject: [PATCH 38/39] Ditto for list_vhosts --- .../test/list_vhosts_command_test.exs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/deps/rabbitmq_cli/test/list_vhosts_command_test.exs b/deps/rabbitmq_cli/test/list_vhosts_command_test.exs index 88cda58587..69dc05f917 100644 --- a/deps/rabbitmq_cli/test/list_vhosts_command_test.exs +++ b/deps/rabbitmq_cli/test/list_vhosts_command_test.exs @@ -93,8 +93,8 @@ defmodule ListVhostsCommandTest do capture_io(fn -> matches_found = ListVhostsCommand.run([], context[:opts]) - assert Enum.all?(matches_found, fn(vhost) -> - Enum.find(context[:name_result], fn(found) -> found == vhost end) + assert Enum.all?(context[:name_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) end) end) end @@ -104,10 +104,8 @@ defmodule ListVhostsCommandTest do # checks to ensure that all expected vhosts are in the results capture_io(fn -> matches_found = ListVhostsCommand.run(["name"], context[:opts]) - - assert matches_found - |> Enum.all?(fn(vhost) -> - Enum.find(context[:name_result], fn(found) -> found == vhost end) + assert Enum.all?(context[:name_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) end) end) end @@ -116,8 +114,10 @@ defmodule ListVhostsCommandTest do test "with the tracing tag, print just say if tracing is on", context do # checks to ensure that all expected vhosts are in the results capture_io(fn -> - found = ListVhostsCommand.run(["tracing"], context[:opts]) - assert found == context[:tracing_result] + matches_found = ListVhostsCommand.run(["tracing"], context[:opts]) + assert Enum.all?(context[:tracing_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) + end) end) end @@ -154,16 +154,16 @@ defmodule ListVhostsCommandTest do # checks to ensure that all expected vhosts are in the results capture_io(fn -> matches_found = ListVhostsCommand.run(["name", "tracing"], context[:opts]) - assert Enum.all?(matches_found, fn(vhost) -> - Enum.find(context[:full_result], fn(found) -> found == vhost end) + assert Enum.all?(context[:full_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) end) end) # checks to ensure that all expected vhosts are in the results capture_io(fn -> matches_found = ListVhostsCommand.run(["tracing", "name"], context[:opts]) - assert Enum.all?(matches_found, fn(vhost) -> - Enum.find(context[:transposed_result], fn(found) -> found == vhost end) + assert Enum.all?(context[:transposed_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) end) end) end @@ -172,9 +172,9 @@ defmodule ListVhostsCommandTest do test "duplicate args do not produce duplicate entries", context do # checks to ensure that all expected vhosts are in the results capture_io(fn -> - assert ListVhostsCommand.run(["name", "name"], context[:opts]) - |> Enum.all?(fn(vhost) -> - Enum.find(context[:name_result], fn(found) -> found == vhost end) + matches_found = ListVhostsCommand.run(["name", "name"], context[:opts]) + assert Enum.all?(context[:name_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) end) end) end @@ -183,9 +183,9 @@ defmodule ListVhostsCommandTest do test "sufficiently long timeouts don't interfere with results", context do # checks to ensure that all expected vhosts are in the results capture_io(fn -> - assert ListVhostsCommand.run(["name", "tracing"], context[:opts]) - |> Enum.all?(fn(vhost) -> - Enum.find(context[:full_result], fn(found) -> found == vhost end) + matches_found = ListVhostsCommand.run(["name", "tracing"], context[:opts]) + assert Enum.all?(context[:full_result], fn(vhost) -> + Enum.find(matches_found, fn(found) -> found == vhost end) end) end) end From e0baa7da11fc07d005ac93731a6f02a62347f223 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Sat, 21 May 2016 17:18:19 +0300 Subject: [PATCH 39/39] This sleep is no longer needed --- deps/rabbitmq_cli/test/list_queues_command_test.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/deps/rabbitmq_cli/test/list_queues_command_test.exs b/deps/rabbitmq_cli/test/list_queues_command_test.exs index bc74acd6da..cd20216c04 100644 --- a/deps/rabbitmq_cli/test/list_queues_command_test.exs +++ b/deps/rabbitmq_cli/test/list_queues_command_test.exs @@ -208,7 +208,6 @@ defmodule ListQueuesCommandTest do "test_message" <> Integer.to_string(i)) end AMQP.Confirm.wait_for_confirms(channel, 30) - :timer.sleep(200) end) end