Skip to content

Commit

Permalink
Merge pull request #9254 from rabbitmq/routing-suite
Browse files Browse the repository at this point in the history
routing_SUITE: extract topic test from unit_access_control_SUITE
  • Loading branch information
michaelklishin authored Sep 1, 2023
2 parents 82fcaf3 + 6b4cfe8 commit 337a47e
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 143 deletions.
5 changes: 5 additions & 0 deletions deps/rabbit/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,11 @@ rabbitmq_integration_suite(
],
)

rabbitmq_integration_suite(
name = "routing_SUITE",
size = "large",
)

assert_suites()

filegroup(
Expand Down
9 changes: 9 additions & 0 deletions deps/rabbit/app.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2028,3 +2028,12 @@ def test_suite_beam_files(name = "test_suite_beam_files"):
erlc_opts = "//:test_erlc_opts",
deps = ["//deps/amqp10_common:erlang_app", "//deps/rabbit_common:erlang_app"],
)
erlang_bytecode(
name = "routing_SUITE_beam_files",
testonly = True,
srcs = ["test/routing_SUITE.erl"],
outs = ["test/routing_SUITE.beam"],
app_name = "rabbit",
erlc_opts = "//:test_erlc_opts",
deps = ["//deps/amqp_client:erlang_app"],
)
208 changes: 208 additions & 0 deletions deps/rabbit/test/routing_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2011-2023 VMware, Inc. or its affiliates. All rights reserved.
%%

-module(routing_SUITE).

-include_lib("eunit/include/eunit.hrl").
-include_lib("amqp_client/include/amqp_client.hrl").
-include_lib("common_test/include/ct.hrl").

-compile([nowarn_export_all, export_all]).
-compile(export_all).

-define(VHOST, <<"/">>).
-define(USER, <<"user">>).

all() ->
[
{group, mnesia_store}
].

suite() ->
[{timetrap, {minutes, 5}}].

groups() ->
[
{mnesia_store, [], all_tests()}
].

all_tests() ->
[
topic
].

%% -------------------------------------------------------------------
%% Test suite setup/teardown.
%% -------------------------------------------------------------------

init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
rabbit_ct_helpers:run_setup_steps(Config).

end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).

init_per_group(mnesia_store = Group, Config) ->
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodename_suffix, Group},
{rmq_nodes_count, 1}
]),
rabbit_ct_helpers:run_steps(Config1,
rabbit_ct_broker_helpers:setup_steps() ++
rabbit_ct_client_helpers:setup_steps()).

end_per_group(_Group, Config) ->
rabbit_ct_helpers:run_steps(Config,
rabbit_ct_client_helpers:teardown_steps() ++
rabbit_ct_broker_helpers:teardown_steps()).

init_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_started(Config, Testcase).

end_per_testcase(Testcase, Config) ->
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_db_binding, clear, []),
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_db_exchange, clear, []),
rabbit_ct_helpers:testcase_finished(Config, Testcase).

%% ---------------------------------------------------------------------------
%% Test Cases
%% ---------------------------------------------------------------------------

topic(Config) ->
passed = rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, topic1, [Config]).

topic1(_Config) ->
XName = rabbit_misc:r(?VHOST, exchange, <<"topic_matching-exchange">>),
X = rabbit_exchange:declare(
XName, topic, _Durable = true, _AutoDelete = false,
_Internal = false, _Args = [], ?USER),

