@@ -88,14 +88,17 @@ groups() ->
88
88
[
89
89
last_queue_confirms ,
90
90
target_queue_deleted ,
91
- credit_reply_quorum_queue ,
92
91
async_notify_settled_classic_queue ,
93
92
async_notify_settled_quorum_queue ,
94
93
async_notify_settled_stream ,
95
94
async_notify_unsettled_classic_queue ,
96
95
async_notify_unsettled_quorum_queue ,
97
96
async_notify_unsettled_stream ,
98
- link_flow_control
97
+ link_flow_control ,
98
+ classic_queue_on_old_node ,
99
+ classic_queue_on_new_node ,
100
+ quorum_queue_on_old_node ,
101
+ quorum_queue_on_new_node
99
102
]},
100
103
101
104
{metrics , [shuffle ],
@@ -135,15 +138,17 @@ end_per_group(_, Config) ->
135
138
rabbit_ct_client_helpers :teardown_steps () ++
136
139
rabbit_ct_broker_helpers :teardown_steps ()).
137
140
138
- init_per_testcase (T = message_headers_conversion , Config ) ->
141
+ init_per_testcase (T , Config )
142
+ when T =:= message_headers_conversion orelse
143
+ T =:= roundtrip_with_drain_quorum_queue orelse
144
+ T =:= timed_get_quorum_queue ->
139
145
case rabbit_ct_broker_helpers :rpc (
140
146
Config , rabbit_feature_flags , is_enabled , [credit_api_v2 ]) of
141
147
true ->
142
148
rabbit_ct_helpers :testcase_started (Config , T );
143
149
false ->
144
- {skip , " Quorum queues are known to behave incorrectly with feature flag "
145
- " credit_api_v2 disabled because they send a send_drained queue event "
146
- " before sending all available messages." }
150
+ {skip , " Receiving with drain from quorum queues in credit API v1 have a known "
151
+ " bug that they reply with send_drained before delivering the message." }
147
152
end ;
148
153
init_per_testcase (Testcase , Config ) ->
149
154
rabbit_ct_helpers :testcase_started (Config , Testcase ).
@@ -563,9 +568,6 @@ roundtrip_with_drain(Config, QueueType, QName)
563
568
Session , <<" test-sender" >>, Address ),
564
569
wait_for_credit (Sender ),
565
570
566
- % Create a new message using a delivery-tag, body and indicate
567
- % its settlement status (true meaning no disposition confirmation
568
- % will be sent by the receiver).
569
571
OutMsg = amqp10_msg :new (<<" my-tag" >>, <<" my-body" >>, false ),
570
572
ok = amqp10_client :send_msg (Sender , OutMsg ),
571
573
ok = wait_for_accepts (1 ),
@@ -2151,61 +2153,9 @@ target_queue_deleted(Config) ->
2151
2153
amqp_channel :call (Ch , # 'queue.delete' {queue = QuorumQ })),
2152
2154
ok = rabbit_ct_client_helpers :close_channel (Ch ).
2153
2155
2154
- % % This test is mostly interesting in mixed version mode with feature flag
2155
- % % consumer_tag_in_credit_reply disabled.
2156
- credit_reply_quorum_queue (Config ) ->
2157
- % % Place quorum queue leader on the old version node.
2158
- OldVersionNode = 1 ,
2159
- Ch = rabbit_ct_client_helpers :open_channel (Config , OldVersionNode ),
2160
- QName = atom_to_binary (? FUNCTION_NAME ),
2161
- # 'queue.declare_ok' {} = amqp_channel :call (
2162
- Ch , # 'queue.declare' {
2163
- queue = QName ,
2164
- durable = true ,
2165
- arguments = [{<<" x-queue-type" >>, longstr , <<" quorum" >>},
2166
- {<<" x-queue-leader-locator" >>, longstr , <<" client-local" >>}]}),
2167
- % % Connect to the new node.
2168
- OpnConf = connection_config (Config ),
2169
- {ok , Connection } = amqp10_client :open_connection (OpnConf ),
2170
- {ok , Session } = amqp10_client :begin_session_sync (Connection ),
2171
- Address = <<" /amq/queue/" , QName /binary >>,
2172
- {ok , Sender } = amqp10_client :attach_sender_link (
2173
- Session , <<" test-sender" >>, Address ),
2174
- ok = wait_for_credit (Sender ),
2175
- {ok , Receiver } = amqp10_client :attach_receiver_link (
2176
- Session ,
2177
- <<" test-receiver" >>,
2178
- Address ,
2179
- unsettled ),
2180
- receive {amqp10_event , {link , Receiver , attached }} -> ok
2181
- after 5000 -> ct :fail (" missing attached" )
2182
- end ,
2183
- flush (receiver_attached ),
2184
-
2185
- NumMsgs = 10 ,
2186
- [begin
2187
- Bin = integer_to_binary (N ),
2188
- ok = amqp10_client :send_msg (Sender , amqp10_msg :new (Bin , Bin , true ))
2189
- end || N <- lists :seq (1 , NumMsgs )],
2190
-
2191
- % % Grant credits to the sending queue.
2192
- ok = amqp10_client :flow_link_credit (Receiver , NumMsgs , never ),
2193
-
2194
- % % We should receive all messages.
2195
- Msgs = receive_messages (Receiver , NumMsgs ),
2196
- FirstMsg = hd (Msgs ),
2197
- LastMsg = lists :last (Msgs ),
2198
- ? assertEqual ([<<" 1" >>], amqp10_msg :body (FirstMsg )),
2199
- ? assertEqual ([integer_to_binary (NumMsgs )], amqp10_msg :body (LastMsg )),
2200
-
2201
- ExpectedReadyMsgs = 0 ,
2202
- ? assertEqual (# 'queue.delete_ok' {message_count = ExpectedReadyMsgs },
2203
- amqp_channel :call (Ch , # 'queue.delete' {queue = QName })),
2204
- ok = rabbit_ct_client_helpers :close_channel (Ch ),
2205
- ok = amqp10_client :close_connection (Connection ).
2206
-
2207
2156
async_notify_settled_classic_queue (Config ) ->
2208
- % % TODO require ff message_containers
2157
+ % % TODO Bump old version in mixed version tests to 3.13.x,
2158
+ % % require ff message_containers and always run this test case.
2209
2159
case rabbit_ct_broker_helpers :enable_feature_flag (Config , message_containers ) of
2210
2160
ok -> async_notify (settled , <<" classic" >>, Config );
2211
2161
{skip , _ } = Skip -> Skip
@@ -2218,7 +2168,8 @@ async_notify_settled_stream(Config) ->
2218
2168
async_notify (settled , <<" stream" >>, Config ).
2219
2169
2220
2170
async_notify_unsettled_classic_queue (Config ) ->
2221
- % % TODO require ff message_containers
2171
+ % % TODO Bump old version in mixed version tests to 3.13.x,
2172
+ % % require ff message_containers and always run this test case.
2222
2173
case rabbit_ct_broker_helpers :enable_feature_flag (Config , message_containers ) of
2223
2174
ok -> async_notify (unsettled , <<" classic" >>, Config );
2224
2175
{skip , _ } = Skip -> Skip
@@ -2232,14 +2183,15 @@ async_notify_unsettled_stream(Config) ->
2232
2183
2233
2184
% % Test asynchronous notification, figure 2.45.
2234
2185
async_notify (SenderSettleMode , QType , Config ) ->
2186
+ % % Place queue leader on the old node.
2235
2187
Ch = rabbit_ct_client_helpers :open_channel (Config , 1 ),
2236
2188
QName = atom_to_binary (? FUNCTION_NAME ),
2237
2189
# 'queue.declare_ok' {} = amqp_channel :call (
2238
2190
Ch , # 'queue.declare' {
2239
2191
queue = QName ,
2240
2192
durable = true ,
2241
2193
arguments = [{<<" x-queue-type" >>, longstr , QType }]}),
2242
-
2194
+ % % Connect AMQP client to the new node causing queue client to run the new code.
2243
2195
OpnConf = connection_config (Config ),
2244
2196
{ok , Connection } = amqp10_client :open_connection (OpnConf ),
2245
2197
{ok , Session } = amqp10_client :begin_session_sync (Connection ),
@@ -2385,12 +2337,108 @@ link_flow_control(Config) ->
2385
2337
delete_queue (Config , QQ ),
2386
2338
delete_queue (Config , CQ ).
2387
2339
2340
+ classic_queue_on_old_node (Config ) ->
2341
+ % % TODO Bump old version in mixed version tests to 3.13.x,
2342
+ % % require ff message_containers and always run this test case.
2343
+ case rabbit_ct_broker_helpers :enable_feature_flag (Config , message_containers ) of
2344
+ ok -> queue_and_client_different_nodes (1 , 0 , <<" classic" >>, Config );
2345
+ {skip , _ } = Skip -> Skip
2346
+ end .
2347
+
2348
+ classic_queue_on_new_node (Config ) ->
2349
+ queue_and_client_different_nodes (0 , 1 , <<" classic" >>, Config ).
2350
+
2351
+ quorum_queue_on_old_node (Config ) ->
2352
+ queue_and_client_different_nodes (1 , 0 , <<" quorum" >>, Config ).
2353
+
2354
+ quorum_queue_on_new_node (Config ) ->
2355
+ queue_and_client_different_nodes (0 , 1 , <<" quorum" >>, Config ).
2356
+
2357
+ % % In mixed version tests, run the queue leader with old code
2358
+ % % and queue client with new code, or vice versa.
2359
+ queue_and_client_different_nodes (QueueLeaderNode , ClientNode , QueueType , Config ) ->
2360
+ Ch = rabbit_ct_client_helpers :open_channel (Config , QueueLeaderNode ),
2361
+ QName = atom_to_binary (? FUNCTION_NAME ),
2362
+ # 'queue.declare_ok' {} = amqp_channel :call (
2363
+ Ch , # 'queue.declare' {queue = QName ,
2364
+ durable = true ,
2365
+ arguments = [{<<" x-queue-type" >>, longstr , QueueType }]}),
2366
+ % % Connect AMQP client to the new node causing queue client to run the new code.
2367
+ OpnConf = connection_config (ClientNode , Config ),
2368
+ {ok , Connection } = amqp10_client :open_connection (OpnConf ),
2369
+ {ok , Session } = amqp10_client :begin_session_sync (Connection ),
2370
+ Address = <<" /amq/queue/" , QName /binary >>,
2371
+ {ok , Sender } = amqp10_client :attach_sender_link (
2372
+ Session , <<" test-sender" >>, Address ),
2373
+ ok = wait_for_credit (Sender ),
2374
+ {ok , Receiver } = amqp10_client :attach_receiver_link (
2375
+ Session ,
2376
+ <<" test-receiver" >>,
2377
+ Address ,
2378
+ unsettled ),
2379
+ receive {amqp10_event , {link , Receiver , attached }} -> ok
2380
+ after 5000 -> ct :fail (" missing attached" )
2381
+ end ,
2382
+ flush (receiver_attached ),
2383
+
2384
+ NumMsgs = 10 ,
2385
+ [begin
2386
+ Bin = integer_to_binary (N ),
2387
+ ok = amqp10_client :send_msg (Sender , amqp10_msg :new (Bin , Bin , true ))
2388
+ end || N <- lists :seq (1 , NumMsgs )],
2389
+
2390
+ % % Grant credits to the sending queue.
2391
+ ok = amqp10_client :flow_link_credit (Receiver , NumMsgs , never ),
2392
+
2393
+ % % We should receive all messages.
2394
+ Msgs = receive_messages (Receiver , NumMsgs ),
2395
+ FirstMsg = hd (Msgs ),
2396
+ LastMsg = lists :last (Msgs ),
2397
+ ? assertEqual ([<<" 1" >>], amqp10_msg :body (FirstMsg )),
2398
+ ? assertEqual ([integer_to_binary (NumMsgs )], amqp10_msg :body (LastMsg )),
2399
+ ok = amqp10_client_session :disposition (
2400
+ Session ,
2401
+ receiver ,
2402
+ amqp10_msg :delivery_id (FirstMsg ),
2403
+ amqp10_msg :delivery_id (LastMsg ),
2404
+ true ,
2405
+ accepted ),
2406
+
2407
+ CreditApiV2 = rpc (Config , rabbit_feature_flags , is_enabled , [credit_api_v2 ]),
2408
+ case QueueType =:= <<" quorum" >> andalso not CreditApiV2 of
2409
+ true ->
2410
+ ct :pal (" Quorum queues in credit API v1 have a known bug that they "
2411
+ " reply with send_drained before delivering the message." );
2412
+ false ->
2413
+ % % Send another message and drain.
2414
+ Tag = <<" tag" >>,
2415
+ Body = <<" body" >>,
2416
+ ok = amqp10_client :send_msg (Sender , amqp10_msg :new (Tag , Body , false )),
2417
+ ok = wait_for_settlement (Tag ),
2418
+ ok = amqp10_client :flow_link_credit (Receiver , 999 , never , true ),
2419
+ [Msg ] = receive_messages (Receiver , 1 ),
2420
+ ? assertEqual ([Body ], amqp10_msg :body (Msg )),
2421
+ receive {amqp10_event , {link , Receiver , credit_exhausted }} -> ok
2422
+ after 5000 -> ct :fail (" expected credit_exhausted" )
2423
+ end ,
2424
+ ok = amqp10_client :accept_msg (Receiver , Msg )
2425
+ end ,
2426
+
2427
+ ExpectedReadyMsgs = 0 ,
2428
+ ? assertEqual (# 'queue.delete_ok' {message_count = ExpectedReadyMsgs },
2429
+ amqp_channel :call (Ch , # 'queue.delete' {queue = QName })),
2430
+ ok = rabbit_ct_client_helpers :close_channel (Ch ),
2431
+ ok = amqp10_client :close_connection (Connection ).
2432
+
2388
2433
% % internal
2389
2434
% %
2390
2435
2391
2436
connection_config (Config ) ->
2437
+ connection_config (0 , Config ).
2438
+
2439
+ connection_config (Node , Config ) ->
2392
2440
Host = ? config (rmq_hostname , Config ),
2393
- Port = rabbit_ct_broker_helpers :get_node_config (Config , 0 , tcp_port_amqp ),
2441
+ Port = rabbit_ct_broker_helpers :get_node_config (Config , Node , tcp_port_amqp ),
2394
2442
#{address => Host ,
2395
2443
port => Port ,
2396
2444
container_id => <<" my container" >>,
0 commit comments