@@ -6,7 +6,7 @@ use matrix_sdk::{
6
6
config:: StoreConfig ,
7
7
media:: { MediaFormat , MediaRequestParameters , MediaThumbnailSettings } ,
8
8
send_queue:: {
9
- LocalEcho , LocalEchoContent , RoomSendQueueError , RoomSendQueueStorageError ,
9
+ LocalEcho , LocalEchoContent , RoomSendQueue , RoomSendQueueError , RoomSendQueueStorageError ,
10
10
RoomSendQueueUpdate ,
11
11
} ,
12
12
test_utils:: {
@@ -40,6 +40,25 @@ use tokio::{
40
40
} ;
41
41
use wiremock:: { Request , ResponseTemplate } ;
42
42
43
+ /// Queues an attachment whenever the actual data/mime type etc. don't matter.
44
+ ///
45
+ /// Returns the filename, for sanity check purposes.
46
+ async fn queue_attachment_no_thumbnail ( q : & RoomSendQueue ) -> & ' static str {
47
+ let filename = "surprise.jpeg.exe" ;
48
+ let content_type = mime:: IMAGE_JPEG ;
49
+ let data = b"hello world" . to_vec ( ) ;
50
+ let config = AttachmentConfig :: new ( ) . info ( AttachmentInfo :: Image ( BaseImageInfo {
51
+ height : Some ( uint ! ( 13 ) ) ,
52
+ width : Some ( uint ! ( 37 ) ) ,
53
+ size : Some ( uint ! ( 42 ) ) ,
54
+ blurhash : None ,
55
+ } ) ) ;
56
+ q. send_attachment ( filename, content_type, data, config)
57
+ . await
58
+ . expect ( "queuing the attachment works" ) ;
59
+ filename
60
+ }
61
+
43
62
fn mock_jpeg_upload < ' a > (
44
63
mock : & ' a MatrixMockServer ,
45
64
mxc : & MxcUri ,
@@ -1936,18 +1955,6 @@ async fn test_media_upload_retry() {
1936
1955
let ( local_echoes, mut watch) = q. subscribe ( ) . await . unwrap ( ) ;
1937
1956
assert ! ( local_echoes. is_empty( ) ) ;
1938
1957
1939
- // Create the media to send (no thumbnails).
1940
- let filename = "surprise.jpeg.exe" ;
1941
- let content_type = mime:: IMAGE_JPEG ;
1942
- let data = b"hello world" . to_vec ( ) ;
1943
-
1944
- let config = AttachmentConfig :: new ( ) . info ( AttachmentInfo :: Image ( BaseImageInfo {
1945
- height : Some ( uint ! ( 13 ) ) ,
1946
- width : Some ( uint ! ( 37 ) ) ,
1947
- size : Some ( uint ! ( 42 ) ) ,
1948
- blurhash : None ,
1949
- } ) ) ;
1950
-
1951
1958
// Prepare endpoints.
1952
1959
mock. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
1953
1960
@@ -1962,9 +1969,7 @@ async fn test_media_upload_retry() {
1962
1969
1963
1970
// Send the media.
1964
1971
assert ! ( watch. is_empty( ) ) ;
1965
- q. send_attachment ( filename, content_type, data, config)
1966
- . await
1967
- . expect ( "queuing the attachment works" ) ;
1972
+ let filename = queue_attachment_no_thumbnail ( & q) . await ;
1968
1973
1969
1974
// Observe the local echo.
1970
1975
let ( event_txn, _send_handle, content) = assert_update ! ( watch => local echo event) ;
@@ -2024,18 +2029,6 @@ async fn test_unwedging_media_upload() {
2024
2029
let ( local_echoes, mut watch) = q. subscribe ( ) . await . unwrap ( ) ;
2025
2030
assert ! ( local_echoes. is_empty( ) ) ;
2026
2031
2027
- // Create the media to send (no thumbnails).
2028
- let filename = "rickroll.gif" ;
2029
- let content_type = mime:: IMAGE_JPEG ;
2030
- let data = b"Never gonna give you up" . to_vec ( ) ;
2031
-
2032
- let config = AttachmentConfig :: new ( ) . info ( AttachmentInfo :: Image ( BaseImageInfo {
2033
- height : Some ( uint ! ( 13 ) ) ,
2034
- width : Some ( uint ! ( 37 ) ) ,
2035
- size : Some ( uint ! ( 42 ) ) ,
2036
- blurhash : None ,
2037
- } ) ) ;
2038
-
2039
2032
// Prepare endpoints.
2040
2033
mock. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
2041
2034
@@ -2045,9 +2038,7 @@ async fn test_unwedging_media_upload() {
2045
2038
2046
2039
// Send the media.
2047
2040
assert ! ( watch. is_empty( ) ) ;
2048
- q. send_attachment ( filename, content_type, data, config)
2049
- . await
2050
- . expect ( "queuing the attachment works" ) ;
2041
+ let filename = queue_attachment_no_thumbnail ( & q) . await ;
2051
2042
2052
2043
// Observe the local echo.
2053
2044
let ( event_txn, send_handle, content) = assert_update ! ( watch => local echo event) ;
@@ -2085,3 +2076,86 @@ async fn test_unwedging_media_upload() {
2085
2076
// That's all, folks!
2086
2077
assert ! ( watch. is_empty( ) ) ;
2087
2078
}
2079
+
2080
+ #[ async_test]
2081
+ async fn test_media_upload_ordering ( ) {
2082
+ // Test that despite happening in multiple requests, sending a media maintains
2083
+ // the ordering.
2084
+
2085
+ let mock = MatrixMockServer :: new ( ) . await ;
2086
+
2087
+ // Mark the room as joined.
2088
+ let room_id = room_id ! ( "!a:b.c" ) ;
2089
+ let client = mock. client_builder ( ) . build ( ) . await ;
2090
+ let room = mock. sync_joined_room ( & client, room_id) . await ;
2091
+
2092
+ let q = room. send_queue ( ) ;
2093
+ let ( local_echoes, mut watch) = q. subscribe ( ) . await . unwrap ( ) ;
2094
+ assert ! ( local_echoes. is_empty( ) ) ;
2095
+
2096
+ // Prepare endpoints.
2097
+ mock. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
2098
+ mock. mock_upload ( ) . ok ( mxc_uri ! ( "mxc://sdk.rs/media" ) ) . mock_once ( ) . mount ( ) . await ;
2099
+
2100
+ assert ! ( watch. is_empty( ) ) ;
2101
+
2102
+ {
2103
+ // 1. Send a text message that will get wedged.
2104
+ mock. mock_room_send ( ) . error_too_large ( ) . mock_once ( ) . mount ( ) . await ;
2105
+ q. send ( RoomMessageEventContent :: text_plain ( "error" ) . into ( ) ) . await . unwrap ( ) ;
2106
+ let ( text_txn, _send_handle) = assert_update ! ( watch => local echo { body = "error" } ) ;
2107
+ assert_update ! ( watch => error { recoverable = false , txn = text_txn } ) ;
2108
+ }
2109
+
2110
+ // We'll then send a media event, and then a text event with success.
2111
+ mock. mock_room_send ( ) . ok ( event_id ! ( "$media" ) ) . mock_once ( ) . mount ( ) . await ;
2112
+ mock. mock_room_send ( ) . ok ( event_id ! ( "$text" ) ) . mock_once ( ) . mount ( ) . await ;
2113
+
2114
+ // 2. Queue the media.
2115
+ let filename = queue_attachment_no_thumbnail ( & q) . await ;
2116
+
2117
+ // 3. Queue the message.
2118
+ q. send ( RoomMessageEventContent :: text_plain ( "hello world" ) . into ( ) ) . await . unwrap ( ) ;
2119
+
2120
+ // Observe the local echo for the media.
2121
+ let ( event_txn, _send_handle, content) = assert_update ! ( watch => local echo event) ;
2122
+ assert_let ! ( MessageType :: Image ( img_content) = content. msgtype) ;
2123
+ assert_eq ! ( img_content. body, filename) ;
2124
+
2125
+ // Observe the local echo for the message.
2126
+ let ( text_txn, _send_handle) = assert_update ! ( watch => local echo { body = "hello world" } ) ;
2127
+
2128
+ // The media gets uploaded.
2129
+ assert_update ! ( watch => uploaded {
2130
+ related_to = event_txn,
2131
+ mxc = mxc_uri!( "mxc://sdk.rs/media" )
2132
+ } ) ;
2133
+
2134
+ let edit_msg = assert_update ! ( watch => edit local echo {
2135
+ txn = event_txn
2136
+ } ) ;
2137
+ assert_let ! ( MessageType :: Image ( new_content) = edit_msg. msgtype) ;
2138
+ assert_let ! ( MediaSource :: Plain ( new_uri) = & new_content. source) ;
2139
+ assert_eq ! ( new_uri, mxc_uri!( "mxc://sdk.rs/media" ) ) ;
2140
+
2141
+ // The media event is sent, at some point.
2142
+ assert_update ! ( watch => sent {
2143
+ txn = event_txn,
2144
+ event_id = event_id!( "$media" )
2145
+ } ) ;
2146
+
2147
+ // Then the text event is sent.
2148
+ assert_update ! ( watch => sent {
2149
+ txn = text_txn,
2150
+ event_id = event_id!( "$text" )
2151
+ } ) ;
2152
+
2153
+ // That's all, folks!
2154
+ assert ! ( watch. is_empty( ) ) ;
2155
+
2156
+ // When reopening the send queue, we still see the wedged event.
2157
+ let ( local_echoes, _watch) = q. subscribe ( ) . await . unwrap ( ) ;
2158
+ assert_eq ! ( local_echoes. len( ) , 1 ) ;
2159
+ assert_let ! ( LocalEchoContent :: Event { send_error, .. } = & local_echoes[ 0 ] . content) ;
2160
+ assert ! ( send_error. is_some( ) ) ;
2161
+ }
0 commit comments