@@ -60,7 +60,8 @@ federation_mechanics_tests() ->
6060 dynamic_reconfiguration ,
6161 federate_unfederate ,
6262 dynamic_plugin_stop_start ,
63- supervisor_shutdown_concurrency_safety
63+ supervisor_shutdown_concurrency_safety ,
64+ clear_upstream_leaves_same_named_exchange_intact
6465 ]}
6566 ]}
6667 ].
@@ -399,6 +400,49 @@ supervisor_shutdown_concurrency_safety(Config) ->
399400
400401 expect_federation (Ch , UpQ1 , DownQ1 , ? EXPECT_FEDERATION_TIMEOUT )
401402 end , upstream_downstream (Config ) ++ [q (DownQ2 , Args )]).
403+
404+ % % Clearing a queue-federation upstream must leave a same-named exchange
405+ % % untouched. See rabbitmq/rabbitmq-server#16991.
406+ clear_upstream_leaves_same_named_exchange_intact (Config ) ->
407+ % % The federated queue and a fanout exchange share {vhost, name}.
408+ Name = <<" fed1.downstream" >>,
409+ XName = rabbit_misc :r (<<" /" >>, exchange , Name ),
410+ with_ch (Config ,
411+ fun (Ch ) ->
412+ # 'exchange.declare_ok' {} =
413+ amqp_channel :call (Ch , # 'exchange.declare' {exchange = Name ,
414+ type = <<" fanout" >>,
415+ durable = true }),
416+ # 'queue.bind_ok' {} =
417+ amqp_channel :call (Ch , # 'queue.bind' {queue = Name ,
418+ exchange = Name }),
419+
420+ await_running_federation (Config ,
421+ [{Name , <<" upstream" >>}],
422+ ? EXPECT_FEDERATION_TIMEOUT ),
423+ expect_federation (Ch , <<" upstream" >>, Name , ? EXPECT_FEDERATION_TIMEOUT ),
424+
425+ % % Before clearing, the decorators are a valid {Route, NoRoute} tuple.
426+ {_ , _ } = exchange_decorators (Config , XName ),
427+
428+ clear_upstream (Config , 0 , <<" localhost" >>),
429+
430+ % % After clearing they must still be a tuple, not a bare [].
431+ {_ , _ } = exchange_decorators (Config , XName ),
432+
433+ % % Publishing to the exchange still routes to the queue rather
434+ % % than crashing the channel with a decorator function_clause.
435+ Payload = <<" after-clear" >>,
436+ publish (Ch , Name , <<>>, Payload ),
437+ expect (Ch , Name , [Payload ])
438+ end , upstream_downstream (Config )).
439+
440+ % % #exchange.decorators
441+ exchange_decorators (Config , XName ) ->
442+ {ok , X } = rabbit_ct_broker_helpers :rpc (Config , 0 ,
443+ rabbit_exchange , lookup , [XName ]),
444+ element (11 , X ).
445+
402446restart_upstream (Config ) ->
403447 [Rabbit , Hare ] = rabbit_ct_broker_helpers :get_node_configs (Config ,
404448 nodename ),
0 commit comments