atagen

macltok

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