%% add some bindings
Bindings = [#binding{source = XName,
key = list_to_binary(Key),
destination = rabbit_misc:r(
?VHOST, queue, list_to_binary(Q)),
args = Args} ||
{Key, Q, Args} <- [{"a.b.c", "t1", []},
{"a.*.c", "t2", []},
{"a.#.b", "t3", []},
{"a.b.b.c", "t4", []},
{"#", "t5", []},
{"#.#", "t6", []},
{"#.b", "t7", []},
{"*.*", "t8", []},
{"a.*", "t9", []},
{"*.b.c", "t10", []},
{"a.#", "t11", []},
{"a.#.#", "t12", []},
{"b.b.c", "t13", []},
{"a.b.b", "t14", []},
{"a.b", "t15", []},
{"b.c", "t16", []},
{"", "t17", []},
{"*.*.*", "t18", []},
{"vodka.martini", "t19", []},
{"a.b.c", "t20", []},
{"*.#", "t21", []},
{"#.*.#", "t22", []},
{"*.#.#", "t23", []},
{"#.#.#", "t24", []},
{"*", "t25", []},
{"#.b.#", "t26", []},
{"args-test", "t27",
[{<<"foo">>, longstr, <<"bar">>}]},
{"args-test", "t27", %% Note aliasing
[{<<"foo">>, longstr, <<"baz">>}]}]],
[ok = create_binding(Binding) || Binding <- Bindings],

test_topic_expect_match(
X, [{"a.b.c", ["t1", "t2", "t5", "t6", "t10", "t11", "t12",
"t18", "t20", "t21", "t22", "t23", "t24",
"t26"]},
{"a.b", ["t3", "t5", "t6", "t7", "t8", "t9", "t11",
"t12", "t15", "t21", "t22", "t23", "t24",
"t26"]},
{"a.b.b", ["t3", "t5", "t6", "t7", "t11", "t12", "t14",
"t18", "t21", "t22", "t23", "t24", "t26"]},
{"", ["t5", "t6", "t17", "t24"]},
{"b.c.c", ["t5", "t6", "t18", "t21", "t22", "t23",
"t24", "t26"]},
{"a.a.a.a.a", ["t5", "t6", "t11", "t12", "t21", "t22",
"t23", "t24"]},
{"vodka.gin", ["t5", "t6", "t8", "t21", "t22", "t23",
"t24"]},
{"vodka.martini", ["t5", "t6", "t8", "t19", "t21", "t22", "t23",
"t24"]},
{"b.b.c", ["t5", "t6", "t10", "t13", "t18", "t21",
"t22", "t23", "t24", "t26"]},
{"nothing.here.at.all", ["t5", "t6", "t21", "t22", "t23", "t24"]},
{"oneword", ["t5", "t6", "t21", "t22", "t23", "t24",
"t25"]},
{"args-test", ["t5", "t6", "t21", "t22", "t23", "t24",
"t25", "t27"]}]),

%% remove some bindings
RemovedBindings = [lists:nth(N, Bindings) || N <- [1, 5, 11, 19, 21, 28]],
[delete_binding(Binding) || Binding <- RemovedBindings],

%% test some matches
test_topic_expect_match(
X,
[{"a.b.c", ["t2", "t6", "t10", "t12", "t18", "t20", "t22",
"t23", "t24", "t26"]},
{"a.b", ["t3", "t6", "t7", "t8", "t9", "t12", "t15",
"t22", "t23", "t24", "t26"]},
{"a.b.b", ["t3", "t6", "t7", "t12", "t14", "t18", "t22",
"t23", "t24", "t26"]},
{"", ["t6", "t17", "t24"]},
{"b.c.c", ["t6", "t18", "t22", "t23", "t24", "t26"]},
{"a.a.a.a.a", ["t6", "t12", "t22", "t23", "t24"]},
{"vodka.gin", ["t6", "t8", "t22", "t23", "t24"]},
{"vodka.martini", ["t6", "t8", "t22", "t23", "t24"]},
{"b.b.c", ["t6", "t10", "t13", "t18", "t22", "t23",
"t24", "t26"]},
{"nothing.here.at.all", ["t6", "t22", "t23", "t24"]},
{"oneword", ["t6", "t22", "t23", "t24", "t25"]},
{"args-test", ["t6", "t22", "t23", "t24", "t25", "t27"]}]),

%% remove the entire exchange
rabbit_exchange:delete(XName, _IfUnused = false, ?USER),
%% none should match now
test_topic_expect_match(X, [{"a.b.c", []}, {"b.b.c", []}, {"", []}]),
passed.

%% Internal functions.

