Skip to content

Commit 3aeb081

Browse files
committed
Unit test rabbit_db_topic_exchange and API updates
1 parent 164eca2 commit 3aeb081

File tree

4 files changed

+211
-22
lines changed

4 files changed

+211
-22
lines changed

deps/rabbit/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,11 @@ rabbitmq_integration_suite(
11131113
size = "small",
11141114
)
11151115

1116+
rabbitmq_integration_suite(
1117+
name = "unit_rabbit_db_topic_exchange_SUITE",
1118+
size = "small",
1119+
)
1120+
11161121
assert_suites()
11171122

11181123
filegroup(

deps/rabbit/src/rabbit_db_topic_exchange.erl

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,28 @@
99

1010
-include_lib("rabbit_common/include/rabbit.hrl").
1111

12-
-export([insert/1, delete_all_for_exchange/1, delete/1, match/2]).
12+
-export([set/1, delete_all_for_exchange/1, delete/1, match/2]).
13+
14+
%% For testing
15+
-export([clear/0]).
16+
17+
-define(MNESIA_NODE_TABLE, rabbit_topic_trie_node).
18+
-define(MNESIA_EDGE_TABLE, rabbit_topic_trie_edge).
19+
-define(MNESIA_BINDING_TABLE, rabbit_topic_trie_binding).
1320

1421
%% -------------------------------------------------------------------
15-
%% insert().
22+
%% set().
1623
%% -------------------------------------------------------------------
1724

18-
-spec insert(Binding) -> ok when
25+
-spec set(Binding) -> ok when
1926
Binding :: rabbit_types:binding().
20-
%% @doc Inserts a topic binding.
27+
%% @doc Sets a topic binding.
2128
%%
2229
%% @private
2330

24-
insert(#binding{source = XName, key = RoutingKey, destination = Destination, args = Args}) ->
31+
set(#binding{source = XName, key = RoutingKey, destination = Destination, args = Args}) ->
2532
rabbit_db:run(
26-
#{mnesia => fun() -> insert_in_mnesia(XName, RoutingKey, Destination, Args) end
33+
#{mnesia => fun() -> set_in_mnesia(XName, RoutingKey, Destination, Args) end
2734
}).
2835

2936
%% -------------------------------------------------------------------
@@ -78,13 +85,32 @@ match(XName, RoutingKey) ->
7885
end
7986
}).
8087

88+
%% -------------------------------------------------------------------
89+
%% clear().
90+
%% -------------------------------------------------------------------
91+
92+
-spec clear() -> ok.
93+
%% @doc Deletes all topic bindings
94+
%%
95+
%% @private
96+
97+
clear() ->
98+
rabbit_db:run(
99+
#{mnesia => fun() -> clear_in_mnesia() end
100+
}).
101+
102+
clear_in_mnesia() ->
103+
mnesia:clear_table(?MNESIA_NODE_TABLE),
104+
mnesia:clear_table(?MNESIA_EDGE_TABLE),
105+
mnesia:clear_table(?MNESIA_BINDING_TABLE).
106+
81107
%% Internal
82108
%% --------------------------------------------------------------
83109

84110
split_topic_key(Key) ->
85111
split_topic_key(Key, [], []).
86112

87-
insert_in_mnesia(XName, RoutingKey, Destination, Args) ->
113+
set_in_mnesia(XName, RoutingKey, Destination, Args) ->
88114
rabbit_mnesia:execute_mnesia_transaction(
89115
fun() ->
90116
FinalNode = follow_down_create(XName, split_topic_key(RoutingKey)),
@@ -106,19 +132,19 @@ match_in_mnesia(XName, RoutingKey) ->
106132
mnesia:async_dirty(fun trie_match/2, [XName, Words]).
107133

108134
trie_remove_all_nodes(X) ->
109-
remove_all(rabbit_topic_trie_node,
135+
remove_all(?MNESIA_NODE_TABLE,
110136
#topic_trie_node{trie_node = #trie_node{exchange_name = X,
111137
_ = '_'},
112138
_ = '_'}).
113139

114140
trie_remove_all_edges(X) ->
115-
remove_all(rabbit_topic_trie_edge,
141+
remove_all(?MNESIA_EDGE_TABLE,
116142
#topic_trie_edge{trie_edge = #trie_edge{exchange_name = X,
117143
_ = '_'},
118144
_ = '_'}).
119145

