Skip to content

Commit c82efd8

Browse files
Merge pull request #14372 from rabbitmq/mergify/bp/v4.1.x/pr-14206
Collection of test fixes (2025Q2, batch 1) (backport #14206)
2 parents 7c2fa96 + 34dac81 commit c82efd8

37 files changed

+672
-361
lines changed

.github/workflows/test-make-target.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,6 @@ jobs:
119119
name: CT logs (${{ inputs.plugin }} ${{ inputs.make_target }} OTP-${{ inputs.erlang_version }} ${{ inputs.metadata_store }}${{ inputs.mixed_clusters && ' mixed' || '' }})
120120
path: |
121121
logs/
122+
deps/rabbitmq_cli/logs/
122123
# !logs/**/log_private
123124
if-no-files-found: ignore

deps/rabbit/src/rabbit_vhosts.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ start_processes_for_all(Nodes) ->
124124

125125
-spec start_processes_for_all() -> 'ok'.
126126
start_processes_for_all() ->
127-
start_processes_for_all(rabbit_nodes:list_reachable()).
127+
start_processes_for_all(rabbit_nodes:list_running()).
128128

129129
%% Same as rabbit_vhost_sup_sup:start_on_all_nodes/0.
130130
-spec start_on_all_nodes(vhost:name(), [node()]) -> 'ok'.

deps/rabbit/test/amqp_client_SUITE.erl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,11 @@ link_target_queue_deleted(QType, Config) ->
17731773
ok = amqp10_client:send_msg(Sender, amqp10_msg:new(DTag1, <<"m1">>, false)),
17741774
ok = wait_for_accepted(DTag1),
17751775

1776+
%% Load test module on the broker: we reference an anonymous function
1777+
%% from it during the configuration of meck.
1778+
[_ | _] = rabbit_ct_broker_helpers:rpc(
1779+
Config, ?MODULE, module_info, []),
1780+
17761781
%% Mock delivery to the target queue to do nothing.
17771782
rabbit_ct_broker_helpers:setup_meck(Config, [?MODULE]),
17781783
Mod = rabbit_queue_type,
@@ -1833,6 +1838,11 @@ target_queues_deleted_accepted(Config) ->
18331838
ok = amqp10_client:send_msg(Sender, amqp10_msg:new(DTag1, <<"m1">>, false)),
18341839
ok = wait_for_accepted(DTag1),
18351840

1841+
%% Load test module on the broker: we reference an anonymous function
1842+
%% from it during the configuration of meck.
1843+
[_ | _] = rabbit_ct_broker_helpers:rpc(
1844+
Config, ?MODULE, module_info, []),
1845+
18361846
%% Mock to deliver only to q1.
18371847
rabbit_ct_broker_helpers:setup_meck(Config, [?MODULE]),
18381848
Mod = rabbit_queue_type,
@@ -3979,7 +3989,7 @@ list_connections(Config) ->
39793989
end,
39803990

39813991
{ok, StdOut0} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["list_connections", "--silent", "protocol"]),
3982-
Protocols0 = re:split(StdOut0, <<"\n">>, [trim]),
3992+
Protocols0 = re:split(string:trim(StdOut0), <<"\n">>, [trim]),
39833993
%% Remove any whitespaces.
39843994
Protocols1 = [binary:replace(Subject, <<" ">>, <<>>, [global]) || Subject <- Protocols0],
39853995
Protocols = lists:sort(Protocols1),
@@ -3993,7 +4003,7 @@ list_connections(Config) ->
39934003

39944004
%% CLI should list AMQP 1.0 container-id
39954005
{ok, StdOut1} = rabbit_ct_broker_helpers:rabbitmqctl(Config, 0, ["list_connections", "--silent", "container_id"]),
3996-
ContainerIds0 = re:split(StdOut1, <<"\n">>, [trim]),
4006+
ContainerIds0 = re:split(string:trim(StdOut1), <<"\n">>, [trim]),
39974007
ContainerIds = lists:sort(ContainerIds0),
39984008
?assertEqual([<<>>, ContainerId0, ContainerId2],
39994009
ContainerIds),
@@ -4630,6 +4640,11 @@ idle_time_out_on_server(Config) ->
46304640
after 30000 -> ct:fail({missing_event, ?LINE})
46314641
end,
46324642