%% Create a binding, creating the queue if it does not already exist.
create_binding(#binding{destination = QName} = Binding) ->
case rabbit_amqqueue:declare(QName, true, false, [], self(), ?USER) of
{new, _Q} ->
ok;
{existing, _Q} ->
ok
end,
ok = rabbit_binding:add(Binding, ?USER).

delete_binding(Binding) ->
ok = rabbit_binding:remove(Binding, ?USER).

test_topic_expect_match(X, List) ->
lists:foreach(
fun ({Key, Expected}) ->
BinKey = list_to_binary(Key),
Message = rabbit_basic:message(X#exchange.name, BinKey,
#'P_basic'{}, <<>>),
Msg = mc_amqpl:message(X#exchange.name,
BinKey,
Message#basic_message.content),
Res = rabbit_exchange_type_topic:route(X, Msg),
ExpectedRes = [rabbit_misc:r(?VHOST, queue, list_to_binary(Q)) ||
Q <- Expected],
?assertEqual(
lists:usort(ExpectedRes), lists:usort(Res),
lists:flatten(io_lib:format("Routing key: ~p", [BinKey])))
end, List).
143 changes: 0 additions & 143 deletions deps/rabbit/test/unit_access_control_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ groups() ->
login_of_passwordless_user,
set_tags_for_passwordless_user,
change_password,
topic_matching,
auth_backend_internal_expand_topic_permission,
rabbit_direct_extract_extra_auth_props
]}
Expand Down Expand Up @@ -296,145 +295,3 @@ test_unsupported_connection_refusal(H, P, Header) ->
{ok, <<"AMQP",0,0,9,1>>} = gen_tcp:recv(C, 8, 100),
ok = gen_tcp:close(C),
passed.


%% -------------------------------------------------------------------
%% Topic matching.
%% -------------------------------------------------------------------

topic_matching(Config) ->
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
?MODULE, topic_matching1, [Config]).

topic_matching1(_Config) ->
XName = #resource{virtual_host = <<"/">>,
kind = exchange,
name = <<"topic_matching-exchange">>},
X0 = #exchange{name = XName, type = topic, durable = false,
auto_delete = false, arguments = []},
X = rabbit_exchange_decorator:set(X0),
%% create
rabbit_exchange_type_topic:validate(X),
exchange_op_callback(X, create, []),

%% add some bindings
Bindings = [#binding{source = XName,
key = list_to_binary(Key),
destination = #resource{virtual_host = <<"/">>,
kind = queue,
name = list_to_binary(Q)},
args = Args} ||
{Key, Q, Args} <- [{"a.b.c", "t1", []},
{"a.*.c", "t2", []},
{"a.#.b", "t3", []},
{"a.b.b.c", "t4", []},
{"#", "t5", []},
{"#.#", "t6", []},
{"#.b", "t7", []},
{"*.*", "t8", []},
{"a.*", "t9", []},
{"*.b.c", "t10", []},
{"a.#", "t11", []},
{"a.#.#", "t12", []},
{"b.b.c", "t13", []},
{"a.b.b", "t14", []},
{"a.b", "t15", []},
{"b.c", "t16", []},
{"", "t17", []},
{"*.*.*", "t18", []},
{"vodka.martini", "t19", []},
{"a.b.c", "t20", []},
{"*.#", "t21", []},
{"#.*.#", "t22", []},
{"*.#.#", "t23", []},
{"#.#.#", "t24", []},
{"*", "t25", []},
{"#.b.#", "t26", []},
{"args-test", "t27",
[{<<"foo">>, longstr, <<"bar">>}]},
{"args-test", "t27", %% Note aliasing
[{<<"foo">>, longstr, <<"baz">>}]}]],
lists:foreach(fun (B) -> exchange_op_callback(X, add_binding, [B]) end,
Bindings),

