atagen

macltok

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

Blame: tests/state.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
fe4133dbcd47atagen2026-09-26 09:05 UTC5
use macltok::{
17e042fbc331atagen2026-10-08 12:39 UTC6
    ConnectionState, Engine, EngineConfig, EngineError, Event, PackUsage, Retain, RoomMembership,
17e042fbc331atagen2026-10-08 12:39 UTC7
    Termination,
fe4133dbcd47atagen2026-09-26 09:05 UTC8
};
96fdf90aacd6atagen2026-09-08 08:24 UTC9
use matrix_sdk::{
17e042fbc331atagen2026-10-08 12:39 UTC10
    ruma::{api::client::sync::sync_events::v5, events::AnySyncStateEvent, room_id, serde::Raw},
96fdf90aacd6atagen2026-09-08 08:24 UTC11
    test_utils::mocks::MatrixMockServer,
96fdf90aacd6atagen2026-09-08 08:24 UTC12
};
17e042fbc331atagen2026-10-08 12:39 UTC13
use matrix_sdk_test::JoinedRoomBuilder;
17e042fbc331atagen2026-10-08 12:39 UTC14
use serde_json::json;
96fdf90aacd6atagen2026-09-08 08:24 UTC15
use tokio::sync::watch;
96fdf90aacd6atagen2026-09-08 08:24 UTC16
96fdf90aacd6atagen2026-09-08 08:24 UTC17
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC18
async fn rooms_changed_invalidates_room_summaries() {
96fdf90aacd6atagen2026-09-08 08:24 UTC19
    let server = MatrixMockServer::new().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC20
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC21
        .mock_sliding_sync()
96fdf90aacd6atagen2026-09-08 08:24 UTC22
        .ok(v5::Response::new("1".to_owned()))
96fdf90aacd6atagen2026-09-08 08:24 UTC23
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC24
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC25
    let client = server.client_builder().build().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC26
    let room_id = room_id!("!state:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC27
    server.mock_room_state_encryption().plain().mount().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC28
    server.sync_joined_room(&client, room_id).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC29
    let config = EngineConfig::default().with_initial_history_limit(0);
96fdf90aacd6atagen2026-09-08 08:24 UTC30
    let (engine, handle, mut events) = Engine::from_client(client, config).await.unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC31
    let running = tokio::spawn(engine.run());
96fdf90aacd6atagen2026-09-08 08:24 UTC32
31ce2453c82fatagen2026-09-24 13:07 UTC33
    support::receive_until(&mut events, |event| matches!(event, Event::RoomsChanged)).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC34
    let rooms = handle.rooms().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC35
    let summary = rooms
96fdf90aacd6atagen2026-09-08 08:24 UTC36
        .iter()
96fdf90aacd6atagen2026-09-08 08:24 UTC37
        .find(|summary| summary.room_id == room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC38
        .expect("synced room was absent from the room summaries");
96fdf90aacd6atagen2026-09-08 08:24 UTC39
    assert_eq!(summary.membership, RoomMembership::Joined);
96fdf90aacd6atagen2026-09-08 08:24 UTC40
    assert!(!summary.name.is_empty());
96fdf90aacd6atagen2026-09-08 08:24 UTC41
31ce2453c82fatagen2026-09-24 13:07 UTC42
    support::shut_down(&handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC43
}
96fdf90aacd6atagen2026-09-08 08:24 UTC44
96fdf90aacd6atagen2026-09-08 08:24 UTC45
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC46
async fn connection_watch_tracks_the_engine_lifecycle() {
96fdf90aacd6atagen2026-09-08 08:24 UTC47
    let server = MatrixMockServer::new().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC48
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC49
        .mock_sliding_sync()
96fdf90aacd6atagen2026-09-08 08:24 UTC50
        .ok(v5::Response::new("1".to_owned()))
96fdf90aacd6atagen2026-09-08 08:24 UTC51
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC52
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC53
    let client = server.client_builder().build().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC54
    let config = EngineConfig::default().with_initial_history_limit(0);
96fdf90aacd6atagen2026-09-08 08:24 UTC55
    let (engine, handle, mut events) = Engine::from_client(client, config).await.unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC56
    let mut connection = handle.connection_state();
96fdf90aacd6atagen2026-09-08 08:24 UTC57
    let connection_peer = connection.clone();
96fdf90aacd6atagen2026-09-08 08:24 UTC58
    assert_eq!(*connection.borrow(), ConnectionState::Idle);
96fdf90aacd6atagen2026-09-08 08:24 UTC59
    assert_eq!(*connection_peer.borrow(), ConnectionState::Idle);
96fdf90aacd6atagen2026-09-08 08:24 UTC60
96fdf90aacd6atagen2026-09-08 08:24 UTC61
    let running = tokio::spawn(engine.run());
31ce2453c82fatagen2026-09-24 13:07 UTC62
    support::receive_until(&mut events, |event| {
96fdf90aacd6atagen2026-09-08 08:24 UTC63
        matches!(event, Event::ConnectionChanged(ConnectionState::Connecting))
96fdf90aacd6atagen2026-09-08 08:24 UTC64
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC65
    .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC66
    assert_ne!(*connection.borrow(), ConnectionState::Idle);
31ce2453c82fatagen2026-09-24 13:07 UTC67
    support::receive_until(&mut events, |event| {
96fdf90aacd6atagen2026-09-08 08:24 UTC68
        matches!(event, Event::ConnectionChanged(ConnectionState::Online))
96fdf90aacd6atagen2026-09-08 08:24 UTC69
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC70
    .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC71
    wait_for_connection(&mut connection, ConnectionState::Online).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC72
    assert_eq!(*connection_peer.borrow(), ConnectionState::Online);
96fdf90aacd6atagen2026-09-08 08:24 UTC73
31ce2453c82fatagen2026-09-24 13:07 UTC74
    support::shut_down(&handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC75
    wait_for_connection(&mut connection, ConnectionState::Stopped).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC76
    assert_eq!(*connection_peer.borrow(), ConnectionState::Stopped);
96fdf90aacd6atagen2026-09-08 08:24 UTC77
}
96fdf90aacd6atagen2026-09-08 08:24 UTC78
96fdf90aacd6atagen2026-09-08 08:24 UTC79
#[tokio::test]
fa9114fcf75fatagen2026-09-24 12:51 UTC80
async fn soft_logout_says_so_and_stops_the_engine() {
fa9114fcf75fatagen2026-09-24 12:51 UTC81
    let server = MatrixMockServer::new().await;
fa9114fcf75fatagen2026-09-24 12:51 UTC82
    server
fa9114fcf75fatagen2026-09-24 12:51 UTC83
        .mock_sliding_sync()
fa9114fcf75fatagen2026-09-24 12:51 UTC84
        .error_unknown_token(true)
fa9114fcf75fatagen2026-09-24 12:51 UTC85
        .mount()
fa9114fcf75fatagen2026-09-24 12:51 UTC86
        .await;
fa9114fcf75fatagen2026-09-24 12:51 UTC87
    let client = server.client_builder().build().await;
fa9114fcf75fatagen2026-09-24 12:51 UTC88
    let (engine, _handle, mut events) = Engine::from_client(
fa9114fcf75fatagen2026-09-24 12:51 UTC89
        client,
fa9114fcf75fatagen2026-09-24 12:51 UTC90
        EngineConfig::default().with_initial_history_limit(0),
fa9114fcf75fatagen2026-09-24 12:51 UTC91
    )
fa9114fcf75fatagen2026-09-24 12:51 UTC92
    .await
fa9114fcf75fatagen2026-09-24 12:51 UTC93
    .unwrap();
fa9114fcf75fatagen2026-09-24 12:51 UTC94
    let running = tokio::spawn(engine.run());
31ce2453c82fatagen2026-09-24 13:07 UTC95
    support::receive_until(&mut events, |event| {
7c26fad34822atagen2026-09-26 09:41 UTC96
        matches!(
7c26fad34822atagen2026-09-26 09:41 UTC97
            event,
7c26fad34822atagen2026-09-26 09:41 UTC98
            Event::SessionAccessRejected {
7c26fad34822atagen2026-09-26 09:41 UTC99
                soft_logout: Some(_)
7c26fad34822atagen2026-09-26 09:41 UTC100
            }
7c26fad34822atagen2026-09-26 09:41 UTC101
        )
fa9114fcf75fatagen2026-09-24 12:51 UTC102
    })
fa9114fcf75fatagen2026-09-24 12:51 UTC103
    .await;
31ce2453c82fatagen2026-09-24 13:07 UTC104
    support::receive_until(&mut events, |event| matches!(event, Event::Stopped)).await;
fe4133dbcd47atagen2026-09-26 09:05 UTC105
    let termination = running.await.unwrap().unwrap();
fe4133dbcd47atagen2026-09-26 09:05 UTC106
    assert!(matches!(termination, Termination::SoftLoggedOut { .. }));
fe4133dbcd47atagen2026-09-26 09:05 UTC107
    assert_eq!(termination.retain(), Retain::Store);
fa9114fcf75fatagen2026-09-24 12:51 UTC108
}
fa9114fcf75fatagen2026-09-24 12:51 UTC109
fa9114fcf75fatagen2026-09-24 12:51 UTC110
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC111
async fn closing_the_event_stream_stops_an_idle_engine() {
96fdf90aacd6atagen2026-09-08 08:24 UTC112
    let server = MatrixMockServer::new().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC113
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC114
        .mock_sliding_sync()
96fdf90aacd6atagen2026-09-08 08:24 UTC115
        .ok(v5::Response::new("1".to_owned()))
96fdf90aacd6atagen2026-09-08 08:24 UTC116
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC117
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC118
    let client = server.client_builder().build().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC119
    let (engine, handle, mut events) = Engine::from_client(
96fdf90aacd6atagen2026-09-08 08:24 UTC120
        client,
96fdf90aacd6atagen2026-09-08 08:24 UTC121
        EngineConfig::default().with_initial_history_limit(0),
96fdf90aacd6atagen2026-09-08 08:24 UTC122
    )
96fdf90aacd6atagen2026-09-08 08:24 UTC123
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC124
    .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC125
    let running = tokio::spawn(engine.run());
31ce2453c82fatagen2026-09-24 13:07 UTC126
    support::receive_until(&mut events, |event| {
96fdf90aacd6atagen2026-09-08 08:24 UTC127
        matches!(event, Event::ConnectionChanged(ConnectionState::Online))
96fdf90aacd6atagen2026-09-08 08:24 UTC128
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC129
    .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC130
    drop(events);
96fdf90aacd6atagen2026-09-08 08:24 UTC131
    let result = tokio::time::timeout(Duration::from_secs(2), running)
96fdf90aacd6atagen2026-09-08 08:24 UTC132
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC133
        .expect("engine did not stop after its event receiver closed")
96fdf90aacd6atagen2026-09-08 08:24 UTC134
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC135
    assert!(matches!(result, Err(EngineError::EventReceiverClosed)));
96fdf90aacd6atagen2026-09-08 08:24 UTC136
    drop(handle);
96fdf90aacd6atagen2026-09-08 08:24 UTC137
}
96fdf90aacd6atagen2026-09-08 08:24 UTC138
96fdf90aacd6atagen2026-09-08 08:24 UTC139
async fn wait_for_connection(
96fdf90aacd6atagen2026-09-08 08:24 UTC140
    connection: &mut watch::Receiver<ConnectionState>,
96fdf90aacd6atagen2026-09-08 08:24 UTC141
    expected: ConnectionState,
96fdf90aacd6atagen2026-09-08 08:24 UTC142
) {
96fdf90aacd6atagen2026-09-08 08:24 UTC143
    tokio::time::timeout(Duration::from_secs(2), async {
96fdf90aacd6atagen2026-09-08 08:24 UTC144
        loop {
96fdf90aacd6atagen2026-09-08 08:24 UTC145
            if *connection.borrow_and_update() == expected {
96fdf90aacd6atagen2026-09-08 08:24 UTC146
                return;
96fdf90aacd6atagen2026-09-08 08:24 UTC147
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC148
            connection
96fdf90aacd6atagen2026-09-08 08:24 UTC149
                .changed()
96fdf90aacd6atagen2026-09-08 08:24 UTC150
                .await
96fdf90aacd6atagen2026-09-08 08:24 UTC151
                .expect("connection watch closed before the expected state");
96fdf90aacd6atagen2026-09-08 08:24 UTC152
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC153
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC154
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC155
    .expect("expected connection state did not arrive");
96fdf90aacd6atagen2026-09-08 08:24 UTC156
}
17e042fbc331atagen2026-10-08 12:39 UTC157
17e042fbc331atagen2026-10-08 12:39 UTC158
#[tokio::test]
17e042fbc331atagen2026-10-08 12:39 UTC159
async fn image_packs_follow_room_state_and_account_data() {
17e042fbc331atagen2026-10-08 12:39 UTC160
    let server = MatrixMockServer::new().await;
17e042fbc331atagen2026-10-08 12:39 UTC161
    server
17e042fbc331atagen2026-10-08 12:39 UTC162
        .mock_sliding_sync()
17e042fbc331atagen2026-10-08 12:39 UTC163
        .ok(v5::Response::new("1".to_owned()))
17e042fbc331atagen2026-10-08 12:39 UTC164
        .mount()
17e042fbc331atagen2026-10-08 12:39 UTC165
        .await;
17e042fbc331atagen2026-10-08 12:39 UTC166
    let client = server.client_builder().build().await;
17e042fbc331atagen2026-10-08 12:39 UTC167
    let room_id = room_id!("!packs:localhost");
17e042fbc331atagen2026-10-08 12:39 UTC168
    server.mock_room_state_encryption().plain().mount().await;
17e042fbc331atagen2026-10-08 12:39 UTC169
    server.sync_joined_room(&client, room_id).await;
17e042fbc331atagen2026-10-08 12:39 UTC170
    let config = EngineConfig::default().with_initial_history_limit(0);
17e042fbc331atagen2026-10-08 12:39 UTC171
    let (engine, handle, mut events) = Engine::from_client(client.clone(), config).await.unwrap();
17e042fbc331atagen2026-10-08 12:39 UTC172
    let running = tokio::spawn(engine.run());
17e042fbc331atagen2026-10-08 12:39 UTC173
17e042fbc331atagen2026-10-08 12:39 UTC174
    let pack: Raw<AnySyncStateEvent> = serde_json::from_value(json!({
17e042fbc331atagen2026-10-08 12:39 UTC175
        "type": "im.ponies.room_emotes",
17e042fbc331atagen2026-10-08 12:39 UTC176
        "state_key": "cats",
17e042fbc331atagen2026-10-08 12:39 UTC177
        "event_id": "$pack",
17e042fbc331atagen2026-10-08 12:39 UTC178
        "sender": "@example:localhost",
17e042fbc331atagen2026-10-08 12:39 UTC179
        "origin_server_ts": 1,
17e042fbc331atagen2026-10-08 12:39 UTC180
        "content": {
17e042fbc331atagen2026-10-08 12:39 UTC181
            "pack": { "display_name": "cats", "usage": ["emoticon"] },
17e042fbc331atagen2026-10-08 12:39 UTC182
            "images": {
17e042fbc331atagen2026-10-08 12:39 UTC183
                "blep": { "url": "mxc://localhost/blep" },
17e042fbc331atagen2026-10-08 12:39 UTC184
                "broken": { "url": "not an mxc" },
17e042fbc331atagen2026-10-08 12:39 UTC185
                "sticker": { "url": "mxc://localhost/sticker", "usage": ["sticker"] },
17e042fbc331atagen2026-10-08 12:39 UTC186
            },
17e042fbc331atagen2026-10-08 12:39 UTC187
        },
17e042fbc331atagen2026-10-08 12:39 UTC188
    }))
17e042fbc331atagen2026-10-08 12:39 UTC189
    .unwrap();
17e042fbc331atagen2026-10-08 12:39 UTC190
    server
17e042fbc331atagen2026-10-08 12:39 UTC191
        .mock_sync()
17e042fbc331atagen2026-10-08 12:39 UTC192
        .ok_and_run(&client, |builder| {
17e042fbc331atagen2026-10-08 12:39 UTC193
            builder.add_joined_room(JoinedRoomBuilder::new(room_id).add_state_event(pack));
17e042fbc331atagen2026-10-08 12:39 UTC194
            builder.add_custom_global_account_data(json!({
17e042fbc331atagen2026-10-08 12:39 UTC195
                "type": "im.ponies.emote_rooms",
17e042fbc331atagen2026-10-08 12:39 UTC196
                "content": { "rooms": { "!packs:localhost": { "cats": {} } } },
17e042fbc331atagen2026-10-08 12:39 UTC197
            }));
17e042fbc331atagen2026-10-08 12:39 UTC198
        })
17e042fbc331atagen2026-10-08 12:39 UTC199
        .await;
17e042fbc331atagen2026-10-08 12:39 UTC200
    support::receive_until(&mut events, |event| {
17e042fbc331atagen2026-10-08 12:39 UTC201
        matches!(event, Event::ImagePacksChanged)
17e042fbc331atagen2026-10-08 12:39 UTC202
    })
17e042fbc331atagen2026-10-08 12:39 UTC203
    .await;
17e042fbc331atagen2026-10-08 12:39 UTC204
17e042fbc331atagen2026-10-08 12:39 UTC205
    let packs = handle.image_packs().await.unwrap();
17e042fbc331atagen2026-10-08 12:39 UTC206
    let offered = packs.for_room(Some(room_id));
17e042fbc331atagen2026-10-08 12:39 UTC207
    assert_eq!(offered.len(), 1, "an enabled room's pack was offered twice");
17e042fbc331atagen2026-10-08 12:39 UTC208
    let pack = offered[0];
17e042fbc331atagen2026-10-08 12:39 UTC209
    assert_eq!(pack.id, "room:!packs:localhost:cats");
17e042fbc331atagen2026-10-08 12:39 UTC210
    assert_eq!(packs.global, vec![pack.clone()]);
17e042fbc331atagen2026-10-08 12:39 UTC211
    let images: Vec<_> = pack
17e042fbc331atagen2026-10-08 12:39 UTC212
        .images
17e042fbc331atagen2026-10-08 12:39 UTC213
        .iter()
17e042fbc331atagen2026-10-08 12:39 UTC214
        .map(|image| {
17e042fbc331atagen2026-10-08 12:39 UTC215
            (
17e042fbc331atagen2026-10-08 12:39 UTC216
                image.shortcode.as_str(),
17e042fbc331atagen2026-10-08 12:39 UTC217
                image.reaction_key.as_str(),
17e042fbc331atagen2026-10-08 12:39 UTC218
                image.usage.clone(),
17e042fbc331atagen2026-10-08 12:39 UTC219
            )
17e042fbc331atagen2026-10-08 12:39 UTC220
        })
17e042fbc331atagen2026-10-08 12:39 UTC221
        .collect();
17e042fbc331atagen2026-10-08 12:39 UTC222
    assert_eq!(
17e042fbc331atagen2026-10-08 12:39 UTC223
        images,
17e042fbc331atagen2026-10-08 12:39 UTC224
        [
17e042fbc331atagen2026-10-08 12:39 UTC225
            ("blep", "mxc://localhost/blep", vec![PackUsage::Emoticon]),
17e042fbc331atagen2026-10-08 12:39 UTC226
            (
17e042fbc331atagen2026-10-08 12:39 UTC227
                "sticker",
17e042fbc331atagen2026-10-08 12:39 UTC228
                "mxc://localhost/sticker",
17e042fbc331atagen2026-10-08 12:39 UTC229
                vec![PackUsage::Sticker]
17e042fbc331atagen2026-10-08 12:39 UTC230
            ),
17e042fbc331atagen2026-10-08 12:39 UTC231
        ]
17e042fbc331atagen2026-10-08 12:39 UTC232
    );
17e042fbc331atagen2026-10-08 12:39 UTC233
17e042fbc331atagen2026-10-08 12:39 UTC234
    support::shut_down(&handle, &mut events, running).await;
17e042fbc331atagen2026-10-08 12:39 UTC235
}