@@ -239,10 +239,12 @@ is_skipped(_, _) ->
239
239
basic_groups () ->
240
240
[
241
241
{mam_all , [parallel ],
242
- [{mam04 , [parallel ], mam_cases () ++ [retrieve_form_fields ] ++ text_search_cases ()},
242
+ [{mam04 , [parallel ], mam_cases () ++ [retrieve_form_fields ] ++ text_search_cases ()
243
+ ++ [{stream_management , [], stream_management_cases ()}]},
243
244
{mam06 , [parallel ], mam_cases () ++ [retrieve_form_fields_extra_features ]
244
245
++ stanzaid_cases () ++ retract_cases ()
245
- ++ metadata_cases () ++ fetch_specific_msgs_cases ()},
246
+ ++ metadata_cases () ++ fetch_specific_msgs_cases ()
247
+ ++ [{stream_management , [], stream_management_cases ()}]},
246
248
{nostore , [parallel ], nostore_cases ()},
247
249
{archived , [parallel ], archived_cases ()},
248
250
{configurable_archiveid , [], configurable_archiveid_cases ()},
@@ -513,6 +515,11 @@ impl_specific() ->
513
515
pm_sql_query_failed ,
514
516
async_pools_batch_flush ].
515
517
518
+ stream_management_cases () ->
519
+ [reconnect_ack ,
520
+ reconnect_no_ack ,
521
+ reconnect_no_ack_different_resource ].
522
+
516
523
suite () ->
517
524
require_rpc_nodes ([mim ]) ++ escalus :suite ().
518
525
@@ -582,6 +589,13 @@ init_per_group(with_rsm04, Config) ->
582
589
[{props , mam04_props ()}, {with_rsm , true }|Config ];
583
590
init_per_group (nostore , Config ) ->
584
591
Config ;
592
+ init_per_group (stream_management , Config ) ->
593
+ Config1 = dynamic_modules :save_modules (host_type (), Config ),
594
+ DefaultSMConfig = config_parser_helper :default_mod_config (mod_stream_management ),
595
+ MnesiaOrCets = ct_helper :get_internal_database (),
596
+ SMConfig = DefaultSMConfig #{backend => MnesiaOrCets },
597
+ dynamic_modules :ensure_modules (host_type (), [{mod_stream_management , SMConfig }]),
598
+ Config1 ;
585
599
init_per_group (archived , Config ) ->
586
600
Config ;
587
601
init_per_group (muc04 , Config ) ->
@@ -683,6 +697,8 @@ end_per_group(G, Config) when G == drop_msg;
683
697
G == muc_drop_msg ->
684
698
teardown_meck (),
685
699
Config ;
700
+ end_per_group (stream_management , Config ) ->
701
+ dynamic_modules :restore_modules (Config );
686
702
end_per_group (muc_configurable_archiveid , Config ) ->
687
703
dynamic_modules :restore_modules (Config ),
688
704
Config ;
@@ -3854,6 +3870,139 @@ check_user_exist(Config) ->
3854
3870
% % cleanup
3855
3871
ok = rpc (mim (), ejabberd_auth , remove_user , [JID ]).
3856
3872
3873
+ reconnect_no_ack (Config ) ->
3874
+ % % Connect Bob and Alice
3875
+ Bob = sm_helper :connect_fresh (Config , bob , presence ),
3876
+ Alice = sm_helper :connect_fresh (Config , alice , sr_presence , manual ),
3877
+ AliceJid = escalus_client :full_jid (Alice ),
3878
+ BobJid = escalus_client :full_jid (Bob ),
3879
+ sm_helper :ack_initial_presence (Alice ),
3880
+
3881
+ % 1. Bob sends a msg to Alice
3882
+ Body = <<" OH, HAI! Msg 1" >>,
3883
+ escalus :send (Bob , escalus_stanza :chat_to (Alice , Body )),
3884
+ mam_helper :wait_for_archive_size (Alice , 1 ),
3885
+
3886
+ % 2. Alice receives, and does not acknowledge
3887
+ % She may get the ack request before the message for some reason
3888
+ Resp = [_ , _ ] = escalus_client :wait_for_stanzas (Alice , 2 ),
3889
+ escalus :assert_many ([fun (Msg ) -> escalus_pred :is_chat_message_from_to (BobJid , AliceJid , Body , Msg ) end ,
3890
+ fun (SMRequest ) -> escalus_pred :is_sm_ack_request (SMRequest ) end ],
3891
+ Resp ),
3892
+
3893
+ % 3. Alice disconnects abruptly
3894
+ C2SPid = mongoose_helper :get_session_pid (Alice ),
3895
+ escalus_connection :kill (Alice ),
3896
+ sm_helper :wait_until_resume_session (C2SPid ),
3897
+ sm_helper :assert_alive_resources (Alice , 1 ),
3898
+
3899
+ % 4. Alice reconnects
3900
+ NewAlice = sm_helper :connect_same (Alice , session ),
3901
+
3902
+ % We have to send presence by hand, because the message may be received first
3903
+ sm_helper :send_initial_presence (NewAlice ),
3904
+ % Current behaviour - unacked stanza is rerouted when a quick reconnection occurs
3905
+ % there is no delay element, or any indication of retransmission
3906
+ NewResp = [_ , _ ] = escalus_client :wait_for_stanzas (NewAlice , 2 ),
3907
+ escalus :assert_many ([fun (Msg ) -> escalus_pred :is_chat_message_from_to (BobJid , AliceJid , Body , Msg ) end ,
3908
+ fun (Presence ) -> escalus_pred :is_presence (Presence ) end ],
3909
+ NewResp ),
3910
+
3911
+ AliceUsername = escalus_client :username (NewAlice ),
3912
+ AliceServer = escalus_client :server (NewAlice ),
3913
+
3914
+ % There is only one message in MAM, even though it was resent
3915
+ ? assertEqual (1 , mam_helper :archive_size (AliceServer , AliceUsername )),
3916
+
3917
+ escalus_connection :stop (Bob ),
3918
+ escalus_connection :stop (Alice ).
3919
+
3920
+ reconnect_ack (Config ) ->
3921
+ % Connect Bob and Alice
3922
+ Bob = sm_helper :connect_fresh (Config , bob , presence ),
3923
+ Alice = sm_helper :connect_fresh (Config , alice , sr_presence , manual ),
3924
+ AliceJid = escalus_client :full_jid (Alice ),
3925
+ BobJid = escalus_client :full_jid (Bob ),
3926
+ sm_helper :ack_initial_presence (Alice ),
3927
+
3928
+ % 1. Bob sends a msg to Alice
3929
+ Body = <<" OH, HAI! Msg 1" >>,
3930
+ escalus :send (Bob , escalus_stanza :chat_to (Alice , Body )),
3931
+ mam_helper :wait_for_archive_size (Alice , 1 ),
3932
+
3933
+ % 2. Alice receives, and acknowledges
3934
+ Resp = [_ , _ ] = escalus_client :wait_for_stanzas (Alice , 2 ),
3935
+ escalus :assert_many ([fun (Msg ) -> escalus_pred :is_chat_message_from_to (BobJid , AliceJid , Body , Msg ) end ,
3936
+ fun (SMRequest ) -> escalus_pred :is_sm_ack_request (SMRequest ) end ],
3937
+ Resp ),
3938
+ escalus_connection :send (Alice , escalus_stanza :sm_ack (2 )),
3939
+
3940
+ % 3. Alice disconnects abruptly
3941
+ C2SPid = mongoose_helper :get_session_pid (Alice ),
3942
+ escalus_connection :kill (Alice ),
3943
+ sm_helper :wait_until_resume_session (C2SPid ),
3944
+ sm_helper :assert_alive_resources (Alice , 1 ),
3945
+
3946
+ % 4. Alice reconnects
3947
+ NewAlice = sm_helper :connect_same (Alice , presence ),
3948
+
3949
+ % 5. Check no new messages received
3950
+ timer :sleep (timer :seconds (1 )),
3951
+ escalus_assert :has_no_stanzas (NewAlice ),
3952
+
3953
+ % No new messages in MAM as well
3954
+ AliceUsername = escalus_client :username (NewAlice ),
3955
+ AliceServer = escalus_client :server (NewAlice ),
3956
+ ? assertEqual (1 , mam_helper :archive_size (AliceServer , AliceUsername )),
3957
+
3958
+ escalus_connection :stop (Bob ),
3959
+ escalus_connection :stop (Alice ).
3960
+
3961
+ reconnect_no_ack_different_resource (Config ) ->
3962
+ % % Connect Bob and Alice
3963
+ Bob = sm_helper :connect_fresh (Config , bob , presence ),
3964
+ Spec = escalus_fresh :create_fresh_user (Config , {alice , 2 }),
3965
+ Alice = sm_helper :connect_spec (Spec , sr_presence , manual ),
3966
+ AliceJid = escalus_client :full_jid (Alice ),
3967
+ BobJid = escalus_client :full_jid (Bob ),
3968
+ sm_helper :ack_initial_presence (Alice ),
3969
+
3970
+ % 1. Bob sends a msg to Alice
3971
+ Body = <<" OH, HAI! Msg 1" >>,
3972
+ escalus :send (Bob , escalus_stanza :chat_to (Alice , Body )),
3973
+ mam_helper :wait_for_archive_size (Alice , 1 ),
3974
+
3975
+ % 2. Alice receives, and does not acknowledge
3976
+ Resp = [_ , _ ] = escalus_client :wait_for_stanzas (Alice , 2 ),
3977
+ escalus :assert_many ([fun (Msg ) -> escalus_pred :is_chat_message_from_to (BobJid , AliceJid , Body , Msg ) end ,
3978
+ fun (SMRequest ) -> escalus_pred :is_sm_ack_request (SMRequest ) end ],
3979
+ Resp ),
3980
+
3981
+ % 3. Alice disconnects abruptly
3982
+ C2SPid = mongoose_helper :get_session_pid (Alice ),
3983
+ escalus_connection :kill (Alice ),
3984
+ sm_helper :wait_until_resume_session (C2SPid ),
3985
+ sm_helper :assert_alive_resources (Alice , 1 ),
3986
+
3987
+ % 4. Alice reconnects a different resource
3988
+ NewAlice = sm_helper :connect_spec ([{resource , <<" mam_sm_test_2nd_resource" >>} | Spec ], presence , manual ),
3989
+
3990
+ % 2nd resource doesn't get the stanza, only the delayed presence.
3991
+ Presence = escalus :wait_for_stanza (NewAlice ),
3992
+ escalus :assert (is_presence , Presence ),
3993
+
3994
+ % 5. Check no new messages received
3995
+ timer :sleep (timer :seconds (1 )),
3996
+ escalus_assert :has_no_stanzas (NewAlice ),
3997
+
3998
+ % No new messages in MAM as well
3999
+ AliceUsername = escalus_client :username (NewAlice ),
4000
+ AliceServer = escalus_client :server (NewAlice ),
4001
+ ? assertEqual (1 , mam_helper :archive_size (AliceServer , AliceUsername )),
4002
+
4003
+ escalus_connection :stop (Bob ),
4004
+ escalus_connection :stop (Alice ).
4005
+
3857
4006
% % This function supports only one device, one user.
3858
4007
% % We don't send initial presence to avoid presence broadcasts between resources
3859
4008
% % of the same user from different stories.
0 commit comments