%% test some matches
test_topic_expect_match(
X, [{"a.b.c", ["t1", "t2", "t5", "t6", "t10", "t11", "t12",
"t18", "t20", "t21", "t22", "t23", "t24",
"t26"]},
{"a.b", ["t3", "t5", "t6", "t7", "t8", "t9", "t11",
"t12", "t15", "t21", "t22", "t23", "t24",
"t26"]},
{"a.b.b", ["t3", "t5", "t6", "t7", "t11", "t12", "t14",
"t18", "t21", "t22", "t23", "t24", "t26"]},
{"", ["t5", "t6", "t17", "t24"]},
{"b.c.c", ["t5", "t6", "t18", "t21", "t22", "t23",
"t24", "t26"]},
{"a.a.a.a.a", ["t5", "t6", "t11", "t12", "t21", "t22",
"t23", "t24"]},
{"vodka.gin", ["t5", "t6", "t8", "t21", "t22", "t23",
"t24"]},
{"vodka.martini", ["t5", "t6", "t8", "t19", "t21", "t22", "t23",
"t24"]},
{"b.b.c", ["t5", "t6", "t10", "t13", "t18", "t21",
"t22", "t23", "t24", "t26"]},
{"nothing.here.at.all", ["t5", "t6", "t21", "t22", "t23", "t24"]},
{"oneword", ["t5", "t6", "t21", "t22", "t23", "t24",
"t25"]},
{"args-test", ["t5", "t6", "t21", "t22", "t23", "t24",
"t25", "t27"]}]),
%% remove some bindings
RemovedBindings = [lists:nth(1, Bindings), lists:nth(5, Bindings),
lists:nth(11, Bindings), lists:nth(19, Bindings),
lists:nth(21, Bindings), lists:nth(28, Bindings)],
exchange_op_callback(X, remove_bindings, [RemovedBindings]),
_RemainingBindings = ordsets:to_list(
ordsets:subtract(ordsets:from_list(Bindings),
ordsets:from_list(RemovedBindings))),

%% test some matches
test_topic_expect_match(
X,
[{"a.b.c", ["t2", "t6", "t10", "t12", "t18", "t20", "t22",
"t23", "t24", "t26"]},
{"a.b", ["t3", "t6", "t7", "t8", "t9", "t12", "t15",
"t22", "t23", "t24", "t26"]},
{"a.b.b", ["t3", "t6", "t7", "t12", "t14", "t18", "t22",
"t23", "t24", "t26"]},
{"", ["t6", "t17", "t24"]},
{"b.c.c", ["t6", "t18", "t22", "t23", "t24", "t26"]},
{"a.a.a.a.a", ["t6", "t12", "t22", "t23", "t24"]},
{"vodka.gin", ["t6", "t8", "t22", "t23", "t24"]},
{"vodka.martini", ["t6", "t8", "t22", "t23", "t24"]},
{"b.b.c", ["t6", "t10", "t13", "t18", "t22", "t23",
"t24", "t26"]},
{"nothing.here.at.all", ["t6", "t22", "t23", "t24"]},
{"oneword", ["t6", "t22", "t23", "t24", "t25"]},
{"args-test", ["t6", "t22", "t23", "t24", "t25", "t27"]}]),

%% remove the entire exchange
exchange_op_callback(X, delete, []),
%% none should match now
test_topic_expect_match(X, [{"a.b.c", []}, {"b.b.c", []}, {"", []}]),
passed.

exchange_op_callback(X, Fun, Args) ->
rabbit_exchange:callback(X, Fun, none, [X] ++ Args).

test_topic_expect_match(X, List) ->
lists:foreach(
fun ({Key, Expected}) ->
BinKey = list_to_binary(Key),
Message = rabbit_basic:message(X#exchange.name, BinKey,
#'P_basic'{}, <<>>),
Msg = mc_amqpl:message(X#exchange.name,
BinKey,
Message#basic_message.content),
Res = rabbit_exchange_type_topic:route(X, Msg),
ExpectedRes = lists:map(
fun (Q) -> #resource{virtual_host = <<"/">>,
kind = queue,
name = list_to_binary(Q)}
end, Expected),
true = (lists:usort(ExpectedRes) =:= lists:usort(Res))
end, List).

0 comments on commit 337a47e

Please sign in to comment.