120146
trie_remove_all_bindings(X) ->
121-
remove_all(rabbit_topic_trie_binding,
147+
remove_all(?MNESIA_BINDING_TABLE,
122148
#topic_trie_binding{
123149
trie_binding = #trie_binding{exchange_name = X, _ = '_'},
124150
_ = '_'}).
@@ -133,9 +159,9 @@ delete_in_mnesia_tx(Bs) ->
133159
case Bs of
134160
[_] -> ok;
135161
_ -> [mnesia:lock({table, T}, write) ||
136-
T <- [rabbit_topic_trie_node,
137-
rabbit_topic_trie_edge,
138-
rabbit_topic_trie_binding]]
162+
T <- [?MNESIA_NODE_TABLE,
163+
?MNESIA_EDGE_TABLE,
164+
?MNESIA_BINDING_TABLE]]
139165
end,
140166
[case follow_down_get_path(X, split_topic_key(K)) of
141167
{ok, Path = [{FinalNode, _} | _]} ->
@@ -222,15 +248,15 @@ follow_down(X, CurNode, AccFun, Acc, Words = [W | RestW]) ->
222248
remove_path_if_empty(_, [{root, none}]) ->
223249
ok;
224250
remove_path_if_empty(X, [{Node, W} | [{Parent, _} | _] = RestPath]) ->
225-
case mnesia:read(rabbit_topic_trie_node,
251+
case mnesia:read(?MNESIA_NODE_TABLE,
226252
#trie_node{exchange_name = X, node_id = Node}, write) of
227253
[] -> trie_remove_edge(X, Parent, Node, W),
228254
remove_path_if_empty(X, RestPath);
229255
_ -> ok
230256
end.
231257

232258
trie_child(X, Node, Word) ->
233-
case mnesia:read({rabbit_topic_trie_edge,
259+
case mnesia:read({?MNESIA_EDGE_TABLE,
234260
#trie_edge{exchange_name = X,
235261
node_id = Node,
236262
word = Word}}) of
@@ -244,10 +270,10 @@ trie_bindings(X, Node) ->
244270
node_id = Node,
245271
destination = '$1',
246272
arguments = '_'}},
247-
mnesia:select(rabbit_topic_trie_binding, [{MatchHead, [], ['$1']}]).
273+
mnesia:select(?MNESIA_BINDING_TABLE, [{MatchHead, [], ['$1']}]).
248274

249275
trie_update_node_counts(X, Node, Field, Delta) ->
250-
E = case mnesia:read(rabbit_topic_trie_node,
276+
E = case mnesia:read(?MNESIA_NODE_TABLE,
251277
#trie_node{exchange_name = X,
252278
node_id = Node}, write) of
253279
[] -> #topic_trie_node{trie_node = #trie_node{
@@ -259,9 +285,9 @@ trie_update_node_counts(X, Node, Field, Delta) ->
259285
end,
260286
case setelement(Field, E, element(Field, E) + Delta) of
261287
#topic_trie_node{edge_count = 0, binding_count = 0} ->
262-
ok = mnesia:delete_object(rabbit_topic_trie_node, E, write);
288+
ok = mnesia:delete_object(?MNESIA_NODE_TABLE, E, write);
263289
EN ->
264-
ok = mnesia:write(rabbit_topic_trie_node, EN, write)
290+
ok = mnesia:write(?MNESIA_NODE_TABLE, EN, write)
265291
end.
266292

267293
trie_add_edge(X, FromNode, ToNode, W) ->
@@ -273,7 +299,7 @@ trie_remove_edge(X, FromNode, ToNode, W) ->
273299
trie_edge_op(X, FromNode, ToNode, W, fun mnesia:delete_object/3).
274300

275301
trie_edge_op(X, FromNode, ToNode, W, Op) ->
276-
ok = Op(rabbit_topic_trie_edge,
302+
ok = Op(?MNESIA_EDGE_TABLE,
277303
#topic_trie_edge{trie_edge = #trie_edge{exchange_name = X,
278304
node_id = FromNode,
279305
word = W},
@@ -289,7 +315,7 @@ trie_remove_binding(X, Node, D, Args) ->
289315
trie_binding_op(X, Node, D, Args, fun mnesia:delete_object/3).
290316

291317
trie_binding_op(X, Node, D, Args, Op) ->
292-
ok = Op(rabbit_topic_trie_binding,
318+
ok = Op(?MNESIA_BINDING_TABLE,
293319
#topic_trie_binding{
294320
trie_binding = #trie_binding{exchange_name = X,
295321
node_id = Node,

deps/rabbit/src/rabbit_exchange_type_topic.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ delete(_Serial, #exchange{name = X}) ->
4949
policy_changed(_X1, _X2) -> ok.
5050

5151
add_binding(_Serial, _Exchange, Binding) ->
52-
rabbit_db_topic_exchange:insert(Binding).
52+
rabbit_db_topic_exchange:set(Binding).
5353

5454
remove_bindings(_Serial, _X, Bs) ->
5555
rabbit_db_topic_exchange:delete(Bs).
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2023 VMware, Inc. or its affiliates. All rights reserved.
6+
%%
7+
8+
-module(unit_rabbit_db_topic_exchange_SUITE).
9+
10+
-include_lib("rabbit_common/include/rabbit.hrl").
11+
-include_lib("eunit/include/eunit.hrl").
12+
-include_lib("common_test/include/ct.hrl").
13+
14+
-compile(export_all).
15+
16+
-define(VHOST, <<"/">>).
17+
18+
all() ->
19+
[
20+
{group, all_tests}
21+
].
22+
23+
groups() ->
24+
[
25+
{all_tests, [], all_tests()}
26+
].
27+
28+
all_tests() ->
29+
[
30+
set,
31+
delete,
32+
delete_all_for_exchange,
33+
match
34+
].
35+
36+
%% -------------------------------------------------------------------
37+
%% Test suite setup/teardown.
38+
%% -------------------------------------------------------------------
39+
40+
init_per_suite(Config) ->
41+
rabbit_ct_helpers:log_environment(),
42+
rabbit_ct_helpers:run_setup_steps(Config).
43+
44+
end_per_suite(Config) ->
45+
rabbit_ct_helpers:run_teardown_steps(Config).
46+
47+
init_per_group(Group, Config) ->
48+
Config1 = rabbit_ct_helpers:set_config(Config, [
49+
{rmq_nodename_suffix, Group},
50+
{rmq_nodes_count, 1}
51+
]),
52+
rabbit_ct_helpers:run_steps(Config1,
53+
rabbit_ct_broker_helpers:setup_steps() ++
54+
rabbit_ct_client_helpers:setup_steps()).
55+
56+
end_per_group(_Group, Config) ->
57+
rabbit_ct_helpers:run_steps(Config,
58+
rabbit_ct_client_helpers:teardown_steps() ++
59+
rabbit_ct_broker_helpers:teardown_steps()).
60+
61+
init_per_testcase(Testcase, Config) ->
62+
rabbit_ct_helpers:testcase_started(Config, Testcase).
63+
64+
end_per_testcase(Testcase, Config) ->
65+
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_db_topic_exchange, clear, []),
66+
rabbit_ct_helpers:testcase_finished(Config, Testcase).
67+
68+
%% ---------------------------------------------------------------------------
69+
%% Test Cases
70+
%% ---------------------------------------------------------------------------
71+
72+
set(Config) ->
73+
passed = rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, set1, [Config]).
74+
75+
set1(_Config) ->
76+
Src = rabbit_misc:r(?VHOST, exchange, <<"test-exchange">>),
77+
Dst = rabbit_misc:r(?VHOST, queue, <<"test-queue">>),
78+
RoutingKey = <<"a.b.c">>,
79+
Binding = #binding{source = Src, key = RoutingKey, destination = Dst, args = #{}},
80+
?assertEqual([], rabbit_db_topic_exchange:match(Src, RoutingKey)),
81+
?assertEqual(ok, rabbit_db_topic_exchange:set(Binding)),
82+
?assertEqual(ok, rabbit_db_topic_exchange:set(Binding)),
83+
?assertEqual([Dst], rabbit_db_topic_exchange:match(Src, RoutingKey)),
84+
passed.
85+
86+
delete(Config) ->
87+
passed = rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, delete1, [Config]).
88+
89+
delete1(_Config) ->
90+
Src = rabbit_misc:r(?VHOST, exchange, <<"test-exchange">>),
91+
Dst1 = rabbit_misc:r(?VHOST, queue, <<"test-queue1">>),
92+
Dst2 = rabbit_misc:r(?VHOST, queue, <<"test-queue2">>),
93+
Dst3= rabbit_misc:r(?VHOST, queue, <<"test-queue3">>),
94+
Dsts = lists:sort([Dst1, Dst2, Dst3]),
95+
RoutingKey = <<"a.b.c">>,
96+
Binding1 = #binding{source = Src, key = RoutingKey, destination = Dst1, args = #{}},
97+
Binding2 = #binding{source = Src, key = RoutingKey, destination = Dst2, args = #{}},
98+
Binding3 = #binding{source = Src, key = RoutingKey, destination = Dst3, args = #{}},
99+
?assertEqual(ok, rabbit_db_topic_exchange:delete([Binding1])),
100+
?assertEqual(ok, rabbit_db_topic_exchange:set(Binding1)),
101+
?assertEqual(ok, rabbit_db_topic_exchange:set(Binding2)),
102+
?assertEqual(ok, rabbit_db_topic_exchange:set(Binding3)),
103+
?assertEqual(Dsts, lists:sort(rabbit_db_topic_exchange:match(Src, RoutingKey))),
104+
?assertEqual(ok, rabbit_db_topic_exchange:delete([Binding1, Binding2])),
105+
?assertEqual([Dst3], rabbit_db_topic_exchange:match(Src, RoutingKey)),
106+
passed.
107+
108+
delete_all_for_exchange(Config) ->
109+
passed = rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, delete_all_for_exchange1, [Config]).
110+
111+
delete_all_for_exchange1(_Config) ->
112+
Src1 = rabbit_misc:r(?VHOST, exchange, <<"test-exchange1">>),
113+
Src2 = rabbit_misc:r(?VHOST, exchange, <<"test-exchange2">>),
114+
Dst1 = rabbit_misc:r(?VHOST, queue, <<"test-queue1">>),
115+
Dst2 = rabbit_misc:r(?VHOST, queue, <<"test-queue2">>),
116+
Dsts = lists:sort([Dst1, Dst2]),
117+
RoutingKey = <<"a.b.c">>,
118+
?assertEqual(ok, rabbit_db_topic_exchange:delete_all_for_exchange(Src1)),
119+
set(Src1, RoutingKey, Dst1),
120+
set(Src1, RoutingKey, Dst2),
121+
set(Src2, RoutingKey, Dst1),
122+
?assertEqual(Dsts, lists:sort(rabbit_db_topic_exchange:match(Src1, RoutingKey))),
123+
?assertEqual([Dst1], rabbit_db_topic_exchange:match(Src2, RoutingKey)),
124+
?assertEqual(ok, rabbit_db_topic_exchange:delete_all_for_exchange(Src1)),
125+
?assertEqual([], rabbit_db_topic_exchange:match(Src1, RoutingKey)),
126+
?assertEqual([Dst1], rabbit_db_topic_exchange:match(Src2, RoutingKey)),
127+
passed.
128+
129+
match(Config) ->
130+
passed = rabbit_ct_broker_helpers:rpc(Config, 0, ?MODULE, match1, [Config]).
131+
132+
match1(_Config) ->
133+
Src = rabbit_misc:r(?VHOST, exchange, <<"test-exchange">>),
134+
Dst1 = rabbit_misc:r(?VHOST, queue, <<"test-queue1">>),
135+
Dst2 = rabbit_misc:r(?VHOST, queue, <<"test-queue2">>),
136+
Dst3 = rabbit_misc:r(?VHOST, queue, <<"test-queue3">>),
137+
Dst4 = rabbit_misc:r(?VHOST, queue, <<"test-queue4">>),
138+
Dst5 = rabbit_misc:r(?VHOST, queue, <<"test-queue5">>),
139+
Dst6 = rabbit_misc:r(?VHOST, queue, <<"test-queue6">>),
140+
set(Src, <<"a.b.c">>, Dst1),
141+
set(Src, <<"a.*.c">>, Dst2),
142+
set(Src, <<"*.#">>, Dst3),
143+
set(Src, <<"#">>, Dst4),
144+
set(Src, <<"#.#">>, Dst5),
145+
set(Src, <<"a.*">>, Dst6),
146+
Dsts1 = lists:sort([Dst1, Dst2, Dst3, Dst4, Dst5]),
147+
?assertEqual(Dsts1, lists:usort(rabbit_db_topic_exchange:match(Src, <<"a.b.c">>))),
148+
Dsts2 = lists:sort([Dst3, Dst4, Dst5, Dst6]),
149+
?assertEqual(Dsts2, lists:usort(rabbit_db_topic_exchange:match(Src, <<"a.b">>))),
150+
Dsts3 = lists:sort([Dst4, Dst5]),
151+
?assertEqual(Dsts3, lists:usort(rabbit_db_topic_exchange:match(Src, <<"">>))),
152+
Dsts4 = lists:sort([Dst3, Dst4, Dst5]),
153+
?assertEqual(Dsts4, lists:usort(rabbit_db_topic_exchange:match(Src, <<"zen.rabbit">>))),
154+
passed.
155+
156+
set(Src, RoutingKey, Dst) ->
157+
Binding = #binding{source = Src, key = RoutingKey, destination = Dst, args = #{}},
158+
ok = rabbit_db_topic_exchange:set(Binding).

0 commit comments

Comments
 (0)