216 lines
9.5 KiB
Erlang
216 lines
9.5 KiB
Erlang
%% This Source Code Form is subject to the terms of the Mozilla Public
|
|
%% License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
%%
|
|
%% Copyright (c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
|
|
%%
|
|
|
|
-module(routing_SUITE).
|
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-include_lib("amqp_client/include/amqp_client.hrl").
|
|
-compile([nowarn_export_all, export_all]).
|
|
-compile(export_all).
|
|
|
|
-define(VHOST, <<"/">>).
|
|
-define(USER, <<"user">>).
|
|
|
|
all() ->
|
|
[
|
|
{group, mnesia_store},
|
|
{group, khepri_store}
|
|
].
|
|
|
|
suite() ->
|
|
[{timetrap, {minutes, 5}}].
|
|
|
|
groups() ->
|
|
[
|
|
{mnesia_store, [], all_tests()},
|
|
{khepri_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, Config0) ->
|
|
Config = rabbit_ct_helpers:set_config(Config0, [{metadata_store, mnesia}]),
|
|
init_per_group_common(Group, Config, 1);
|
|
init_per_group(khepri_store = Group, Config0) ->
|
|
Config = rabbit_ct_helpers:set_config(Config0, [{metadata_store, khepri}]),
|
|
init_per_group_common(Group, Config, 1).
|
|
|
|
init_per_group_common(Group, Config, Size) ->
|
|
Config1 = rabbit_ct_helpers:set_config(Config, [
|
|
{rmq_nodename_suffix, Group},
|
|
{rmq_nodes_count, Size}
|
|
]),
|
|
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">>),
|
|
{ok, 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'{}, <<>>),
|
|
{ok, 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).
|