4643+
%% Load test module on the broker: we reference an anonymous function
4644+
%% from it during the configuration of meck.
4645+
[_ | _] = rabbit_ct_broker_helpers:rpc(
4646+
Config, ?MODULE, module_info, []),
4647+
46334648
%% Mock the server socket to not have received any bytes.
46344649
rabbit_ct_broker_helpers:setup_meck(Config),
46354650
ok = rpc(Config, meck, new, [Mod, [no_link, passthrough]]),
@@ -4653,7 +4668,7 @@ idle_time_out_on_server(Config) ->
46534668
ct:fail({missing_event, ?LINE})
46544669
end
46554670
after
4656-
?assert(rpc(Config, meck, validate, [Mod])),
4671+
_ = rpc(Config, meck, validate, [Mod]),
46574672
ok = rpc(Config, meck, unload, [Mod]),
46584673
ok = rpc(Config, application, set_env, [App, Par, DefaultVal])
46594674
end.

deps/rabbit/test/amqp_jms_SUITE.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ groups() ->
5252

5353
suite() ->
5454
[
55-
{timetrap, {minutes, 2}}
55+
{timetrap, {minutes, 5}}
5656
].
5757

5858
init_per_suite(Config) ->

deps/rabbit/test/backing_queue_SUITE.erl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,18 +1445,18 @@ variable_queue_restart_large_seq_id2(VQ0, QName) ->
14451445
Terms = variable_queue_read_terms(QName),
14461446
Count = proplists:get_value(next_seq_id, Terms),
14471447

1448-
%% set a very high next_seq_id as if 100M messages have been
1448+
%% set a very high next_seq_id as if 100 billion messages have been
14491449
%% published and consumed
1450-
Terms2 = lists:keyreplace(next_seq_id, 1, Terms, {next_seq_id, 100_000_000}),
1450+
Terms2 = lists:keyreplace(next_seq_id, 1, Terms, {next_seq_id, 100_000_000_000}),
14511451

14521452
{TInit, VQ3} =
14531453
timer:tc(
14541454
fun() -> variable_queue_init(test_amqqueue(QName, true), Terms2) end,
14551455
millisecond),
14561456
%% even with a very high next_seq_id start of an empty queue
1457-
%% should be quick (few milliseconds, but let's give it 100ms, to
1457+
%% should be quick (few milliseconds, but let's give it 500ms, to
14581458
%% avoid flaking on slow servers)
1459-
{true, _} = {TInit < 100, TInit},
1459+
{true, _} = {TInit < 500, TInit},
14601460

14611461
%% should be empty now
14621462
true = rabbit_variable_queue:is_empty(VQ3),

deps/rabbit/test/cluster_minority_SUITE.erl

Lines changed: 167 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99

1010
-include_lib("amqp_client/include/amqp_client.hrl").
1111
-include_lib("eunit/include/eunit.hrl").
12+
-include_lib("rabbitmq_ct_helpers/include/rabbit_assert.hrl").
1213

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

1516
all() ->
1617
[
1718
{group, client_operations},
18-
{group, cluster_operation_add},
19-
{group, cluster_operation_remove}
19+
{group, cluster_operation}
2020
].
2121

2222
groups() ->
@@ -42,8 +42,10 @@ groups() ->
4242
delete_policy,
4343
export_definitions
4444
]},
45-
{cluster_operation_add, [], [add_node]},
46-
{cluster_operation_remove, [], [remove_node]},
45+
{cluster_operation, [], [add_node_when_seed_node_is_leader,
46+
add_node_when_seed_node_is_follower,
47+
remove_node_when_seed_node_is_leader,
48+
remove_node_when_seed_node_is_follower]},
4749
{feature_flags, [], [enable_feature_flag]}
4850
].
4951

