@@ -2010,3 +2010,78 @@ async fn test_media_upload_retry() {
20102010 // That's all, folks!
20112011 assert ! ( watch. is_empty( ) ) ;
20122012}
2013+
2014+ #[ async_test]
2015+ async fn test_unwedging_media_upload ( ) {
2016+ let mock = MatrixMockServer :: new ( ) . await ;
2017+
2018+ // Mark the room as joined.
2019+ let room_id = room_id ! ( "!a:b.c" ) ;
2020+ let client = mock. client_builder ( ) . build ( ) . await ;
2021+ let room = mock. sync_joined_room ( & client, room_id) . await ;
2022+
2023+ let q = room. send_queue ( ) ;
2024+ let ( local_echoes, mut watch) = q. subscribe ( ) . await . unwrap ( ) ;
2025+ assert ! ( local_echoes. is_empty( ) ) ;
2026+
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+ // Prepare endpoints.
2040+ mock. mock_room_state_encryption ( ) . plain ( ) . mount ( ) . await ;
2041+
2042+ // Fail for the first attempt with an error indicating the media's too large,
2043+ // wedging the upload.
2044+ mock. mock_upload ( ) . error_too_large ( ) . mock_once ( ) . mount ( ) . await ;
2045+
2046+ // Send the media.
2047+ assert ! ( watch. is_empty( ) ) ;
2048+ q. send_attachment ( filename, content_type, data, config)
2049+ . await
2050+ . expect ( "queuing the attachment works" ) ;
2051+
2052+ // Observe the local echo.
2053+ let ( event_txn, send_handle, content) = assert_update ! ( watch => local echo event) ;
2054+ assert_let ! ( MessageType :: Image ( img_content) = content. msgtype) ;
2055+ assert_eq ! ( img_content. body, filename) ;
2056+
2057+ // Although the actual error happens on the file upload transaction id, it must
2058+ // be reported with the *event* transaction id.
2059+ let error = assert_update ! ( watch => error { recoverable=false , txn=event_txn } ) ;
2060+ let error = error. as_client_api_error ( ) . unwrap ( ) ;
2061+ assert_eq ! ( error. status_code, 413 ) ;
2062+ assert ! ( q. is_enabled( ) ) ;
2063+
2064+ // Mount the mock for the upload and sending the event.
2065+ mock. mock_upload ( ) . ok ( mxc_uri ! ( "mxc://sdk.rs/media" ) ) . mock_once ( ) . mount ( ) . await ;
2066+ mock. mock_room_send ( ) . ok ( event_id ! ( "$1" ) ) . mock_once ( ) . mount ( ) . await ;
2067+
2068+ // Unwedge the upload.
2069+ send_handle. unwedge ( ) . await . unwrap ( ) ;
2070+
2071+ // Observe the notification for the retry itself.
2072+ assert_update ! ( watch => retry { txn = event_txn } ) ;
2073+
2074+ // Observe the upload succeeding at some point.
2075+ assert_update ! ( watch => uploaded { related_to = event_txn, mxc = mxc_uri!( "mxc://sdk.rs/media" ) } ) ;
2076+
2077+ let edit_msg = assert_update ! ( watch => edit local echo { txn = event_txn } ) ;
2078+ assert_let ! ( MessageType :: Image ( new_content) = edit_msg. msgtype) ;
2079+ assert_let ! ( MediaSource :: Plain ( new_uri) = & new_content. source) ;
2080+ assert_eq ! ( new_uri, mxc_uri!( "mxc://sdk.rs/media" ) ) ;
2081+
2082+ // The event is sent, at some point.
2083+ assert_update ! ( watch => sent { txn = event_txn, event_id = event_id!( "$1" ) } ) ;
2084+
2085+ // That's all, folks!
2086+ assert ! ( watch. is_empty( ) ) ;
2087+ }
0 commit comments