mithril_aggregator_client/
external_trait_impls.rs

1use anyhow::{Context, anyhow};
2use async_trait::async_trait;
3
4use mithril_common::certificate_chain::{CertificateRetriever, CertificateRetrieverError};
5use mithril_common::entities::Certificate;
6
7use crate::AggregatorHttpClient;
8use crate::query::GetCertificateQuery;
9
10#[cfg_attr(target_family = "wasm", async_trait(?Send))]
11#[cfg_attr(not(target_family = "wasm"), async_trait)]
12impl CertificateRetriever for AggregatorHttpClient {
13    async fn get_certificate_details(
14        &self,
15        certificate_hash: &str,
16    ) -> Result<Certificate, CertificateRetrieverError> {
17        let message = self
18            .send(GetCertificateQuery::by_hash(certificate_hash))
19            .await
20            .with_context(|| {
21                format!("Failed to retrieve certificate with hash: '{certificate_hash}'")
22            })
23            .map_err(CertificateRetrieverError)?
24            .ok_or(CertificateRetrieverError(anyhow!(
25                "Certificate does not exist: '{certificate_hash}'"
26            )))?;
27
28        message.try_into().map_err(CertificateRetrieverError)
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use mithril_common::{
35        entities::ServerError, messages::CertificateMessage, test::double::Dummy,
36    };
37
38    use super::*;
39
40    #[tokio::test]
41    async fn test_retrieve_certificate_that_exist() {
42        let certificate_message = CertificateMessage::dummy();
43        let expected_certificate = certificate_message.clone().try_into().unwrap();
44
45        let (server, client) = crate::test::setup_server_and_client();
46        server.mock(|when, then| {
47            when.method(httpmock::Method::GET)
48                .path(format!("/certificate/{}", certificate_message.hash));
49            then.status(200)
50                .body(serde_json::to_string(&certificate_message).unwrap());
51        });
52
53        let certificate = client
54            .get_certificate_details(&certificate_message.hash)
55            .await
56            .unwrap();
57
58        assert_eq!(certificate, expected_certificate);
59    }
60
61    #[tokio::test]
62    async fn test_retrieve_certificate_that_does_not_exist() {
63        let (server, client) = crate::test::setup_server_and_client();
64        server.mock(|when, then| {
65            when.method(httpmock::Method::GET);
66            then.status(404);
67        });
68
69        let error = client.get_certificate_details("whatever").await.unwrap_err();
70
71        assert!(
72            format!("{error:?}").contains("Certificate does not exist"),
73            "Error message should contain 'Certificate does not exist', error:\n{error:?}",
74        );
75    }
76
77    #[tokio::test]
78    async fn test_retrieve_certificate_when_request_fails() {
79        let (server, client) = crate::test::setup_server_and_client();
80        server.mock(|when, then| {
81            when.method(httpmock::Method::GET);
82            then.status(500)
83                .body(serde_json::to_string(&ServerError::new("an error")).unwrap());
84        });
85
86        let error = client.get_certificate_details("whatever").await.unwrap_err();
87
88        assert!(
89            format!("{error:?}").contains("Failed to retrieve certificate with hash"),
90            "Error message should contain 'Failed to retrieve certificate with hash', error:\n{error:?}",
91        );
92    }
93}