atagen

macltok

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