1
//! Tests invoking an API defined in a custom backend.
2

            
3
use bonsaidb::client::url::Url;
4
use bonsaidb::client::AsyncClient;
5
use bonsaidb::core::api::{Api, Infallible};
6
use bonsaidb::core::async_trait::async_trait;
7
use bonsaidb::core::test_util::{Basic, TestDirectory};
8
use bonsaidb::local::config::Builder;
9
use bonsaidb::server::api::Handler;
10
use bonsaidb::server::{Backend, CustomServer, DefaultPermissions, ServerConfiguration};
11
use bonsaidb_core::api::ApiName;
12
use bonsaidb_core::schema::Qualified;
13
use bonsaidb_server::api::{HandlerResult, HandlerSession};
14
use serde::{Deserialize, Serialize};
15

            
16
1
#[derive(Debug, Default)]
17
struct CustomBackend;
18

            
19
impl Backend for CustomBackend {
20
    type ClientData = u64;
21
    type Error = Infallible;
22
}
23

            
24
1
#[tokio::test]
25
1
async fn custom_api() -> anyhow::Result<()> {
26
1
    let dir = TestDirectory::new("custom_api.bonsaidb");
27
1
    let server = CustomServer::<CustomBackend>::open(
28
1
        ServerConfiguration::new(&dir)
29
1
            .default_permissions(DefaultPermissions::AllowAll)
30
1
            .with_api::<SetValueHandler, _>()?
31
1
            .with_schema::<Basic>()?,
32
    )
33
3
    .await?;
34
10
    server.install_self_signed_certificate(false).await?;
35
1
    let certificate = server
36
1
        .certificate_chain()
37
2
        .await?
38
1
        .into_end_entity_certificate();
39
3
    tokio::spawn(async move { server.listen_on(12346).await });
40

            
41
1
    let client = AsyncClient::build(Url::parse("bonsaidb://localhost:12346")?)
42
1
        .with_api::<SetValue>()
43
1
        .with_certificate(certificate)
44
1
        .build()?;
45

            
46
1
    let old_value = client.send_api_request(&SetValue { new_value: 1 }).await?;
47
1
    assert_eq!(old_value, None);
48
1
    let old_value = client.send_api_request(&SetValue { new_value: 2 }).await?;
49
1
    assert_eq!(old_value, Some(1));
50

            
51
1
    Ok(())
52
}
53

            
54
6
#[derive(Debug, Serialize, Deserialize)]
55
struct SetValue {
56
    new_value: u64,
57
}
58

            
59
impl Api for SetValue {
60
    type Error = Infallible;
61
    type Response = Option<u64>;
62

            
63
4
    fn name() -> ApiName {
64
4
        ApiName::private("set-value")
65
4
    }
66
}
67

            
68
#[derive(Debug)]
69
struct SetValueHandler;
70

            
71
#[async_trait]
72
impl Handler<SetValue, CustomBackend> for SetValueHandler {
73
2
    async fn handle(
74
2
        session: HandlerSession<'_, CustomBackend>,
75
2
        request: SetValue,
76
2
    ) -> HandlerResult<SetValue> {
77
2
        let mut data = session.client.client_data().await;
78
2
        let existing_value = data.replace(request.new_value);
79
2
        Ok(existing_value)
80
4
    }
81
}