@@ -127,26 +129,49 @@ init_per_group(Group, Config0) when Group == client_operations;
127129
partition_5_node_cluster(Config1),
128130
Config1
129131
end;
130-
init_per_group(Group, Config0) ->
132+
init_per_group(_Group, Config0) ->
131133
Config = rabbit_ct_helpers:set_config(Config0, [{rmq_nodes_count, 5},
132-
{rmq_nodename_suffix, Group},
133134
{rmq_nodes_clustered, false},
134135
{tcp_ports_base},
135136
{net_ticktime, 5}]),
136137
Config1 = rabbit_ct_helpers:merge_app_env(
137-
Config, {rabbit, [{forced_feature_flags_on_init, []}]}),
138-
rabbit_ct_helpers:run_steps(Config1,
139-
rabbit_ct_broker_helpers:setup_steps() ++
140-
rabbit_ct_client_helpers:setup_steps()).
138+
Config, {rabbit, [{forced_feature_flags_on_init, []},
139+
{khepri_leader_wait_retry_timeout, 30000}]}),
140+
Config1.
141141

142-
end_per_group(_, Config) ->
142+
end_per_group(Group, Config) when Group == client_operations;
143+
Group == feature_flags ->
143144
rabbit_ct_helpers:run_steps(Config,
144145
rabbit_ct_client_helpers:teardown_steps() ++
145-
rabbit_ct_broker_helpers:teardown_steps()).
146-
146+
rabbit_ct_broker_helpers:teardown_steps());
147+
end_per_group(_Group, Config) ->
148+
Config.
149+
150+
init_per_testcase(Testcase, Config)
151+
when Testcase =:= add_node_when_seed_node_is_leader orelse
152+
Testcase =:= add_node_when_seed_node_is_follower orelse
153+
Testcase =:= remove_node_when_seed_node_is_leader orelse
154+
Testcase =:= remove_node_when_seed_node_is_follower ->
155+
rabbit_ct_helpers:testcase_started(Config, Testcase),
156+
Config1 = rabbit_ct_helpers:set_config(
157+
Config, [{rmq_nodename_suffix, Testcase}]),
158+
rabbit_ct_helpers:run_steps(
159+
Config1,
160+
rabbit_ct_broker_helpers:setup_steps() ++
161+
rabbit_ct_client_helpers:setup_steps());
147162
init_per_testcase(Testcase, Config) ->
148163
rabbit_ct_helpers:testcase_started(Config, Testcase).
149164

165+
end_per_testcase(Testcase, Config)
166+
when Testcase =:= add_node_when_seed_node_is_leader orelse
167+
Testcase =:= add_node_when_seed_node_is_follower orelse
168+
Testcase =:= remove_node_when_seed_node_is_leader orelse
169+
Testcase =:= remove_node_when_seed_node_is_follower ->
170+
rabbit_ct_helpers:run_steps(
171+
Config,
172+
rabbit_ct_client_helpers:teardown_steps() ++
173+
rabbit_ct_broker_helpers:teardown_steps()),
174+
rabbit_ct_helpers:testcase_finished(Config, Testcase);
150175
end_per_testcase(Testcase, Config) ->
151176
rabbit_ct_helpers:testcase_finished(Config, Testcase).
152177

@@ -271,53 +296,151 @@ set_policy(Config) ->
271296
delete_policy(Config) ->
272297
?assertError(_, rabbit_ct_broker_helpers:clear_policy(Config, 0, <<"policy-to-delete">>)).
273298

