@@ -16,7 +16,10 @@ use std::{sync::Arc, time::Duration};
16
16
17
17
use assert_matches2:: assert_let;
18
18
use eyeball_im:: VectorDiff ;
19
- use futures_util:: future:: { join, join3} ;
19
+ use futures_util:: {
20
+ future:: { join, join3} ,
21
+ FutureExt ,
22
+ } ;
20
23
use matrix_sdk:: { config:: SyncSettings , test_utils:: logged_in_client_with_server} ;
21
24
use matrix_sdk_test:: {
22
25
async_test, EventBuilder , JoinedRoomBuilder , StateTestEvent , SyncResponseBuilder , ALICE , BOB ,
@@ -35,7 +38,10 @@ use ruma::{
35
38
} ;
36
39
use serde_json:: { json, Value as JsonValue } ;
37
40
use stream_assert:: { assert_next_eq, assert_next_matches} ;
38
- use tokio:: time:: { sleep, timeout} ;
41
+ use tokio:: {
42
+ spawn,
43
+ time:: { sleep, timeout} ,
44
+ } ;
39
45
use wiremock:: {
40
46
matchers:: { header, method, path_regex, query_param, query_param_is_missing} ,
41
47
Mock , ResponseTemplate ,
@@ -49,10 +55,10 @@ async fn test_back_pagination() {
49
55
let ( client, server) = logged_in_client_with_server ( ) . await ;
50
56
let sync_settings = SyncSettings :: new ( ) . timeout ( Duration :: from_millis ( 3000 ) ) ;
51
57
52
- let mut ev_builder = SyncResponseBuilder :: new ( ) ;
53
- ev_builder . add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
58
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
59
+ sync_builder . add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
54
60
55
- mock_sync ( & server, ev_builder . build_json_sync_response ( ) , None ) . await ;
61
+ mock_sync ( & server, sync_builder . build_json_sync_response ( ) , None ) . await ;
56
62
let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
57
63
server. reset ( ) . await ;
58
64
@@ -140,16 +146,16 @@ async fn test_back_pagination_highlighted() {
140
146
let ( client, server) = logged_in_client_with_server ( ) . await ;
141
147
let sync_settings = SyncSettings :: new ( ) . timeout ( Duration :: from_millis ( 3000 ) ) ;
142
148
143
- let mut ev_builder = SyncResponseBuilder :: new ( ) ;
144
- ev_builder
149
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
150
+ sync_builder
145
151
// We need the member event and power levels locally so the push rules processor works.
146
152
. add_joined_room (
147
153
JoinedRoomBuilder :: new ( room_id)
148
154
. add_state_event ( StateTestEvent :: Member )
149
155
. add_state_event ( StateTestEvent :: PowerLevels ) ,
150
156
) ;
151
157
152
- mock_sync ( & server, ev_builder . build_json_sync_response ( ) , None ) . await ;
158
+ mock_sync ( & server, sync_builder . build_json_sync_response ( ) , None ) . await ;
153
159
let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
154
160
server. reset ( ) . await ;
155
161
@@ -522,10 +528,10 @@ async fn test_empty_chunk() {
522
528
let ( client, server) = logged_in_client_with_server ( ) . await ;
523
529
let sync_settings = SyncSettings :: new ( ) . timeout ( Duration :: from_millis ( 3000 ) ) ;
524
530
525
- let mut ev_builder = SyncResponseBuilder :: new ( ) ;
526
- ev_builder . add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
531
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
532
+ sync_builder . add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
527
533
528
- mock_sync ( & server, ev_builder . build_json_sync_response ( ) , None ) . await ;
534
+ mock_sync ( & server, sync_builder . build_json_sync_response ( ) , None ) . await ;
529
535
let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
530
536
server. reset ( ) . await ;
531
537
@@ -612,10 +618,10 @@ async fn test_until_num_items_with_empty_chunk() {
612
618
let ( client, server) = logged_in_client_with_server ( ) . await ;
613
619
let sync_settings = SyncSettings :: new ( ) . timeout ( Duration :: from_millis ( 3000 ) ) ;
614
620
615
- let mut ev_builder = SyncResponseBuilder :: new ( ) ;
616
- ev_builder . add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
621
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
622
+ sync_builder . add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
617
623
618
- mock_sync ( & server, ev_builder . build_json_sync_response ( ) , None ) . await ;
624
+ mock_sync ( & server, sync_builder . build_json_sync_response ( ) , None ) . await ;
619
625
let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
620
626
server. reset ( ) . await ;
621
627
@@ -719,3 +725,54 @@ async fn test_until_num_items_with_empty_chunk() {
719
725
assert ! ( day_divider. is_day_divider( ) ) ;
720
726
assert_next_matches ! ( timeline_stream, VectorDiff :: Remove { index: 2 } ) ;
721
727
}
728
+
729
+ #[ async_test]
730
+ async fn test_back_pagination_aborted ( ) {
731
+ let room_id = room_id ! ( "!a98sd12bjh:example.org" ) ;
732
+ let ( client, server) = logged_in_client_with_server ( ) . await ;
733
+ let sync_settings = SyncSettings :: new ( ) . timeout ( Duration :: from_millis ( 3000 ) ) ;
734
+
735
+ let mut sync_builder = SyncResponseBuilder :: new ( ) ;
736
+ sync_builder. add_joined_room ( JoinedRoomBuilder :: new ( room_id) ) ;
737
+
738
+ mock_sync ( & server, sync_builder. build_json_sync_response ( ) , None ) . await ;
739
+ let _response = client. sync_once ( sync_settings. clone ( ) ) . await . unwrap ( ) ;
740
+ server. reset ( ) . await ;
741
+
742
+ let room = client. get_room ( room_id) . unwrap ( ) ;
743
+ let timeline = Arc :: new ( room. timeline ( ) . await . unwrap ( ) ) ;
744
+ let mut back_pagination_status = timeline. back_pagination_status ( ) ;
745
+
746
+ // Delay the server response, so we have time to abort the request.
747
+ Mock :: given ( method ( "GET" ) )
748
+ . and ( path_regex ( r"^/_matrix/client/r0/rooms/.*/messages$" ) )
749
+ . and ( header ( "authorization" , "Bearer 1234" ) )
750
+ . respond_with (
751
+ ResponseTemplate :: new ( 200 )
752
+ . set_body_json ( & * ROOM_MESSAGES_BATCH_1 )
753
+ . set_delay ( Duration :: from_secs ( 5 ) ) ,
754
+ )
755
+ . mount ( & server)
756
+ . await ;
757
+
758
+ let paginate = spawn ( {
759
+ let timeline = timeline. clone ( ) ;
760
+ async move {
761
+ timeline. live_paginate_backwards ( PaginationOptions :: simple_request ( 10 ) ) . await . unwrap ( ) ;
762
+ }
763
+ } ) ;
764
+
765
+ assert_eq ! ( back_pagination_status. next( ) . await , Some ( PaginationStatus :: Paginating ) ) ;
766
+
767
+ // Abort the pagination!
768
+ paginate. abort ( ) ;
769
+
770
+ // The task should finish with a cancellation.
771
+ assert ! ( paginate. await . unwrap_err( ) . is_cancelled( ) ) ;
772
+
773
+ // The timeline should automatically reset to idle.
774
+ assert_next_eq ! ( back_pagination_status, PaginationStatus :: Idle ) ;
775
+
776
+ // And there should be no other pending pagination status updates.
777
+ assert ! ( back_pagination_status. next( ) . now_or_never( ) . is_none( ) ) ;
778
+ }
0 commit comments