atagen

macltok

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

Blame: tests/send_queue.rs

96fdf90aacd6atagen2026-09-08 08:24 UTC1
use std::time::Duration;
96fdf90aacd6atagen2026-09-08 08:24 UTC2
96fdf90aacd6atagen2026-09-08 08:24 UTC3
use macltok::{
96fdf90aacd6atagen2026-09-08 08:24 UTC4
    ClientHandle, Command, CommandErrorKind, CommandId, CommandKind, Engine, EngineConfig, Event,
96fdf90aacd6atagen2026-09-08 08:24 UTC5
    EventStream, LifecycleCommand, MessageContent, RoomCommand, TimelineCommand, TimelineItem,
96fdf90aacd6atagen2026-09-08 08:24 UTC6
};
96fdf90aacd6atagen2026-09-08 08:24 UTC7
use matrix_sdk::{
96fdf90aacd6atagen2026-09-08 08:24 UTC8
    Client,
96fdf90aacd6atagen2026-09-08 08:24 UTC9
    ruma::{OwnedTransactionId, RoomId, api::client::sync::sync_events::v5, event_id, room_id},
96fdf90aacd6atagen2026-09-08 08:24 UTC10
    test_utils::mocks::MatrixMockServer,
96fdf90aacd6atagen2026-09-08 08:24 UTC11
};
96fdf90aacd6atagen2026-09-08 08:24 UTC12
96fdf90aacd6atagen2026-09-08 08:24 UTC13
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC14
async fn cancel_send_uses_transaction_id_from_public_timeline() {
96fdf90aacd6atagen2026-09-08 08:24 UTC15
    let (server, client, handle, mut events, running) = setup().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC16
    let room_id = room_id!("!queue-controls:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC17
    client.send_queue().set_enabled(false).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC18
96fdf90aacd6atagen2026-09-08 08:24 UTC19
    let transaction_id = queue_message(&handle, &mut events, room_id, "discard me").await;
96fdf90aacd6atagen2026-09-08 08:24 UTC20
    assert!(
96fdf90aacd6atagen2026-09-08 08:24 UTC21
        handle
96fdf90aacd6atagen2026-09-08 08:24 UTC22
            .pending_send_ids(room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC23
            .await
96fdf90aacd6atagen2026-09-08 08:24 UTC24
            .unwrap()
96fdf90aacd6atagen2026-09-08 08:24 UTC25
            .contains(&transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC26
    );
96fdf90aacd6atagen2026-09-08 08:24 UTC27
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC28
        .cancel_send(room_id.to_owned(), transaction_id.clone())
96fdf90aacd6atagen2026-09-08 08:24 UTC29
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC30
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC31
    expect_success(&mut events, id, CommandKind::Room).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC32
96fdf90aacd6atagen2026-09-08 08:24 UTC33
    let (echoes, _) = client
96fdf90aacd6atagen2026-09-08 08:24 UTC34
        .get_room(room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC35
        .unwrap()
96fdf90aacd6atagen2026-09-08 08:24 UTC36
        .send_queue()
96fdf90aacd6atagen2026-09-08 08:24 UTC37
        .subscribe()
96fdf90aacd6atagen2026-09-08 08:24 UTC38
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC39
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC40
    assert!(
96fdf90aacd6atagen2026-09-08 08:24 UTC41
        !echoes
96fdf90aacd6atagen2026-09-08 08:24 UTC42
            .iter()
96fdf90aacd6atagen2026-09-08 08:24 UTC43
            .any(|echo| echo.transaction_id == transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC44
    );
96fdf90aacd6atagen2026-09-08 08:24 UTC45
96fdf90aacd6atagen2026-09-08 08:24 UTC46
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC47
        .cancel_send(room_id.to_owned(), transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC48
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC49
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC50
    let failure = receive_until(
96fdf90aacd6atagen2026-09-08 08:24 UTC51
        &mut events,
96fdf90aacd6atagen2026-09-08 08:24 UTC52
        |event| matches!(event, Event::CommandFailed(failure) if failure.id == id),
96fdf90aacd6atagen2026-09-08 08:24 UTC53
    )
96fdf90aacd6atagen2026-09-08 08:24 UTC54
    .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC55
    assert!(
96fdf90aacd6atagen2026-09-08 08:24 UTC56
        matches!(failure, Event::CommandFailed(failure) if failure.kind == CommandErrorKind::Other)
96fdf90aacd6atagen2026-09-08 08:24 UTC57
    );
96fdf90aacd6atagen2026-09-08 08:24 UTC58
96fdf90aacd6atagen2026-09-08 08:24 UTC59
    stop(handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC60
    drop(server);
96fdf90aacd6atagen2026-09-08 08:24 UTC61
}
96fdf90aacd6atagen2026-09-08 08:24 UTC62
96fdf90aacd6atagen2026-09-08 08:24 UTC63
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC64
async fn cancel_queued_attachment_by_pending_send_id() {
96fdf90aacd6atagen2026-09-08 08:24 UTC65
    let (server, client, handle, mut events, running) = setup().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC66
    let room_id = room_id!("!queue-controls:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC67
    client.send_queue().set_enabled(false).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC68
96fdf90aacd6atagen2026-09-08 08:24 UTC69
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC70
        .upload_media(
96fdf90aacd6atagen2026-09-08 08:24 UTC71
            room_id.to_owned().into(),
96fdf90aacd6atagen2026-09-08 08:24 UTC72
            "note.txt".to_owned(),
96fdf90aacd6atagen2026-09-08 08:24 UTC73
            "text/plain".to_owned(),
96fdf90aacd6atagen2026-09-08 08:24 UTC74
            b"attachment".to_vec(),
96fdf90aacd6atagen2026-09-08 08:24 UTC75
            None,
96fdf90aacd6atagen2026-09-08 08:24 UTC76
        )
96fdf90aacd6atagen2026-09-08 08:24 UTC77
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC78
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC79
    expect_success(&mut events, id, CommandKind::Media).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC80
96fdf90aacd6atagen2026-09-08 08:24 UTC81
    let pending = handle.pending_send_ids(room_id).await.unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC82
    assert_eq!(pending.len(), 1);
96fdf90aacd6atagen2026-09-08 08:24 UTC83
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC84
        .cancel_send(room_id.to_owned(), pending[0].clone())
96fdf90aacd6atagen2026-09-08 08:24 UTC85
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC86
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC87
    expect_success(&mut events, id, CommandKind::Room).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC88
    assert!(handle.pending_send_ids(room_id).await.unwrap().is_empty());
96fdf90aacd6atagen2026-09-08 08:24 UTC89
96fdf90aacd6atagen2026-09-08 08:24 UTC90
    stop(handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC91
    drop(server);
96fdf90aacd6atagen2026-09-08 08:24 UTC92
}
96fdf90aacd6atagen2026-09-08 08:24 UTC93
96fdf90aacd6atagen2026-09-08 08:24 UTC94
#[tokio::test]
96fdf90aacd6atagen2026-09-08 08:24 UTC95
async fn retry_send_wakes_paused_queue() {
96fdf90aacd6atagen2026-09-08 08:24 UTC96
    let (server, client, handle, mut events, running) = setup().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC97
    let room_id = room_id!("!queue-controls:localhost");
fa9114fcf75fatagen2026-09-24 12:51 UTC98
    client
fa9114fcf75fatagen2026-09-24 12:51 UTC99
        .get_room(room_id)
fa9114fcf75fatagen2026-09-24 12:51 UTC100
        .unwrap()
fa9114fcf75fatagen2026-09-24 12:51 UTC101
        .send_queue()
fa9114fcf75fatagen2026-09-24 12:51 UTC102
        .set_enabled(false);
96fdf90aacd6atagen2026-09-08 08:24 UTC103
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC104
        .mock_room_send()
96fdf90aacd6atagen2026-09-08 08:24 UTC105
        .body_matches_partial_json(serde_json::json!({ "body": "retry me" }))
96fdf90aacd6atagen2026-09-08 08:24 UTC106
        .ok(event_id!("$retried:localhost"))
96fdf90aacd6atagen2026-09-08 08:24 UTC107
        .expect(1)
96fdf90aacd6atagen2026-09-08 08:24 UTC108
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC109
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC110
96fdf90aacd6atagen2026-09-08 08:24 UTC111
    let transaction_id = queue_message(&handle, &mut events, room_id, "retry me").await;
96fdf90aacd6atagen2026-09-08 08:24 UTC112
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC113
        .retry_send(room_id.to_owned(), transaction_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC114
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC115
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC116
    expect_success(&mut events, id, CommandKind::Room).await;
fa9114fcf75fatagen2026-09-24 12:51 UTC117
    assert!(client.get_room(room_id).unwrap().send_queue().is_enabled());
96fdf90aacd6atagen2026-09-08 08:24 UTC118
96fdf90aacd6atagen2026-09-08 08:24 UTC119
    tokio::time::timeout(Duration::from_secs(5), async {
96fdf90aacd6atagen2026-09-08 08:24 UTC120
        loop {
96fdf90aacd6atagen2026-09-08 08:24 UTC121
            let (echoes, _) = client
96fdf90aacd6atagen2026-09-08 08:24 UTC122
                .get_room(room_id)
96fdf90aacd6atagen2026-09-08 08:24 UTC123
                .unwrap()
96fdf90aacd6atagen2026-09-08 08:24 UTC124
                .send_queue()
96fdf90aacd6atagen2026-09-08 08:24 UTC125
                .subscribe()
96fdf90aacd6atagen2026-09-08 08:24 UTC126
                .await
96fdf90aacd6atagen2026-09-08 08:24 UTC127
                .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC128
            if echoes.is_empty() {
96fdf90aacd6atagen2026-09-08 08:24 UTC129
                break;
96fdf90aacd6atagen2026-09-08 08:24 UTC130
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC131
            tokio::task::yield_now().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC132
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC133
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC134
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC135
    .expect("retried message was not sent");
96fdf90aacd6atagen2026-09-08 08:24 UTC136
96fdf90aacd6atagen2026-09-08 08:24 UTC137
    stop(handle, &mut events, running).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC138
    drop(server);
96fdf90aacd6atagen2026-09-08 08:24 UTC139
}
96fdf90aacd6atagen2026-09-08 08:24 UTC140
96fdf90aacd6atagen2026-09-08 08:24 UTC141
async fn setup() -> (
96fdf90aacd6atagen2026-09-08 08:24 UTC142
    MatrixMockServer,
96fdf90aacd6atagen2026-09-08 08:24 UTC143
    Client,
96fdf90aacd6atagen2026-09-08 08:24 UTC144
    ClientHandle,
96fdf90aacd6atagen2026-09-08 08:24 UTC145
    EventStream,
96fdf90aacd6atagen2026-09-08 08:24 UTC146
    tokio::task::JoinHandle<Result<(), macltok::EngineError>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC147
) {
96fdf90aacd6atagen2026-09-08 08:24 UTC148
    let server = MatrixMockServer::new().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC149
    server
96fdf90aacd6atagen2026-09-08 08:24 UTC150
        .mock_sliding_sync()
96fdf90aacd6atagen2026-09-08 08:24 UTC151
        .ok(v5::Response::new("1".to_owned()))
96fdf90aacd6atagen2026-09-08 08:24 UTC152
        .mount()
96fdf90aacd6atagen2026-09-08 08:24 UTC153
        .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC154
    let client = server.client_builder().build().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC155
    let room_id = room_id!("!queue-controls:localhost");
96fdf90aacd6atagen2026-09-08 08:24 UTC156
    server.mock_room_state_encryption().plain().mount().await;
96fdf90aacd6atagen2026-09-08 08:24 UTC157
    server.sync_joined_room(&client, room_id).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC158
    let (engine, handle, events) = Engine::from_client(
96fdf90aacd6atagen2026-09-08 08:24 UTC159
        client.clone(),
96fdf90aacd6atagen2026-09-08 08:24 UTC160
        EngineConfig::default().with_initial_history_limit(0),
96fdf90aacd6atagen2026-09-08 08:24 UTC161
    )
96fdf90aacd6atagen2026-09-08 08:24 UTC162
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC163
    .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC164
    let running = tokio::spawn(engine.run());
96fdf90aacd6atagen2026-09-08 08:24 UTC165
    let mut events = events;
96fdf90aacd6atagen2026-09-08 08:24 UTC166
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC167
        .send(Command::Room(RoomCommand::Open(room_id.to_owned())))
96fdf90aacd6atagen2026-09-08 08:24 UTC168
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC169
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC170
    expect_success(&mut events, id, CommandKind::Room).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC171
    (server, client, handle, events, running)
96fdf90aacd6atagen2026-09-08 08:24 UTC172
}
96fdf90aacd6atagen2026-09-08 08:24 UTC173
96fdf90aacd6atagen2026-09-08 08:24 UTC174
async fn queue_message(
96fdf90aacd6atagen2026-09-08 08:24 UTC175
    handle: &ClientHandle,
96fdf90aacd6atagen2026-09-08 08:24 UTC176
    events: &mut EventStream,
96fdf90aacd6atagen2026-09-08 08:24 UTC177
    room_id: &RoomId,
96fdf90aacd6atagen2026-09-08 08:24 UTC178
    body: &str,
96fdf90aacd6atagen2026-09-08 08:24 UTC179
) -> OwnedTransactionId {
96fdf90aacd6atagen2026-09-08 08:24 UTC180
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC181
        .send(Command::Timeline(TimelineCommand::Send {
96fdf90aacd6atagen2026-09-08 08:24 UTC182
            timeline_id: room_id.to_owned().into(),
96fdf90aacd6atagen2026-09-08 08:24 UTC183
            content: MessageContent::text(body),
96fdf90aacd6atagen2026-09-08 08:24 UTC184
        }))
96fdf90aacd6atagen2026-09-08 08:24 UTC185
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC186
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC187
    let mut succeeded = false;
96fdf90aacd6atagen2026-09-08 08:24 UTC188
    let mut items = Vec::new();
96fdf90aacd6atagen2026-09-08 08:24 UTC189
    tokio::time::timeout(Duration::from_secs(5), async {
96fdf90aacd6atagen2026-09-08 08:24 UTC190
        loop {
96fdf90aacd6atagen2026-09-08 08:24 UTC191
            match events.recv().await.expect("event stream closed") {
96fdf90aacd6atagen2026-09-08 08:24 UTC192
                Event::TimelineChanged { diffs, .. } => {
96fdf90aacd6atagen2026-09-08 08:24 UTC193
                    for diff in diffs {
96fdf90aacd6atagen2026-09-08 08:24 UTC194
                        diff.try_apply(&mut items).unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC195
                    }
96fdf90aacd6atagen2026-09-08 08:24 UTC196
                    let transaction = items.iter().find_map(|item| match item {
96fdf90aacd6atagen2026-09-08 08:24 UTC197
                        TimelineItem::Message(message) if message.body == body => {
96fdf90aacd6atagen2026-09-08 08:24 UTC198
                            message.transaction_id.clone()
96fdf90aacd6atagen2026-09-08 08:24 UTC199
                        }
96fdf90aacd6atagen2026-09-08 08:24 UTC200
                        _ => None,
96fdf90aacd6atagen2026-09-08 08:24 UTC201
                    });
96fdf90aacd6atagen2026-09-08 08:24 UTC202
                    if let Some(transaction) = transaction {
96fdf90aacd6atagen2026-09-08 08:24 UTC203
                        if !succeeded {
96fdf90aacd6atagen2026-09-08 08:24 UTC204
                            expect_success(events, id, CommandKind::Timeline).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC205
                        }
96fdf90aacd6atagen2026-09-08 08:24 UTC206
                        return transaction;
96fdf90aacd6atagen2026-09-08 08:24 UTC207
                    }
96fdf90aacd6atagen2026-09-08 08:24 UTC208
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC209
                Event::CommandSucceeded {
96fdf90aacd6atagen2026-09-08 08:24 UTC210
                    id: completed,
96fdf90aacd6atagen2026-09-08 08:24 UTC211
                    command: CommandKind::Timeline,
96fdf90aacd6atagen2026-09-08 08:24 UTC212
                } if completed == id => succeeded = true,
96fdf90aacd6atagen2026-09-08 08:24 UTC213
                Event::CommandFailed(failure) if failure.id == id => {
96fdf90aacd6atagen2026-09-08 08:24 UTC214
                    panic!("send failed {failure:?}")
96fdf90aacd6atagen2026-09-08 08:24 UTC215
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC216
                _ => {}
96fdf90aacd6atagen2026-09-08 08:24 UTC217
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC218
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC219
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC220
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC221
    .expect("local echo did not appear")
96fdf90aacd6atagen2026-09-08 08:24 UTC222
}
96fdf90aacd6atagen2026-09-08 08:24 UTC223
96fdf90aacd6atagen2026-09-08 08:24 UTC224
async fn expect_success(events: &mut EventStream, id: CommandId, command: CommandKind) {
96fdf90aacd6atagen2026-09-08 08:24 UTC225
    receive_until(events, |event| {
96fdf90aacd6atagen2026-09-08 08:24 UTC226
        matches!(event, Event::CommandSucceeded { id: completed, command: kind } if *completed == id && *kind == command)
96fdf90aacd6atagen2026-09-08 08:24 UTC227
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC228
    .await;
96fdf90aacd6atagen2026-09-08 08:24 UTC229
}
96fdf90aacd6atagen2026-09-08 08:24 UTC230
96fdf90aacd6atagen2026-09-08 08:24 UTC231
async fn receive_until(events: &mut EventStream, predicate: impl Fn(&Event) -> bool) -> Event {
96fdf90aacd6atagen2026-09-08 08:24 UTC232
    tokio::time::timeout(Duration::from_secs(5), async {
96fdf90aacd6atagen2026-09-08 08:24 UTC233
        loop {
96fdf90aacd6atagen2026-09-08 08:24 UTC234
            let event = events.recv().await.expect("event stream closed");
96fdf90aacd6atagen2026-09-08 08:24 UTC235
            if predicate(&event) {
96fdf90aacd6atagen2026-09-08 08:24 UTC236
                return event;
96fdf90aacd6atagen2026-09-08 08:24 UTC237
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC238
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC239
    })
96fdf90aacd6atagen2026-09-08 08:24 UTC240
    .await
96fdf90aacd6atagen2026-09-08 08:24 UTC241
    .expect("expected event did not arrive")
96fdf90aacd6atagen2026-09-08 08:24 UTC242
}
96fdf90aacd6atagen2026-09-08 08:24 UTC243
96fdf90aacd6atagen2026-09-08 08:24 UTC244
async fn stop(
96fdf90aacd6atagen2026-09-08 08:24 UTC245
    handle: ClientHandle,
96fdf90aacd6atagen2026-09-08 08:24 UTC246
    events: &mut EventStream,
96fdf90aacd6atagen2026-09-08 08:24 UTC247
    running: tokio::task::JoinHandle<Result<(), macltok::EngineError>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC248
) {
96fdf90aacd6atagen2026-09-08 08:24 UTC249
    let id = handle
96fdf90aacd6atagen2026-09-08 08:24 UTC250
        .send(Command::Lifecycle(LifecycleCommand::Shutdown))
96fdf90aacd6atagen2026-09-08 08:24 UTC251
        .await
96fdf90aacd6atagen2026-09-08 08:24 UTC252
        .unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC253
    expect_success(events, id, CommandKind::Lifecycle).await;
96fdf90aacd6atagen2026-09-08 08:24 UTC254
    running.await.unwrap().unwrap();
96fdf90aacd6atagen2026-09-08 08:24 UTC255
}