274-
add_node(Config) ->
275-
[A, B, C, D, _E] = rabbit_ct_broker_helpers:get_node_configs(
299+
add_node_when_seed_node_is_leader(Config) ->
300+
[A, B, C, _D, E] = rabbit_ct_broker_helpers:get_node_configs(
276301
Config, nodename),
277302

278303
%% Three node cluster: A, B, C
279-
ok = rabbit_control_helper:command(stop_app, B),
280-
ok = rabbit_control_helper:command(join_cluster, B, [atom_to_list(A)], []),
281-
rabbit_control_helper:command(start_app, B),
304+
Cluster = [A, B, C],
305+
Config1 = rabbit_ct_broker_helpers:cluster_nodes(Config, Cluster),
282306

283-
ok = rabbit_control_helper:command(stop_app, C),
284-
ok = rabbit_control_helper:command(join_cluster, C, [atom_to_list(A)], []),
285-
rabbit_control_helper:command(start_app, C),
307+
AMember = {rabbit_khepri:get_store_id(), A},
308+
_ = ra:transfer_leadership(AMember, AMember),
309+
clustering_utils:assert_cluster_status({Cluster, Cluster}, Cluster),
286310

287311
%% Minority partition: A
312+
partition_3_node_cluster(Config1),
313+
314+
Pong = ra:ping(AMember, 10000),
315+
ct:pal("Member A state: ~0p", [Pong]),
316+
case Pong of
317+
{pong, State} when State =/= follower andalso State =/= candidate ->
318+
Ret = rabbit_control_helper:command(
319+
join_cluster, E, [atom_to_list(A)], []),
320+
?assertMatch({error, _, _}, Ret),
321+
{error, _, Msg} = Ret,
322+
?assertEqual(
323+
match,
324+
re:run(
325+
Msg, "(Khepri cluster could be in minority|\\{:rabbit, \\{\\{:error, :timeout\\})",
326+
[{capture, none}]));
327+
Ret ->
328+
ct:pal("A is not the expected leader: ~p", [Ret]),
329+
{skip, "Node A was not elected leader"}
330+
end.
331+
332+
add_node_when_seed_node_is_follower(Config) ->
333+
[A, B, C, _D, E] = rabbit_ct_broker_helpers:get_node_configs(
334+
Config, nodename),
335+
336+
%% Three node cluster: A, B, C
288337
Cluster = [A, B, C],
289-
partition_3_node_cluster(Config),
290-
291-
ok = rabbit_control_helper:command(stop_app, D),
292-
%% The command is appended to the log, but it will be dropped once the connectivity
293-
%% is restored
294-
?assertMatch(ok,
295-
rabbit_control_helper:command(join_cluster, D, [atom_to_list(A)], [])),
296-
timer:sleep(10000),
297-
join_3_node_cluster(Config),
298-
clustering_utils:assert_cluster_status({Cluster, Cluster}, Cluster).
299-
300-
remove_node(Config) ->
338+
Config1 = rabbit_ct_broker_helpers:cluster_nodes(Config, Cluster),
339+
340+
CMember = {rabbit_khepri:get_store_id(), C},
341+
ra:transfer_leadership(CMember, CMember),
342+
clustering_utils:assert_cluster_status({Cluster, Cluster}, Cluster),
343+
344+
%% Minority partition: A
345+
partition_3_node_cluster(Config1),
346+
347+
AMember = {rabbit_khepri:get_store_id(), A},
348+
Pong = ra:ping(AMember, 10000),
349+
ct:pal("Member A state: ~0p", [Pong]),
350+
case Pong of
351+
{pong, State}
352+
when State =:= follower orelse State =:= pre_vote ->
353+
Ret = rabbit_control_helper:command(
354+
join_cluster, E, [atom_to_list(A)], []),
355+
?assertMatch({error, _, _}, Ret),
356+
{error, _, Msg} = Ret,
357+
?assertEqual(
358+
match,
359+
re:run(
360+
Msg, "Khepri cluster could be in minority",
361+
[{capture, none}]));
362+
{pong, await_condition} ->
363+
Ret = rabbit_control_helper:command(
364+
join_cluster, E, [atom_to_list(A)], []),
365+
?assertMatch({error, _, _}, Ret),
366+
{error, _, Msg} = Ret,
367+
?assertEqual(
368+
match,
369+
re:run(
370+
Msg, "\\{:rabbit, \\{\\{:error, :timeout\\}",
371+
[{capture, none}])),
372+
clustering_utils:assert_cluster_status(
373+
{Cluster, Cluster}, Cluster);
374+
Ret ->
375+
ct:pal("A is not the expected follower: ~p", [Ret]),
376+
{skip, "Node A was not a follower"}
377+
end.
378+
379+
remove_node_when_seed_node_is_leader(Config) ->
301380
[A, B, C | _] = rabbit_ct_broker_helpers:get_node_configs(
302381
Config, nodename),
303382

304383
%% Three node cluster: A, B, C
305-
ok = rabbit_control_helper:command(stop_app, B),
306-
ok = rabbit_control_helper:command(join_cluster, B, [atom_to_list(A)], []),
307-
rabbit_control_helper:command(start_app, B),
384+
Cluster = [A, B, C],
385+
Config1 = rabbit_ct_broker_helpers:cluster_nodes(Config, Cluster),
308386

309-
ok = rabbit_control_helper:command(stop_app, C),
310-
ok = rabbit_control_helper:command(join_cluster, C, [atom_to_list(A)], []),
311-
rabbit_control_helper:command(start_app, C),
387+
AMember = {rabbit_khepri:get_store_id(), A},
388+
ra:transfer_leadership(AMember, AMember),
389+
clustering_utils:assert_cluster_status({Cluster, Cluster}, Cluster),
390+
ct:pal("Waiting for cluster change permitted on node A"),
391+
?awaitMatch(
392+
{ok, #{cluster_change_permitted := true,
393+
leader_id := AMember}, AMember},
394+
rabbit_ct_broker_helpers:rpc(
395+
Config1, A, ra, member_overview, [AMember]),
396+
60000),
397+
{ok, Overview, AMember} = rabbit_ct_broker_helpers:rpc(
398+
Config1, A, ra, member_overview, [AMember]),
399+
ct:pal("Member A overview: ~p", [maps:remove(machine, Overview)]),
312400

