atagen

macltok

public
Star0
Watch0
2c7ca08237507e839b498f639987316309e3b843
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: tests/send_queue.rs

31ce2453c82fatagen2026-09-24 13:07 UTC1
mod support;
31ce2453c82fatagen2026-09-24 13:07 UTC2
96fdf90aacd6atagen2026-09-08 08:24 UTC3
use std::time::Duration;
96fdf90aacd6atagen2026-09-08 08:24 UTC4
96fdf90aacd6atagen2026-09-08 08:24 UTC5
use macltok::{
31ce2453c82fatagen2026-09-24 13:07 UTC6
    AttachmentUpload, ClientHandle, Engine, EngineConfig, ErrorKind, EventStream, MessageContent,
96fdf90aacd6atagen2026-09-08 08:24 UTC7
};
96fdf90aacd6atagen2026-09-08 08:24 UTC8
use matrix_sdk::{
96fdf90aacd6atagen2026-09-08 08:24 UTC9
    Client,
96fdf90aacd6atagen2026-09-08 08:24 UTC10
    ruma::{OwnedTransactionId, RoomId, api::client::sync::sync_events::v5, event_id, room_id},
96fdf90aacd6atagen2026-09-08 08:24 UTC11
    test_utils::mocks::MatrixMockServer,
96fdf90aacd6atagen2026-09-08 08:24 UTC12
};
96fdf90aacd6atagen2026-09-08 08:24 UTC13
96fdf90aacd6atagen2026-09-08 08:24 UTC14
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC15
async fn cancel_send_uses_transaction_id_from_public_timeline() {
96fdf90aacd6atagen2026-09-08 08:24 UTC16
    let (server, client, handle, mut events, running) = setup().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC17
    let room_id = room_id!("!queue-controls:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC18
    client.send_queue().set_enabled(false).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC19
96fdf90aacd6atagen2026-09-08 08:24 UTC20
    let transaction_id = queue_message(&handle, &mut events, room_id, "discard me").await;
96fdf90aacd6atagen2026-09-08 08:24 UTC21
    assert!(
96fdf90aacd6atagen2026-09-08 08:24 UTC22
        handle
96fdf90aacd6atagen2026-09-08 08:24 UTC23
            .pending_send_ids(room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC24
            .await
96fdf90aacd6atagen2026-09-08 08:24 UTC25
            .unwrap()
96fdf90aacd6atagen2026-09-08 08:24 UTC26
            .contains(&transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC27
    );
31ce2453c82fatagen2026-09-24 13:07 UTC28
    handle
96fdf90aacd6atagen2026-09-08 08:24 UTC29
        .cancel_send(room_id.to_owned(), transaction_id.clone())
96fdf90aacd6atagen2026-09-08 08:24 UTC30
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC31
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC32
96fdf90aacd6atagen2026-09-08 08:24 UTC33
    let (echoes, _) = client
96fdf90aacd6atagen2026-09-08 08:24 UTC34
        .get_room(room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC35
        .unwrap()
96fdf90aacd6atagen2026-09-08 08:24 UTC36
        .send_queue()
96fdf90aacd6atagen2026-09-08 08:24 UTC37
        .subscribe()
96fdf90aacd6atagen2026-09-08 08:24 UTC38
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC39
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC40
    assert!(
96fdf90aacd6atagen2026-09-08 08:24 UTC41
        !echoes
96fdf90aacd6atagen2026-09-08 08:24 UTC42
            .iter()
96fdf90aacd6atagen2026-09-08 08:24 UTC43
            .any(|echo| echo.transaction_id == transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC44
    );
96fdf90aacd6atagen2026-09-08 08:24 UTC45
31ce2453c82fatagen2026-09-24 13:07 UTC46
    let error = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC47
        .cancel_send(room_id.to_owned(), transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC48
        .await
31ce2453c82fatagen2026-09-24 13:07 UTC49
        .unwrap_err();
31ce2453c82fatagen2026-09-24 13:07 UTC50
    assert_eq!(error.kind, ErrorKind::Invalid);
96fdf90aacd6atagen2026-09-08 08:24 UTC51
31ce2453c82fatagen2026-09-24 13:07 UTC52
    support::shut_down(&handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC53
    drop(server);
96fdf90aacd6atagen2026-09-08 08:24 UTC54
}
96fdf90aacd6atagen2026-09-08 08:24 UTC55
96fdf90aacd6atagen2026-09-08 08:24 UTC56
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC57
async fn cancel_queued_attachment_by_pending_send_id() {
96fdf90aacd6atagen2026-09-08 08:24 UTC58
    let (server, client, handle, mut events, running) = setup().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC59
    let room_id = room_id!("!queue-controls:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC60
    client.send_queue().set_enabled(false).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC61
31ce2453c82fatagen2026-09-24 13:07 UTC62
    handle
31ce2453c82fatagen2026-09-24 13:07 UTC63
        .upload(AttachmentUpload::new(
31ce2453c82fatagen2026-09-24 13:07 UTC64
            room_id.to_owned(),
31ce2453c82fatagen2026-09-24 13:07 UTC65
            "note.txt",
31ce2453c82fatagen2026-09-24 13:07 UTC66
            "text/plain",
96fdf90aacd6atagen2026-09-08 08:24 UTC67
            b"attachment".to_vec(),
31ce2453c82fatagen2026-09-24 13:07 UTC68
        ))
96fdf90aacd6atagen2026-09-08 08:24 UTC69
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC70
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC71
96fdf90aacd6atagen2026-09-08 08:24 UTC72
    let pending = handle.pending_send_ids(room_id).await.unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC73
    assert_eq!(pending.len(), 1);
31ce2453c82fatagen2026-09-24 13:07 UTC74
    handle
96fdf90aacd6atagen2026-09-08 08:24 UTC75
        .cancel_send(room_id.to_owned(), pending[0].clone())
96fdf90aacd6atagen2026-09-08 08:24 UTC76
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC77
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC78
    assert!(handle.pending_send_ids(room_id).await.unwrap().is_empty());
96fdf90aacd6atagen2026-09-08 08:24 UTC79
31ce2453c82fatagen2026-09-24 13:07 UTC80
    support::shut_down(&handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC81
    drop(server);
96fdf90aacd6atagen2026-09-08 08:24 UTC82
}
96fdf90aacd6atagen2026-09-08 08:24 UTC83
96fdf90aacd6atagen2026-09-08 08:24 UTC84
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC85
async fn retry_send_wakes_paused_queue() {
96fdf90aacd6atagen2026-09-08 08:24 UTC86
    let (server, client, handle, mut events, running) = setup().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC87
    let room_id = room_id!("!queue-controls:localhost");
fa9114fcf75fatagen2026-09-24 12:51 UTC88
    client
fa9114fcf75fatagen2026-09-24 12:51 UTC89
        .get_room(room_id)
fa9114fcf75fatagen2026-09-24 12:51 UTC90
        .unwrap()
fa9114fcf75fatagen2026-09-24 12:51 UTC91
        .send_queue()
fa9114fcf75fatagen2026-09-24 12:51 UTC92
        .set_enabled(false);
96fdf90aacd6atagen2026-09-08 08:24 UTC93
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC94
        .mock_room_send()
96fdf90aacd6atagen2026-09-08 08:24 UTC95
        .body_matches_partial_json(serde_json::json!({ "body": "retry me" }))
96fdf90aacd6atagen2026-09-08 08:24 UTC96
        .ok(event_id!("$retried:localhost"))
96fdf90aacd6atagen2026-09-08 08:24 UTC97
        .expect(1)
96fdf90aacd6atagen2026-09-08 08:24 UTC98
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC99
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC100
96fdf90aacd6atagen2026-09-08 08:24 UTC101
    let transaction_id = queue_message(&handle, &mut events, room_id, "retry me").await;
31ce2453c82fatagen2026-09-24 13:07 UTC102
    handle
96fdf90aacd6atagen2026-09-08 08:24 UTC103
        .retry_send(room_id.to_owned(), transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC104
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC105
        .unwrap();
fa9114fcf75fatagen2026-09-24 12:51 UTC106
    assert!(client.get_room(room_id).unwrap().send_queue().is_enabled());
96fdf90aacd6atagen2026-09-08 08:24 UTC107
96fdf90aacd6atagen2026-09-08 08:24 UTC108
    tokio::time::timeout(Duration::from_secs(5), async {
96fdf90aacd6atagen2026-09-08 08:24 UTC109
        loop {
96fdf90aacd6atagen2026-09-08 08:24 UTC110
            let (echoes, _) = client
96fdf90aacd6atagen2026-09-08 08:24 UTC111
                .get_room(room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC112
                .unwrap()
96fdf90aacd6atagen2026-09-08 08:24 UTC113
                .send_queue()
96fdf90aacd6atagen2026-09-08 08:24 UTC114
                .subscribe()
96fdf90aacd6atagen2026-09-08 08:24 UTC115
                .await
96fdf90aacd6atagen2026-09-08 08:24 UTC116
                .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC117
            if echoes.is_empty() {
96fdf90aacd6atagen2026-09-08 08:24 UTC118
                break;
96fdf90aacd6atagen2026-09-08 08:24 UTC119
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC120
            tokio::task::yield_now().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC121
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC122
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC123
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC124
    .expect("retried message was not sent");
96fdf90aacd6atagen2026-09-08 08:24 UTC125
31ce2453c82fatagen2026-09-24 13:07 UTC126
    support::shut_down(&handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC127
    drop(server);
96fdf90aacd6atagen2026-09-08 08:24 UTC128
}
96fdf90aacd6atagen2026-09-08 08:24 UTC129
96fdf90aacd6atagen2026-09-08 08:24 UTC130
async fn setup() -> (
96fdf90aacd6atagen2026-09-08 08:24 UTC131
    MatrixMockServer,
96fdf90aacd6atagen2026-09-08 08:24 UTC132
    Client,
96fdf90aacd6atagen2026-09-08 08:24 UTC133
    ClientHandle,
96fdf90aacd6atagen2026-09-08 08:24 UTC134
    EventStream,
fe4133dbcd47atagen2026-09-26 09:05 UTC135
    tokio::task::JoinHandle<Result<macltok::Termination, macltok::EngineError>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC136
) {
96fdf90aacd6atagen2026-09-08 08:24 UTC137
    let server = MatrixMockServer::new().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC138
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC139
        .mock_sliding_sync()
96fdf90aacd6atagen2026-09-08 08:24 UTC140
        .ok(v5::Response::new("1".to_owned()))
96fdf90aacd6atagen2026-09-08 08:24 UTC141
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC142
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC143
    let client = server.client_builder().build().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC144
    let room_id = room_id!("!queue-controls:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC145
    server.mock_room_state_encryption().plain().mount().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC146
    server.sync_joined_room(&client, room_id).await;
31ce2453c82fatagen2026-09-24 13:07 UTC147
    let (engine, handle, mut events) = Engine::from_client(
96fdf90aacd6atagen2026-09-08 08:24 UTC148
        client.clone(),
96fdf90aacd6atagen2026-09-08 08:24 UTC149
        EngineConfig::default().with_initial_history_limit(0),
96fdf90aacd6atagen2026-09-08 08:24 UTC150
    )
96fdf90aacd6atagen2026-09-08 08:24 UTC151
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC152
    .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC153
    let running = tokio::spawn(engine.run());
31ce2453c82fatagen2026-09-24 13:07 UTC154
    let (opened, _) = tokio::join!(handle.open_room(room_id.to_owned()), async {
31ce2453c82fatagen2026-09-24 13:07 UTC155
        support::receive_until(&mut events, |event| {
31ce2453c82fatagen2026-09-24 13:07 UTC156
            matches!(event, macltok::Event::TimelineReset { .. })
31ce2453c82fatagen2026-09-24 13:07 UTC157
        })
96fdf90aacd6atagen2026-09-08 08:24 UTC158
        .await
31ce2453c82fatagen2026-09-24 13:07 UTC159
    });
31ce2453c82fatagen2026-09-24 13:07 UTC160
    opened.unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC161
    (server, client, handle, events, running)
96fdf90aacd6atagen2026-09-08 08:24 UTC162
}
96fdf90aacd6atagen2026-09-08 08:24 UTC163
31ce2453c82fatagen2026-09-24 13:07 UTC164
/// sends a message and waits for its local echo, since only the timeline reveals the transaction id
96fdf90aacd6atagen2026-09-08 08:24 UTC165
async fn queue_message(
96fdf90aacd6atagen2026-09-08 08:24 UTC166
    handle: &ClientHandle,
96fdf90aacd6atagen2026-09-08 08:24 UTC167
    events: &mut EventStream,
96fdf90aacd6atagen2026-09-08 08:24 UTC168
    room_id: &RoomId,
96fdf90aacd6atagen2026-09-08 08:24 UTC169
    body: &str,
96fdf90aacd6atagen2026-09-08 08:24 UTC170
) -> OwnedTransactionId {
31ce2453c82fatagen2026-09-24 13:07 UTC171
    let send = handle.send_message(room_id.to_owned().into(), MessageContent::text(body));
31ce2453c82fatagen2026-09-24 13:07 UTC172
    let wait_for_echo = async {
31ce2453c82fatagen2026-09-24 13:07 UTC173
        tokio::time::timeout(Duration::from_secs(5), async {
31ce2453c82fatagen2026-09-24 13:07 UTC174
            loop {
31ce2453c82fatagen2026-09-24 13:07 UTC175
                let event = events.recv().await.expect("event stream closed");
31ce2453c82fatagen2026-09-24 13:07 UTC176
                let transaction = support::event_messages(&event)
31ce2453c82fatagen2026-09-24 13:07 UTC177
                    .into_iter()
960ac0721079atagen2026-09-25 00:24 UTC178
                    .find(|event| {
960ac0721079atagen2026-09-25 00:24 UTC179
                        support::message(event).is_some_and(|message| message.body == body)
960ac0721079atagen2026-09-25 00:24 UTC180
                    })
960ac0721079atagen2026-09-25 00:24 UTC181
                    .and_then(|event| event.transaction_id.clone());
31ce2453c82fatagen2026-09-24 13:07 UTC182
                if let Some(transaction) = transaction {
31ce2453c82fatagen2026-09-24 13:07 UTC183
                    return transaction;
96fdf90aacd6atagen2026-09-08 08:24 UTC184
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC185
            }
31ce2453c82fatagen2026-09-24 13:07 UTC186
        })
96fdf90aacd6atagen2026-09-08 08:24 UTC187
        .await
31ce2453c82fatagen2026-09-24 13:07 UTC188
        .expect("local echo did not appear")
31ce2453c82fatagen2026-09-24 13:07 UTC189
    };
31ce2453c82fatagen2026-09-24 13:07 UTC190
    let (result, transaction_id) = tokio::join!(send, wait_for_echo);
31ce2453c82fatagen2026-09-24 13:07 UTC191
    result.unwrap();
31ce2453c82fatagen2026-09-24 13:07 UTC192
    transaction_id
96fdf90aacd6atagen2026-09-08 08:24 UTC193
}