atagen

macltok

public
Star0
Watch0
5b21b919d1e6b2bd383e3cfc77ff4f6397d2a488
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git
tests/state.rsRust153 lines5.2 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!(
94
            event,
95
            Event::SessionAccessRejected {
96
                soft_logout: Some(_)
97
            }
98
        )
99
    })
100
    .await;
101
    support::receive_until(&mut events, |event| matches!(event, Event::Stopped)).await;
102
    let termination = running.await.unwrap().unwrap();
103
    assert!(matches!(termination, Termination::SoftLoggedOut { .. }));
104
    assert_eq!(termination.retain(), Retain::Store);
105
}
106
107
#[tokio::test]
108
async fn closing_the_event_stream_stops_an_idle_engine() {
109
    let server = MatrixMockServer::new().await;
110
    server
111
        .mock_sliding_sync()
112
        .ok(v5::Response::new("1".to_owned()))
113
        .mount()
114
        .await;
115
    let client = server.client_builder().build().await;
116
    let (engine, handle, mut events) = Engine::from_client(
117
        client,
118
        EngineConfig::default().with_initial_history_limit(0),
119
    )
120
    .await
121
    .unwrap();
122
    let running = tokio::spawn(engine.run());
123
    support::receive_until(&mut events, |event| {
124
        matches!(event, Event::ConnectionChanged(ConnectionState::Online))
125
    })
126
    .await;
127
    drop(events);
128
    let result = tokio::time::timeout(Duration::from_secs(2), running)
129
        .await
130
        .expect("engine did not stop after its event receiver closed")
131
        .unwrap();
132
    assert!(matches!(result, Err(EngineError::EventReceiverClosed)));
133
    drop(handle);
134
}
135
136
async fn wait_for_connection(
137
    connection: &mut watch::Receiver<ConnectionState>,
138
    expected: ConnectionState,
139
) {
140
    tokio::time::timeout(Duration::from_secs(2), async {
141
        loop {
142
            if *connection.borrow_and_update() == expected {
143
                return;
144
            }
145
            connection
146
                .changed()
147
                .await
148
                .expect("connection watch closed before the expected state");
149
        }
150
    })
151
    .await
152
    .expect("expected connection state did not arrive");
153
}