313401
%% Minority partition: A
314-
partition_3_node_cluster(Config),
402+
partition_3_node_cluster(Config1),
403+
404+
?assertEqual({pong, leader}, ra:ping(AMember, 10000)),
405+
?awaitMatch(
406+
ok,
407+
rabbit_control_helper:command(
408+
forget_cluster_node, A, [atom_to_list(B)], []),
409+
60000).
410+
411+
remove_node_when_seed_node_is_follower(Config) ->
412+
[A, B, C | _] = rabbit_ct_broker_helpers:get_node_configs(
413+
Config, nodename),
414+
415+
%% Three node cluster: A, B, C
315416
Cluster = [A, B, C],
417+
Config1 = rabbit_ct_broker_helpers:cluster_nodes(Config, Cluster),
316418

317-
ok = rabbit_control_helper:command(forget_cluster_node, A, [atom_to_list(B)], []),
318-
timer:sleep(10000),
319-
join_3_node_cluster(Config),
320-
clustering_utils:assert_cluster_status({Cluster, Cluster}, Cluster).
419+
AMember = {rabbit_khepri:get_store_id(), A},
420+
CMember = {rabbit_khepri:get_store_id(), C},
421+
ra:transfer_leadership(CMember, CMember),
422+
clustering_utils:assert_cluster_status({Cluster, Cluster}, Cluster),
423+
?awaitMatch(
424+
{ok, #{cluster_change_permitted := true,
425+
leader_id := CMember}, AMember},
426+
rabbit_ct_broker_helpers:rpc(
427+
Config1, A, ra, member_overview, [AMember]),
428+
60000),
429+
{ok, Overview, AMember} = rabbit_ct_broker_helpers:rpc(
430+
Config1, A, ra, member_overview, [AMember]),
431+
ct:pal("Member A overview: ~p", [maps:remove(machine, Overview)]),
432+
433+
%% Minority partition: A
434+
partition_3_node_cluster(Config1),
435+
436+
Ret = rabbit_control_helper:command(
437+
forget_cluster_node, A, [atom_to_list(B)], []),
438+
?assertMatch({error, _, _}, Ret),
439+
{error, _, Msg} = Ret,
440+
?assertEqual(
441+
match,
442+
re:run(
443+
Msg, "Khepri cluster could be in minority", [{capture, none}])).
321444

322445
enable_feature_flag(Config) ->
323446
[A | _] = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),

deps/rabbit/test/clustering_management_SUITE.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,13 +745,13 @@ is_in_minority(Ret) ->
745745
?assertMatch(match, re:run(Msg, ".*timed out.*minority.*", [{capture, none}])).
746746

747747
reset_last_disc_node(Config) ->
748-
Servers = [Rabbit, Hare | _] = cluster_members(Config),
748+
[Rabbit, Hare | _] = cluster_members(Config),
749749

750750
stop_app(Config, Hare),
751751
?assertEqual(ok, change_cluster_node_type(Config, Hare, ram)),
752752
start_app(Config, Hare),
753753

754-
case rabbit_ct_broker_helpers:enable_feature_flag(Config, Servers, khepri_db) of
754+
case rabbit_ct_broker_helpers:enable_feature_flag(Config, [Rabbit], khepri_db) of
755755
ok ->
756756
%% The reset works after the switch to Khepri because the RAM node was
757757
%% implicitly converted to a disc one as Khepri always writes data on disc.

0 commit comments

Comments
 (0)