atagen

macltok

public
Star0
Watch0
6a5963d5bd6374776bde92c39bea7d2cceceee1d
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git
tests/send_queue.rsRust193 lines5.7 KB
1
mod support;
2
3
use std::time::Duration;
4
5
use macltok::{
6
    AttachmentUpload, ClientHandle, Engine, EngineConfig, ErrorKind, EventStream, MessageContent,
7
};
8
use matrix_sdk::{
9
    Client,
10
    ruma::{OwnedTransactionId, RoomId, api::client::sync::sync_events::v5, event_id, room_id},
11
    test_utils::mocks::MatrixMockServer,
12
};
13
14
#[tokio::test]
15
async fn cancel_send_uses_transaction_id_from_public_timeline() {
16
    let (server, client, handle, mut events, running) = setup().await;
17
    let room_id = room_id!("!queue-controls:localhost");
18
    client.send_queue().set_enabled(false).await;
19
20
    let transaction_id = queue_message(&handle, &mut events, room_id, "discard me").await;
21
    assert!(
22
        handle
23
            .pending_send_ids(room_id)
24
            .await
25
            .unwrap()
26
            .contains(&transaction_id)
27
    );
28
    handle
29
        .cancel_send(room_id.to_owned(), transaction_id.clone())
30
        .await
31
        .unwrap();
32
33
    let (echoes, _) = client
34
        .get_room(room_id)
35
        .unwrap()
36
        .send_queue()
37
        .subscribe()
38
        .await
39
        .unwrap();
40
    assert!(
41
        !echoes
42
            .iter()
43
            .any(|echo| echo.transaction_id == transaction_id)
44
    );
45
46
    let error = handle
47
        .cancel_send(room_id.to_owned(), transaction_id)
48
        .await
49
        .unwrap_err();
50
    assert_eq!(error.kind, ErrorKind::Invalid);
51
52
    support::shut_down(&handle, &mut events, running).await;
53
    drop(server);
54
}
55
56
#[tokio::test]
57
async fn cancel_queued_attachment_by_pending_send_id() {
58
    let (server, client, handle, mut events, running) = setup().await;
59
    let room_id = room_id!("!queue-controls:localhost");
60
    client.send_queue().set_enabled(false).await;
61
62
    handle
63
        .upload(AttachmentUpload::new(
64
            room_id.to_owned(),
65
            "note.txt",
66
            "text/plain",
67
            b"attachment".to_vec(),
68
        ))
69
        .await
70
        .unwrap();
71
72
    let pending = handle.pending_send_ids(room_id).await.unwrap();
73
    assert_eq!(pending.len(), 1);
74
    handle
75
        .cancel_send(room_id.to_owned(), pending[0].clone())
76
        .await
77
        .unwrap();
78
    assert!(handle.pending_send_ids(room_id).await.unwrap().is_empty());
79
80
    support::shut_down(&handle, &mut events, running).await;
81
    drop(server);
82
}
83
84
#[tokio::test]
85
async fn retry_send_wakes_paused_queue() {
86
    let (server, client, handle, mut events, running) = setup().await;
87
    let room_id = room_id!("!queue-controls:localhost");
88
    client
89
        .get_room(room_id)
90
        .unwrap()
91
        .send_queue()
92
        .set_enabled(false);
93
    server
94
        .mock_room_send()
95
        .body_matches_partial_json(serde_json::json!({ "body": "retry me" }))
96
        .ok(event_id!("$retried:localhost"))
97
        .expect(1)
98
        .mount()
99
        .await;
100
101
    let transaction_id = queue_message(&handle, &mut events, room_id, "retry me").await;
102
    handle
103
        .retry_send(room_id.to_owned(), transaction_id)
104
        .await
105
        .unwrap();
106
    assert!(client.get_room(room_id).unwrap().send_queue().is_enabled());
107
108
    tokio::time::timeout(Duration::from_secs(5), async {
109
        loop {
110
            let (echoes, _) = client
111
                .get_room(room_id)
112
                .unwrap()
113
                .send_queue()
114
                .subscribe()
115
                .await
116
                .unwrap();
117
            if echoes.is_empty() {
118
                break;
119
            }
120
            tokio::task::yield_now().await;
121
        }
122
    })
123
    .await
124
    .expect("retried message was not sent");
125
126
    support::shut_down(&handle, &mut events, running).await;
127
    drop(server);
128
}
129
130
async fn setup() -> (
131
    MatrixMockServer,
132
    Client,
133
    ClientHandle,
134
    EventStream,
135
    tokio::task::JoinHandle<Result<macltok::Termination, macltok::EngineError>>,
136
) {
137
    let server = MatrixMockServer::new().await;
138
    server
139
        .mock_sliding_sync()
140
        .ok(v5::Response::new("1".to_owned()))
141
        .mount()
142
        .await;
143
    let client = server.client_builder().build().await;
144
    let room_id = room_id!("!queue-controls:localhost");
145
    server.mock_room_state_encryption().plain().mount().await;
146
    server.sync_joined_room(&client, room_id).await;
147
    let (engine, handle, mut events) = Engine::from_client(
148
        client.clone(),
149
        EngineConfig::default().with_initial_history_limit(0),
150
    )
151
    .await
152
    .unwrap();
153
    let running = tokio::spawn(engine.run());
154
    let (opened, _) = tokio::join!(handle.open_room(room_id.to_owned()), async {
155
        support::receive_until(&mut events, |event| {
156
            matches!(event, macltok::Event::TimelineReset { .. })
157
        })
158
        .await
159
    });
160
    opened.unwrap();
161
    (server, client, handle, events, running)
162
}
163
164
/// sends a message and waits for its local echo, since only the timeline reveals the transaction id
165
async fn queue_message(
166
    handle: &ClientHandle,
167
    events: &mut EventStream,
168
    room_id: &RoomId,
169
    body: &str,
170
) -> OwnedTransactionId {
171
    let send = handle.send_message(room_id.to_owned().into(), MessageContent::text(body));
172
    let wait_for_echo = async {
173
        tokio::time::timeout(Duration::from_secs(5), async {
174
            loop {
175
                let event = events.recv().await.expect("event stream closed");
176
                let transaction = support::event_messages(&event)
177
                    .into_iter()
178
                    .find(|event| {
179
                        support::message(event).is_some_and(|message| message.body == body)
180
                    })
181
                    .and_then(|event| event.transaction_id.clone());
182
                if let Some(transaction) = transaction {
183
                    return transaction;
184
                }
185
            }
186
        })
187
        .await
188
        .expect("local echo did not appear")
189
    };
190
    let (result, transaction_id) = tokio::join!(send, wait_for_echo);
191
    result.unwrap();
192
    transaction_id
193
}