atagen

macltok

public
Star0
Watch0
06c73391cbaec25f3bfaacf44d54a9ac657ec4e9
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git
tests/tier0.rsRust351 lines10.8 KB
1
mod support;
2
3
use macltok::{
4
    ClientHandle, CreateRoomOptions, Engine, EngineConfig, EngineError, ErrorKind, EventStream,
5
    RoomPreset, RoomVisibility,
6
};
7
use matrix_sdk::{
8
    ruma::{
9
        api::client::sync::sync_events::v5,
10
        events::{GlobalAccountDataEventType, RoomAccountDataEventType},
11
        room_id,
12
        serde::Raw,
13
        server_name, user_id,
14
    },
15
    test_utils::mocks::MatrixMockServer,
16
};
17
use matrix_sdk_test::{InvitedRoomBuilder, JoinedRoomBuilder};
18
use serde_json::json;
19
use tokio::task::JoinHandle;
20
use wiremock::{
21
    Mock, ResponseTemplate,
22
    matchers::{body_partial_json, method, path, path_regex, query_param},
23
};
24
25
#[tokio::test]
26
async fn joining_by_room_id_forwards_via_servers() {
27
    let room_id = room_id!("!join:localhost");
28
    let (server, handle, mut events, running) = start_engine().await;
29
    Mock::given(method("POST"))
30
        .and(path(format!("/_matrix/client/v3/join/{room_id}")))
31
        .and(query_param("via", "relay.example"))
32
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({ "room_id": room_id })))
33
        .expect(1)
34
        .mount(server.server())
35
        .await;
36
37
    let joined_room = handle
38
        .join_room(
39
            room_id.to_owned().into(),
40
            vec![server_name!("relay.example").to_owned()],
41
        )
42
        .await
43
        .unwrap();
44
    assert_eq!(joined_room, room_id);
45
    support::shut_down(&handle, &mut events, running).await;
46
}
47
48
#[tokio::test]
49
async fn leaving_then_forgetting_a_room_hits_the_expected_endpoints() {
50
    let room_id = room_id!("!leave:localhost");
51
    let (server, client) = configured_client().await;
52
    server.sync_joined_room(&client, room_id).await;
53
    server.mock_room_leave().ok(room_id).expect(1).mount().await;
54
    server.mock_room_forget().ok().expect(1).mount().await;
55
    let (handle, mut events, running) = run_client(client).await;
56
57
    handle.leave_room(room_id.to_owned()).await.unwrap();
58
    handle.forget_room(room_id.to_owned()).await.unwrap();
59
60
    support::shut_down(&handle, &mut events, running).await;
61
    drop(server);
62
}
63
64
#[tokio::test]
65
async fn accepting_and_rejecting_invites_use_the_expected_endpoints() {
66
    let accepted = room_id!("!accepted:localhost");
67
    let rejected = room_id!("!rejected:localhost");
68
    let (server, client) = configured_client().await;
69
    server
70
        .sync_room(&client, InvitedRoomBuilder::new(accepted))
71
        .await;
72
    server
73
        .sync_room(&client, InvitedRoomBuilder::new(rejected))
74
        .await;
75
    server.mock_room_join(accepted).ok().expect(1).mount().await;
76
    server
77
        .mock_room_leave()
78
        .ok(rejected)
79
        .expect(1)
80
        .mount()
81
        .await;
82
    let (handle, mut events, running) = run_client(client).await;
83
84
    handle.accept_invite(accepted.to_owned()).await.unwrap();
85
    handle.reject_invite(rejected.to_owned()).await.unwrap();
86
87
    support::shut_down(&handle, &mut events, running).await;
88
}
89
90
#[tokio::test]
91
async fn creating_a_room_forwards_options() {
92
    let (server, handle, mut events, running) = start_engine().await;
93
    Mock::given(method("POST"))
94
        .and(path("/_matrix/client/v3/createRoom"))
95
        .and(body_partial_json(json!({
96
            "name": "Planning",
97
            "topic": "Next release",
98
            "room_alias_name": "planning",
99
            "invite": ["@partner:localhost"],
100
            "visibility": "public",
101
            "preset": "public_chat"
102
        })))
103
        .respond_with(
104
            ResponseTemplate::new(200).set_body_json(json!({ "room_id": "!created:localhost" })),
105
        )
106
        .expect(1)
107
        .mount(server.server())
108
        .await;
109
110
    let created_room = handle
111
        .create_room(
112
            CreateRoomOptions::default()
113
                .with_name("Planning")
114
                .with_topic("Next release")
115
                .with_alias_localpart("planning")
116
                .with_invite(vec![user_id!("@partner:localhost").to_owned()])
117
                .with_visibility(RoomVisibility::Public)
118
                .with_preset(RoomPreset::PublicChat),
119
        )
120
        .await
121
        .unwrap();
122
    assert_eq!(created_room, room_id!("!created:localhost").to_owned());
123
    support::shut_down(&handle, &mut events, running).await;
124
}
125
126
#[tokio::test]
127
async fn creating_a_direct_room_invites_the_other_user() {
128
    let (server, handle, mut events, running) = start_engine().await;
129
    Mock::given(method("POST"))
130
        .and(path("/_matrix/client/v3/createRoom"))
131
        .and(body_partial_json(json!({
132
            "invite": ["@partner:localhost"],
133
            "is_direct": true,
134
            "preset": "trusted_private_chat"
135
        })))
136
        .respond_with(
137
            ResponseTemplate::new(200).set_body_json(json!({ "room_id": "!direct:localhost" })),
138
        )
139
        .expect(1)
140
        .mount(server.server())
141
        .await;
142
    Mock::given(method("GET"))
143
        .and(path_regex(
144
            r"^/_matrix/client/v3/user/.*/account_data/m\.direct$",
145
        ))
146
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({})))
147
        .expect(1)
