@@ -175,7 +175,8 @@ groups() ->
175175 x_cc_annotation_exchange_routing_key_empty ,
176176 x_cc_annotation_queue ,
177177 x_cc_annotation_null ,
178- bad_x_cc_annotation_exchange
178+ bad_x_cc_annotation_exchange ,
179+ decimal_types
179180 ]},
180181
181182 {cluster_size_3 , [shuffle ],
@@ -6685,6 +6686,69 @@ bad_x_cc_annotation_exchange(Config) ->
66856686 ok = end_session_sync (Session ),
66866687 ok = close_connection_sync (Connection ).
66876688
6689+ % % Test that RabbitMQ can store and forward AMQP decimal types.
6690+ decimal_types (Config ) ->
6691+ QName = atom_to_binary (? FUNCTION_NAME ),
6692+ Address = rabbitmq_amqp_address :queue (QName ),
6693+ {_ , Session , LinkPair } = Init = init (Config ),
6694+ {ok , _ } = rabbitmq_amqp_client :declare_queue (
6695+ LinkPair , QName ,
6696+ #{arguments => #{<<" x-queue-type" >> => {utf8 , <<" quorum" >>}}}),
6697+ {ok , Sender } = amqp10_client :attach_sender_link (Session , <<" sender" >>, Address ),
6698+ ok = wait_for_credit (Sender ),
6699+
6700+ Decimal32Zero = <<16#22 , 16#50 , 0 , 0 >>,
6701+ Decimal64Zero = <<16#22 , 16#34 , 0 , 0 , 0 , 0 , 0 , 0 >>,
6702+ Decimal128Zero = <<16#22 , 16#08 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 >>,
6703+ Decimal3242 = <<16#22 , 16#50 , 16#00 , 16#2A >>, % 42
6704+ Decimal32NaN = <<16#7C , 0 , 0 , 0 >>,
6705+ Body = # 'v1_0.amqp_value' {content = {list , [{as_is , 16#74 , Decimal32Zero },
6706+ {as_is , 16#84 , Decimal64Zero },
6707+ {as_is , 16#94 , Decimal128Zero }]}},
6708+ MsgAnns = #{<<" x-decimal-32" >> => {as_is , 16#74 , Decimal3242 },
6709+ <<" x-decimal-64" >> => {as_is , 16#84 , Decimal64Zero },
6710+ <<" x-decimal-128" >> => {as_is , 16#94 , Decimal128Zero },
6711+ <<" x-list" >> => {list , [{as_is , 16#94 , Decimal128Zero }]},
6712+ <<" x-map" >> => {map , [{{utf8 , <<" key-1" >>},
6713+ {as_is , 16#94 , Decimal128Zero }}]}},
6714+ AppProps = #{<<" decimal-32" >> => {as_is , 16#74 , Decimal32NaN }},
6715+ Msg0 = amqp10_msg :set_message_annotations (
6716+ MsgAnns ,
6717+ amqp10_msg :set_application_properties (
6718+ AppProps ,
6719+ amqp10_msg :new (<<" tag" >>, Body ))),
6720+ ok = amqp10_client :send_msg (Sender , Msg0 ),
6721+ ok = wait_for_accepted (<<" tag" >>),
6722+ ok = amqp10_client :send_msg (Sender , Msg0 ),
6723+ ok = wait_for_accepted (<<" tag" >>),
6724+ ok = detach_link_sync (Sender ),
6725+
6726+ % % Consume the first message via AMQP 1.0
6727+ {ok , Receiver } = amqp10_client :attach_receiver_link (
6728+ Session , <<" receiver" >>, Address , unsettled ),
6729+ {ok , Msg } = amqp10_client :get_msg (Receiver ),
6730+ ? assertEqual (Body , amqp10_msg :body (Msg )),
6731+ ? assertMatch (#{<<" x-decimal-32" >> := {as_is , 16#74 , Decimal3242 },
6732+ <<" x-decimal-64" >> := {as_is , 16#84 , Decimal64Zero },
6733+ <<" x-decimal-128" >> := {as_is , 16#94 , Decimal128Zero },
6734+ <<" x-list" >> := [{as_is , 16#94 , Decimal128Zero }],
6735+ <<" x-map" >> := [{{utf8 , <<" key-1" >>},
6736+ {as_is , 16#94 , Decimal128Zero }}]},
6737+ amqp10_msg :message_annotations (Msg )),
6738+ ? assertEqual (AppProps , amqp10_msg :application_properties (Msg )),
6739+ ok = amqp10_client :accept_msg (Receiver , Msg ),
6740+ ok = detach_link_sync (Receiver ),
6741+
6742+ % % Consume the second message via AMQP 0.9.1
6743+ % % We expect to receive the message without any crashes.
6744+ {Conn , Ch } = rabbit_ct_client_helpers :open_connection_and_channel (Config ),
6745+ ? assertMatch ({# 'basic.get_ok' {}, # amqp_msg {}},
6746+ amqp_channel :call (Ch , # 'basic.get' {queue = QName , no_ack = true })),
6747+ ok = rabbit_ct_client_helpers :close_connection_and_channel (Conn , Ch ),
6748+
6749+ {ok , _ } = rabbitmq_amqp_client :delete_queue (LinkPair , QName ),
6750+ ok = close (Init ).
6751+
66886752% % Attach a receiver to an unavailable quorum queue.
66896753attach_to_down_quorum_queue (Config ) ->
66906754 QName = <<" q-down" >>,
0 commit comments