@@ -52,7 +52,10 @@ groups() ->
5252 {mock , [], [
5353 insufficient_credit ,
5454 incoming_heartbeat ,
55- multi_transfer_without_delivery_id
55+ multi_transfer_without_delivery_id ,
56+ set_receiver_capabilities ,
57+ set_sender_capabilities ,
58+ set_sender_sync_capabilities
5659 ]}
5760 ].
5861
@@ -687,6 +690,7 @@ subscribe_with_auto_flow_unsettled(Config) ->
687690 ok = amqp10_client :end_session (Session ),
688691 ok = amqp10_client :close_connection (Connection ).
689692
693+
690694insufficient_credit (Config ) ->
691695 Hostname = ? config (mock_host , Config ),
692696 Port = ? config (mock_port , Config ),
@@ -790,6 +794,176 @@ multi_transfer_without_delivery_id(Config) ->
790794 ok = amqp10_client :close_connection (Connection ),
791795 ok .
792796
797+ set_receiver_capabilities (Config ) ->
798+ Hostname = ? config (mock_host , Config ),
799+ Port = ? config (mock_port , Config ),
800+
801+ OpenStep = fun ({0 = Ch , # 'v1_0.open' {}, _Pay }) ->
802+ {Ch , [# 'v1_0.open' {container_id = {utf8 , <<" mock" >>}}]}
803+ end ,
804+ BeginStep = fun ({1 = Ch , # 'v1_0.begin' {}, _Pay }) ->
805+ {Ch , [# 'v1_0.begin' {remote_channel = {ushort , 1 },
806+ next_outgoing_id = {uint , 1 },
807+ incoming_window = {uint , 1000 },
808+ outgoing_window = {uint , 1000 }}
809+ ]}
810+ end ,
811+ AttachStep = fun ({1 = Ch , # 'v1_0.attach' {role = true ,
812+ name = Name ,
813+ source = # 'v1_0.source' {
814+ capabilities = {utf8 , <<" capability-1" >>}}}, <<>>}) ->
815+ {Ch , [# 'v1_0.attach' {name = Name ,
816+ handle = {uint , 99 },
817+ initial_delivery_count = {uint , 1 },
818+ role = false }
819+ ]}
820+ end ,
821+
822+ LinkCreditStep = fun ({1 = Ch , # 'v1_0.flow' {}, <<>>}) ->
823+ {Ch , {multi , [[# 'v1_0.transfer' {handle = {uint , 99 },
824+ delivery_id = {uint , 12 },
825+ more = true },
826+ # 'v1_0.data' {content = <<" hello " >>}],
827+ [# 'v1_0.transfer' {handle = {uint , 99 },
828+ % delivery_id can be omitted
829+ % for continuation frames
830+ delivery_id = undefined ,
831+ settled = undefined ,
832+ more = false },
833+ # 'v1_0.data' {content = <<" world" >>}]
834+ ]}}
835+ end ,
836+ Steps = [fun mock_server :recv_amqp_header_step /1 ,
837+ fun mock_server :send_amqp_header_step /1 ,
838+ mock_server :amqp_step (OpenStep ),
839+ mock_server :amqp_step (BeginStep ),
840+ mock_server :amqp_step (AttachStep ),
841+ mock_server :amqp_step (LinkCreditStep )
842+ ],
843+
844+ ok = mock_server :set_steps (? config (mock_server , Config ), Steps ),
845+
846+ Cfg = #{address => Hostname , port => Port , sasl => none , notify => self ()},
847+ {ok , Connection } = amqp10_client :open_connection (Cfg ),
848+ {ok , Session } = amqp10_client :begin_session_sync (Connection ),
849+ {ok , Receiver } = amqp10_client :attach_receiver_link (Session , <<" mock1-received" >>,
850+ <<" test" >>,
851+ setlled , none ,
852+ #{}, % filter
853+ #{}, % prorperties
854+ <<" capability-1" >>),
855+ amqp10_client :flow_link_credit (Receiver , 100 , 50 ),
856+ receive
857+ {amqp10_msg , Receiver , _InMsg } ->
858+ ok
859+ after 2000 ->
860+ exit (delivery_timeout )
861+ end ,
862+
863+ ok = amqp10_client :end_session (Session ),
864+ ok = amqp10_client :close_connection (Connection ),
865+ ok .
866+
867+ set_sender_capabilities (Config ) ->
868+ Hostname = ? config (mock_host , Config ),
869+ Port = ? config (mock_port , Config ),
870+ OpenStep = fun ({0 = Ch , # 'v1_0.open' {}, _Pay }) ->
871+ {Ch , [# 'v1_0.open' {container_id = {utf8 , <<" mock" >>}}]}
872+ end ,
873+ BeginStep = fun ({1 = Ch , # 'v1_0.begin' {}, _Pay }) ->
874+ {Ch , [# 'v1_0.begin' {remote_channel = {ushort , 1 },
875+ next_outgoing_id = {uint , 1 },
876+ incoming_window = {uint , 1000 },
877+ outgoing_window = {uint , 1000 }}
878+ ]}
879+ end ,
880+ AttachStep = fun ({1 = Ch , # 'v1_0.attach' {role = false ,
881+ name = Name ,
882+ source = # 'v1_0.source' {
883+
884+ },
885+ target = # 'v1_0.target' {
886+ capabilities = {utf8 , <<" capability-1" >>}}}, <<>>}) ->
887+ {Ch , [# 'v1_0.attach' {name = Name ,
888+ handle = {uint , 99 },
889+ role = true }]}
890+ end ,
891+ Steps = [fun mock_server :recv_amqp_header_step /1 ,
892+ fun mock_server :send_amqp_header_step /1 ,
893+ mock_server :amqp_step (OpenStep ),
894+ mock_server :amqp_step (BeginStep ),
895+ mock_server :amqp_step (AttachStep )],
896+
897+ ok = mock_server :set_steps (? config (mock_server , Config ), Steps ),
898+
899+ Cfg = #{address => Hostname , port => Port , sasl => none , notify => self ()},
900+ {ok , Connection } = amqp10_client :open_connection (Cfg ),
901+ {ok , Session } = amqp10_client :begin_session_sync (Connection ),
902+ {ok , Sender } = amqp10_client :attach_sender_link (Session , <<" mock1-sender" >>,
903+ <<" test" >>,
904+ mixed ,
905+ none ,
906+ <<" capability-1" >>),
907+ await_link (Sender , attached , attached_timeout ),
908+ Msg = amqp10_msg :new (<<" mock-tag" >>, <<" banana" >>, true ),
909+ {error , insufficient_credit } = amqp10_client :send_msg (Sender , Msg ),
910+
911+ ok = amqp10_client :end_session (Session ),
912+ ok = amqp10_client :close_connection (Connection ),
913+ ok .
914+
915+
916+ set_sender_sync_capabilities (Config ) ->
917+ Hostname = ? config (mock_host , Config ),
918+ Port = ? config (mock_port , Config ),
919+ OpenStep = fun ({0 = Ch , # 'v1_0.open' {}, _Pay }) ->
920+ {Ch , [# 'v1_0.open' {container_id = {utf8 , <<" mock" >>}}]}
921+ end ,
922+ BeginStep = fun ({1 = Ch , # 'v1_0.begin' {}, _Pay }) ->
923+ {Ch , [# 'v1_0.begin' {remote_channel = {ushort , 1 },
924+ next_outgoing_id = {uint , 1 },
925+ incoming_window = {uint , 1000 },
926+ outgoing_window = {uint , 1000 }}
927+ ]}
928+ end ,
929+ AttachStep = fun ({1 = Ch , # 'v1_0.attach' {role = false ,
930+ name = Name ,
931+ source = # 'v1_0.source' {
932+
933+ },
934+ target = # 'v1_0.target' {
935+ capabilities = {list , [
936+ {utf8 ,<<" capability-1" >>},
937+ {utf8 ,<<" capability-2" >>}
938+ ]}
939+ }}, <<>>}) ->
940+ {Ch , [# 'v1_0.attach' {name = Name ,
941+ handle = {uint , 99 },
942+ role = true }]}
943+ end ,
944+ Steps = [fun mock_server :recv_amqp_header_step /1 ,
945+ fun mock_server :send_amqp_header_step /1 ,
946+ mock_server :amqp_step (OpenStep ),
947+ mock_server :amqp_step (BeginStep ),
948+ mock_server :amqp_step (AttachStep )],
949+
950+ ok = mock_server :set_steps (? config (mock_server , Config ), Steps ),
951+
952+ Cfg = #{address => Hostname , port => Port , sasl => none , notify => self ()},
953+ {ok , Connection } = amqp10_client :open_connection (Cfg ),
954+ {ok , Session } = amqp10_client :begin_session_sync (Connection ),
955+ {ok , Sender } = amqp10_client :attach_sender_link_sync (Session , <<" mock1-sender" >>,
956+ <<" test" >>,
957+ mixed ,
958+ none ,
959+ [<<" capability-1" >>,<<" capability-2" >>]),
960+ Msg = amqp10_msg :new (<<" mock-tag" >>, <<" banana" >>, true ),
961+ {error , insufficient_credit } = amqp10_client :send_msg (Sender , Msg ),
962+
963+ ok = amqp10_client :end_session (Session ),
964+ ok = amqp10_client :close_connection (Connection ),
965+ ok .
966+
793967outgoing_heartbeat (Config ) ->
794968 Hostname = ? config (rmq_hostname , Config ),
795969 Port = rabbit_ct_broker_helpers :get_node_config (Config , 0 , tcp_port_amqp ),
0 commit comments