148
        .mount(server.server())
149
        .await;
150
    Mock::given(method("PUT"))
151
        .and(path_regex(
152
            r"^/_matrix/client/v3/user/.*/account_data/m\.direct$",
153
        ))
154
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({})))
155
        .expect(1)
156
        .mount(server.server())
157
        .await;
158
159
    let direct_room = handle
160
        .create_direct(user_id!("@partner:localhost").to_owned())
161
        .await
162
        .unwrap();
163
    assert_eq!(direct_room, room_id!("!direct:localhost").to_owned());
164
    support::shut_down(&handle, &mut events, running).await;
165
}
166
167
#[tokio::test]
168
async fn unknown_rooms_fail_membership_commands_with_room_unknown() {
169
    let (server, handle, mut events, running) = start_engine().await;
170
    let unknown = room_id!("!unknown:localhost");
171
172
    assert_eq!(
173
        handle
174
            .leave_room(unknown.to_owned())
175
            .await
176
            .unwrap_err()
177
            .kind,
178
        ErrorKind::RoomUnknown
179
    );
180
    assert_eq!(
181
        handle
182
            .forget_room(unknown.to_owned())
183
            .await
184
            .unwrap_err()
185
            .kind,
186
        ErrorKind::RoomUnknown
187
    );
188
    assert_eq!(
189
        handle
190
            .accept_invite(unknown.to_owned())
191
            .await
192
            .unwrap_err()
193
            .kind,
194
        ErrorKind::RoomUnknown
195
    );
196
    assert_eq!(
197
        handle
198
            .reject_invite(unknown.to_owned())
199
            .await
200
            .unwrap_err()
201
            .kind,
202
        ErrorKind::RoomUnknown
203
    );
204
205
    support::shut_down(&handle, &mut events, running).await;
206
    drop(server);
207
}
208
209
#[tokio::test]
210
async fn account_data_reads_synced_values_and_writes_raw_content() {
211
    let room_id = room_id!("!account-data:localhost");
212
    let (server, client) = configured_client().await;
213
    server
214
        .sync_room(
215
            &client,
216
            JoinedRoomBuilder::new(room_id).add_account_data(
217
                Raw::new(&json!({ "type": "m.fully_read", "content": { "event_id": "$seen:localhost" } }))
218
                    .unwrap()
219
                    .cast_unchecked(),
220
            ),
221
        )
222
        .await;
223
    server
224
        .mock_sync()
225
        .ok_and_run(&client, |builder| {
226
            builder.add_custom_global_account_data(json!({
227
                "type": "com.example.preferences",
228
                "content": { "theme": "dark" }
229
            }));
230
        })
231
        .await;
232
    let (engine, handle, mut events) = Engine::from_client(client, EngineConfig::default())
233
        .await
234
        .unwrap();
235
    let running = tokio::spawn(engine.run());
236
    let global_type = GlobalAccountDataEventType::from("com.example.preferences".to_owned());
237
    let room_type = RoomAccountDataEventType::FullyRead;
238
239
    let global = handle
240
        .global_account_data(global_type.clone())
241
        .await
242
        .unwrap()
243
        .unwrap();
244
    assert_eq!(
245
        global.deserialize_as::<serde_json::Value>().unwrap()["theme"],
246
        "dark"
247
    );
248
    let room = handle
249
        .room_account_data(room_id, room_type.clone())
250
        .await
251
        .unwrap()
252
        .unwrap();
253
    assert_eq!(
254
        room.deserialize_as::<serde_json::Value>().unwrap()["content"]["event_id"],
255
        "$seen:localhost"
256
    );
257
    assert_eq!(
258
        handle
259
            .room_account_data(room_id!("!missing:localhost"), room_type.clone())
260
            .await
261
            .unwrap_err()
262
            .kind,
263
        ErrorKind::RoomUnknown
264
    );
265
266
    Mock::given(method("PUT"))
267
        .and(path(
268
            "/_matrix/client/v3/user/@example:localhost/account_data/com.example.preferences",
269
        ))
270
        .and(body_partial_json(json!({ "theme": "light" })))
271
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({})))
272
        .expect(1)
