1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// mockall::mock currently generates these warnings
#![allow(clippy::unused_unit)]
#![allow(clippy::ptr_arg)]

use crate::db::client::DbClient;
pub use crate::db::client::MockDbClient;
use crate::db::error::DbResult;
use crate::db::User;
use crate::notification::Notification;
use async_trait::async_trait;
use std::collections::HashSet;
use std::sync::Arc;
use uuid::Uuid;

use super::client::FetchMessageResponse;

#[async_trait]
impl DbClient for Arc<MockDbClient> {
    async fn add_user(&self, user: &User) -> DbResult<()> {
        Arc::as_ref(self).add_user(user).await
    }

    async fn update_user(&self, user: &mut User) -> DbResult<bool> {
        Arc::as_ref(self).update_user(user).await
    }

    async fn get_user(&self, uaid: &Uuid) -> DbResult<Option<User>> {
        Arc::as_ref(self).get_user(uaid).await
    }

    async fn remove_user(&self, uaid: &Uuid) -> DbResult<()> {
        Arc::as_ref(self).remove_user(uaid).await
    }

    async fn add_channel(&self, uaid: &Uuid, channel_id: &Uuid) -> DbResult<()> {
        Arc::as_ref(self).add_channel(uaid, channel_id).await
    }

    async fn add_channels(&self, uaid: &Uuid, channels: HashSet<Uuid>) -> DbResult<()> {
        Arc::as_ref(self).add_channels(uaid, channels).await
    }

    async fn get_channels(&self, uaid: &Uuid) -> DbResult<HashSet<Uuid>> {
        Arc::as_ref(self).get_channels(uaid).await
    }

    async fn remove_channel(&self, uaid: &Uuid, channel_id: &Uuid) -> DbResult<bool> {
        Arc::as_ref(self).remove_channel(uaid, channel_id).await
    }

    async fn remove_node_id(
        &self,
        uaid: &Uuid,
        node_id: &str,
        connected_at: u64,
        version: &Option<Uuid>,
    ) -> DbResult<bool> {
        Arc::as_ref(self)
            .remove_node_id(uaid, node_id, connected_at, version)
            .await
    }

    async fn save_message(&self, uaid: &Uuid, message: Notification) -> DbResult<()> {
        Arc::as_ref(self).save_message(uaid, message).await
    }

    async fn save_messages(&self, uaid: &Uuid, messages: Vec<Notification>) -> DbResult<()> {
        Arc::as_ref(self).save_messages(uaid, messages).await
    }

    async fn fetch_topic_messages(
        &self,
        uaid: &Uuid,
        limit: usize,
    ) -> DbResult<FetchMessageResponse> {
        Arc::as_ref(self).fetch_topic_messages(uaid, limit).await
    }

    async fn fetch_timestamp_messages(
        &self,
        uaid: &Uuid,
        timestamp: Option<u64>,
        limit: usize,
    ) -> DbResult<FetchMessageResponse> {
        Arc::as_ref(self)
            .fetch_timestamp_messages(uaid, timestamp, limit)
            .await
    }

    async fn increment_storage(&self, uaid: &Uuid, timestamp: u64) -> DbResult<()> {
        Arc::as_ref(self).increment_storage(uaid, timestamp).await
    }

    async fn remove_message(&self, uaid: &Uuid, sort_key: &str) -> DbResult<()> {
        Arc::as_ref(self).remove_message(uaid, sort_key).await
    }

    async fn router_table_exists(&self) -> DbResult<bool> {
        Arc::as_ref(self).router_table_exists().await
    }

    async fn message_table_exists(&self) -> DbResult<bool> {
        Arc::as_ref(self).message_table_exists().await
    }

    async fn health_check(&self) -> DbResult<bool> {
        Arc::as_ref(self).health_check().await
    }

    fn box_clone(&self) -> Box<dyn DbClient> {
        Box::new(Arc::clone(self))
    }

    fn name(&self) -> String {
        Arc::as_ref(self).name()
    }
}

impl MockDbClient {
    /// Convert into a type which can be used in place of `Box<dyn DbClient>`.
    /// Arc is used so that the mock can be cloned. Box is used so it can be
    /// easily cast to `Box<dyn DbClient>`.
    #[allow(clippy::redundant_allocation)]
    pub fn into_boxed_arc(self) -> Box<Arc<Self>> {
        Box::new(Arc::new(self))
    }
}