atagen

macltok

public
Star0
Watch0
1fe480c16a3c6db3270dce9e11f0afe67ebc17fc
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git
tests/state.rsRust144 lines5.0 KB
1
mod support;
2
3
use std::time::Duration;
4
5
use macltok::{ConnectionState, Engine, EngineConfig, EngineError, Event, RoomMembership};
6
use matrix_sdk::{
7
    ruma::{api::client::sync::sync_events::v5, room_id},
8
    test_utils::mocks::MatrixMockServer,
9
};
10
use tokio::sync::watch;
11
12
#[tokio::test]
13
async fn rooms_changed_invalidates_room_summaries() {
14
    let server = MatrixMockServer::new().await;
15
    server
16
        .mock_sliding_sync()
17
        .ok(v5::Response::new("1".to_owned()))
18
        .mount()
19
        .await;
20
    let client = server.client_builder().build().await;
21
    let room_id = room_id!("!state:localhost");
22
    server.mock_room_state_encryption().plain().mount().await;
23
    server.sync_joined_room(&client, room_id).await;
24
    let config = EngineConfig::default().with_initial_history_limit(0);
25
    let (engine, handle, mut events) = Engine::from_client(client, config).await.unwrap();
26
    let running = tokio::spawn(engine.run());
27
28
    support::receive_until(&mut events, |event| matches!(event, Event::RoomsChanged)).await;
29
    let rooms = handle.rooms().await;
30
    let summary = rooms
31
        .iter()
32
        .find(|summary| summary.room_id == room_id)
33
        .expect("synced room was absent from the room summaries");
34
    assert_eq!(summary.membership, RoomMembership::Joined);
35
    assert!(!summary.name.is_empty());
36
37
    support::shut_down(&handle, &mut events, running).await;
38
}
39
40
#[tokio::test]
41
async fn connection_watch_tracks_the_engine_lifecycle() {
42
    let server = MatrixMockServer::new().await;
43
    server
44
        .mock_sliding_sync()
45
        .ok(v5::Response::new("1".to_owned()))
46
        .mount()
47
        .await;
48
    let client = server.client_builder().build().await;
49
    let config = EngineConfig::default().with_initial_history_limit(0);
50
    let (engine, handle, mut events) = Engine::from_client(client, config).await.unwrap();
51
    let mut connection = handle.connection_state();
52
    let connection_peer = connection.clone();
53
    assert_eq!(*connection.borrow(), ConnectionState::Idle);
54
    assert_eq!(*connection_peer.borrow(), ConnectionState::Idle);
55
56
    let running = tokio::spawn(engine.run());
57
    support::receive_until(&mut events, |event| {
58
        matches!(event, Event::ConnectionChanged(ConnectionState::Connecting))
59
    })
60
    .await;
61
    assert_ne!(*connection.borrow(), ConnectionState::Idle);
62
    support::receive_until(&mut events, |event| {
63
        matches!(event, Event::ConnectionChanged(ConnectionState::Online))
64
    })
65
    .await;
66
    wait_for_connection(&mut connection, ConnectionState::Online).await;
67
    assert_eq!(*connection_peer.borrow(), ConnectionState::Online);
68
69
    support::shut_down(&handle, &mut events, running).await;
70
    wait_for_connection(&mut connection, ConnectionState::Stopped).await;
71
    assert_eq!(*connection_peer.borrow(), ConnectionState::Stopped);
72
}
73
74
#[tokio::test]
75
async fn soft_logout_says_so_and_stops_the_engine() {
76
    let server = MatrixMockServer::new().await;
77
    server
78
        .mock_sliding_sync()
79
        .error_unknown_token(true)
80
        .mount()
81
        .await;
82
    let client = server.client_builder().build().await;
83
    let (engine, _handle, mut events) = Engine::from_client(
84
        client,
85
        EngineConfig::default().with_initial_history_limit(0),
86
    )
87
    .await
88
    .unwrap();
89
    let running = tokio::spawn(engine.run());
90
    support::receive_until(&mut events, |event| {
91
        matches!(event, Event::SessionAccessRejected { soft_logout: true })
92
    })
93
    .await;
94
    support::receive_until(&mut events, |event| matches!(event, Event::Stopped)).await;
95
    running.await.unwrap().unwrap();
96
}
97
98
#[tokio::test]
99
async fn closing_the_event_stream_stops_an_idle_engine() {
100
    let server = MatrixMockServer::new().await;
101
    server
102
        .mock_sliding_sync()
103
        .ok(v5::Response::new("1".to_owned()))
104
        .mount()
105
        .await;
106
    let client = server.client_builder().build().await;
107
    let (engine, handle, mut events) = Engine::from_client(
108
        client,
109
        EngineConfig::default().with_initial_history_limit(0),
110
    )
111
    .await
112
    .unwrap();
113
    let running = tokio::spawn(engine.run());
114
    support::receive_until(&mut events, |event| {
115
        matches!(event, Event::ConnectionChanged(ConnectionState::Online))
116
    })
117
    .await;
118
    drop(events);
119
    let result = tokio::time::timeout(Duration::from_secs(2), running)
120
        .await
121
        .expect("engine did not stop after its event receiver closed")
122
        .unwrap();
123
    assert!(matches!(result, Err(EngineError::EventReceiverClosed)));
124
    drop(handle);
125
}
126
127
async fn wait_for_connection(
128
    connection: &mut watch::Receiver<ConnectionState>,
129
    expected: ConnectionState,
130
) {
131
    tokio::time::timeout(Duration::from_secs(2), async {
132
        loop {
133
            if *connection.borrow_and_update() == expected {
134
                return;
135
            }
136
            connection
137
                .changed()
138
                .await
139
                .expect("connection watch closed before the expected state");
140
        }
141
    })
142
    .await
143
    .expect("expected connection state did not arrive");
144
}