273
        .mount(server.server())
274
        .await;
275
    server
276
        .mock_set_room_account_data(room_type.clone())
277
        .ok()
278
        .expect(1)
279
        .mount()
280
        .await;
281
    handle
282
        .set_global_account_data(
283
            global_type,
284
            Raw::new(&json!({ "theme": "light" }))
285
                .unwrap()
286
                .cast_unchecked(),
287
        )
288
        .await
289
        .unwrap();
290
    handle
291
        .set_room_account_data(
292
            room_id.to_owned(),
293
            room_type,
294
            Raw::new(&json!({ "event_id": "$later:localhost" }))
295
                .unwrap()
296
                .cast_unchecked(),
297
        )
298
        .await
299
        .unwrap();
300
    assert_eq!(
301
        handle
302
            .set_room_account_data(
303
                room_id!("!missing:localhost").to_owned(),
304
                RoomAccountDataEventType::FullyRead,
305
                Raw::new(&json!({ "event_id": "$later:localhost" }))
306
                    .unwrap()
307
                    .cast_unchecked()
308
            )
309
            .await
310
            .unwrap_err()
311
            .kind,
312
        ErrorKind::RoomUnknown
313
    );
314
    support::shut_down(&handle, &mut events, running).await;
315
}
316
317
async fn configured_client() -> (MatrixMockServer, matrix_sdk::Client) {
318
    let server = MatrixMockServer::new().await;
319
    server
320
        .mock_sliding_sync()
321
        .ok(v5::Response::new("1".to_owned()))
322
        .mount()
323
        .await;
324
    let client = server.client_builder().build().await;
325
    server.mock_room_state_encryption().plain().mount().await;
326
    (server, client)
327
}
328
329
async fn start_engine() -> (
330
    MatrixMockServer,
331
    ClientHandle,
332
    EventStream,
333
    JoinHandle<Result<macltok::Termination, EngineError>>,
334
) {
335
    let (server, client) = configured_client().await;
336
    let (handle, events, running) = run_client(client).await;
337
    (server, handle, events, running)
338
}
339
340
async fn run_client(
341
    client: matrix_sdk::Client,
342
) -> (
343
    ClientHandle,
344
    EventStream,
345
    JoinHandle<Result<macltok::Termination, EngineError>>,
346
) {
347
    let config = EngineConfig::default().with_initial_history_limit(0);
348
    let (engine, handle, events) = Engine::from_client(client, config).await.unwrap();
349
    let running = tokio::spawn(engine.run());
350
    (handle, events, running)
351
}