Skip to content

Commit a5ef59f

Browse files
committed
add core tests for handling multiple channel interceptors
1 parent 9885109 commit a5ef59f

5 files changed

Lines changed: 201 additions & 1 deletion

deps/rabbit/test/channel_interceptor_SUITE.erl

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ groups() ->
2424
register_interceptor,
2525
register_interceptor_failing_with_amqp_error,
2626
register_interceptor_crashing_with_amqp_error_exception,
27-
register_failing_interceptors
27+
register_failing_interceptors,
28+
multiple_interceptors_ordered_by_priority,
29+
reject_interceptors_with_same_priority_for_same_operation,
30+
priority_overridden_by_config
2831
]}
2932
].
3033

@@ -213,6 +216,98 @@ register_failing_interceptors(Config) ->
213216
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
214217
?MODULE, register_interceptor1, [Config, failing_dummy_interceptor]).
215218

219+
multiple_interceptors_ordered_by_priority(Config) ->
220+
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
221+
?MODULE, multiple_interceptors_ordered_by_priority1, [Config]).
222+
223+
multiple_interceptors_ordered_by_priority1(Config) ->
224+
Ch = rabbit_ct_client_helpers:open_channel(Config, 0),
225+
QName = <<"multiple-interceptors-q">>,
226+
#'queue.declare_ok'{} = amqp_channel:call(Ch, #'queue.declare'{queue = QName,
227+
durable = true}),
228+
229+
ok = application:set_env(rabbit, channel_interceptor_priorities,
230+
[{dummy_interceptor_priority_1, 1},
231+
{dummy_interceptor_priority_2, 2},
232+
{dummy_interceptor_priority_3, 3}]),
233+
234+
ok = rabbit_registry:register(channel_interceptor,
235+
<<"dummy interceptor priority 3">>, dummy_interceptor_priority_3),
236+
ok = rabbit_registry:register(channel_interceptor,
237+
<<"dummy interceptor priority 2">>, dummy_interceptor_priority_2),
238+
ok = rabbit_registry:register(channel_interceptor,
239+
<<"dummy interceptor priority 1">>, dummy_interceptor_priority_1),
240+
241+
%% Interceptors run in ascending priority order regardless of registration order,
242+
%% so the payload becomes <<"foo1">>, then <<"foo12">>, then <<"foo123">>.
243+
check_send_receive(Ch, QName, <<"foo">>, <<"foo123">>),
244+
245+
ok = rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 1">>),
246+
ok = rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 2">>),
247+
ok = rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 3">>),
248+
ok = application:unset_env(rabbit, channel_interceptor_priorities),
249+
250+
#'queue.delete_ok'{} = amqp_channel:call(Ch, #'queue.delete'{queue = QName}),
251+
passed.
252+
253+
reject_interceptors_with_same_priority_for_same_operation(Config) ->
254+
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
255+
?MODULE, reject_interceptors_with_same_priority_for_same_operation1, [Config]).
256+
257+
reject_interceptors_with_same_priority_for_same_operation1(_Config) ->
258+
ok = rabbit_registry:register(channel_interceptor,
259+
<<"dummy interceptor priority 1">>,
260+
dummy_interceptor_priority_1),
261+
ok = rabbit_registry:register(channel_interceptor,
262+
<<"dummy interceptor priority 1 conflict">>,
263+
dummy_interceptor_priority_1_conflict),
264+
try
265+
%% Initialising interceptors must fail: two interceptors with the same
266+
%% priority handle the same AMQP operation.
267+
rabbit_channel_interceptor:init(self())
268+
catch
269+
exit:{amqp_error, internal_error, _, _} -> ok
270+
after
271+
rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 1">>),
272+
rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 1 conflict">>)
273+
end,
274+
passed.
275+
276+
priority_overridden_by_config(Config) ->
277+
passed = rabbit_ct_broker_helpers:rpc(Config, 0,
278+
?MODULE, priority_overridden_by_config1, [Config]).
279+
280+
priority_overridden_by_config1(Config) ->
281+
Ch = rabbit_ct_client_helpers:open_channel(Config, 0),
282+
QName = <<"priority-override-q">>,
283+
#'queue.declare_ok'{} = amqp_channel:call(Ch, #'queue.declare'{queue = QName,
284+
durable = true}),
285+
286+
%% priority_1 (config priority=1) runs before priority_3 (config priority=3),
287+
%% so the result is <<"foo13">>.
288+
ok = application:set_env(rabbit, channel_interceptor_priorities,
289+
[{dummy_interceptor_priority_1, 1},
290+
{dummy_interceptor_priority_3, 3}]),
291+
ok = rabbit_registry:register(channel_interceptor,
292+
<<"dummy interceptor priority 1">>, dummy_interceptor_priority_1),
293+
ok = rabbit_registry:register(channel_interceptor,
294+
<<"dummy interceptor priority 3">>, dummy_interceptor_priority_3),
295+
check_send_receive(Ch, QName, <<"foo">>, <<"foo13">>),
296+
297+
%% Reconfigure priority_3 to run first (priority=0). Now the result is <<"foo31">>.
298+
ok = application:set_env(rabbit, channel_interceptor_priorities,
299+
[{dummy_interceptor_priority_1, 1},
300+
{dummy_interceptor_priority_3, 0}]),
301+
rabbit_channel:refresh_interceptors(),
302+
check_send_receive(Ch, QName, <<"foo">>, <<"foo31">>),
303+
304+
ok = application:unset_env(rabbit, channel_interceptor_priorities),
305+
ok = rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 1">>),
306+
ok = rabbit_registry:unregister(channel_interceptor, <<"dummy interceptor priority 3">>),
307+
308+
#'queue.delete_ok'{} = amqp_channel:call(Ch, #'queue.delete'{queue = QName}),
309+
passed.
310+
216311
check_send_receive(Ch1, QName, Send, Receive) ->
217312
amqp_channel:call(Ch1,
218313
#'basic.publish'{routing_key = QName},
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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-2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(dummy_interceptor_priority_1).
9+
10+
-behaviour(rabbit_channel_interceptor).
11+
12+
-include_lib("rabbit_common/include/rabbit.hrl").
13+
-include_lib("rabbit_common/include/rabbit_framing.hrl").
14+
15+
-compile(export_all).
16+
17+
init(_Ch) -> undefined.
18+
19+
description() -> [{description, <<"Appends '1' to basic.publish payload">>}].
20+
21+
intercept(#'basic.publish'{} = Method, Content, _State) ->
22+
Payload = iolist_to_binary(lists:reverse(Content#content.payload_fragments_rev)),
23+
{Method, Content#content{payload_fragments_rev = [<<Payload/binary, "1">>]}};
24+
intercept(Method, Content, _State) ->
25+
{Method, Content}.
26+
27+
applies_to() -> ['basic.publish'].
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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-2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(dummy_interceptor_priority_1_conflict).
9+
10+
-behaviour(rabbit_channel_interceptor).
11+
12+
-include_lib("rabbit_common/include/rabbit.hrl").
13+
-include_lib("rabbit_common/include/rabbit_framing.hrl").
14+
15+
-compile(export_all).
16+
17+
init(_Ch) -> undefined.
18+
19+
description() -> [{description, <<"Conflicts with dummy_interceptor_priority_1">>}].
20+
21+
intercept(Method, Content, _State) ->
22+
{Method, Content}.
23+
24+
applies_to() -> ['basic.publish'].
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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-2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(dummy_interceptor_priority_2).
9+
10+
-behaviour(rabbit_channel_interceptor).
11+
12+
-include_lib("rabbit_common/include/rabbit.hrl").
13+
-include_lib("rabbit_common/include/rabbit_framing.hrl").
14+
15+
-compile(export_all).
16+
17+
init(_Ch) -> undefined.
18+
19+
description() -> [{description, <<"Appends '2' to basic.publish payload">>}].
20+
21+
intercept(#'basic.publish'{} = Method, Content, _State) ->
22+
Payload = iolist_to_binary(lists:reverse(Content#content.payload_fragments_rev)),
23+
{Method, Content#content{payload_fragments_rev = [<<Payload/binary, "2">>]}};
24+
intercept(Method, Content, _State) ->
25+
{Method, Content}.
26+
27+
applies_to() -> ['basic.publish'].
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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-2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
6+
%%
7+
8+
-module(dummy_interceptor_priority_3).
9+
10+
-behaviour(rabbit_channel_interceptor).
11+
12+
-include_lib("rabbit_common/include/rabbit.hrl").
13+
-include_lib("rabbit_common/include/rabbit_framing.hrl").
14+
15+
-compile(export_all).
16+
17+
init(_Ch) -> undefined.
18+
19+
description() -> [{description, <<"Appends '3' to basic.publish payload">>}].
20+
21+
intercept(#'basic.publish'{} = Method, Content, _State) ->
22+
Payload = iolist_to_binary(lists:reverse(Content#content.payload_fragments_rev)),
23+
{Method, Content#content{payload_fragments_rev = [<<Payload/binary, "3">>]}};
24+
intercept(Method, Content, _State) ->
25+
{Method, Content}.
26+
27+
applies_to() -> ['basic.publish'].

0 commit comments

Comments
 (0)