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

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

            
17
#[derive(Debug)]
18
struct CustomBackend;
19

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

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

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

            
47
1
    let old_value = client
48
1
        .send_api_request_async(&SetValue { new_value: 1 })
49
1
        .await?;
50
1
    assert_eq!(old_value, None);
51
1
    let old_value = client
52
1
        .send_api_request_async(&SetValue { new_value: 2 })
53
1
        .await?;
54
1
    assert_eq!(old_value, Some(1));
55

            
56
1
    Ok(())
57
1
}
58

            
59
6
#[derive(Debug, Serialize, Deserialize)]
60
struct SetValue {
61
    new_value: u64,
62
}
63

            
64
impl Api for SetValue {
65
    type Response = Option<u64>;
66
    type Error = Infallible;
67

            
68
4
    fn name() -> ApiName {
69
4
        ApiName::private("set-value")
70
4
    }
71
}
72

            
73
#[derive(Debug)]
74
struct SetValueHandler;
75

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