Skip to main content

race_test/
client_helpers.rs

1use std::{collections::HashMap, sync::Arc};
2
3use async_trait::async_trait;
4use race_client::Client;
5use race_api::error::Result;
6use race_api::event::{CustomEvent, Event};
7use race_core::{
8    connection::ConnectionT,
9    context::GameContext,
10    secret::SecretState,
11    types::{AttachGameParams, ClientMode, DecisionId, ExitGameParams, SubmitEventParams},
12};
13use race_encryptor::Encryptor;
14use tokio::sync::{mpsc, Mutex};
15
16use crate::{transport_helpers::DummyTransport, account_helpers::test_game_addr};
17
18pub struct TestClient {
19    client: Client,
20}
21
22pub struct DummyConnection {
23    rx: Mutex<mpsc::Receiver<Event>>,
24    tx: mpsc::Sender<Event>,
25    pub attached: Mutex<bool>,
26}
27
28impl Default for DummyConnection {
29    fn default() -> Self {
30        let (tx, rx) = mpsc::channel(1);
31        Self {
32            tx,
33            rx: Mutex::new(rx),
34            attached: Mutex::new(false),
35        }
36    }
37}
38
39impl DummyConnection {
40    pub async fn take(&self) -> Option<Event> {
41        self.rx.lock().await.recv().await
42    }
43
44    pub async fn is_attached(&self) -> bool {
45        *self.attached.lock().await
46    }
47}
48
49#[async_trait]
50impl ConnectionT for DummyConnection {
51    async fn attach_game(&self, _game_addr: &str, _params: AttachGameParams) -> Result<()> {
52        let mut attached = self.attached.lock().await;
53        *attached = true;
54        Ok(())
55    }
56    async fn submit_event(&self, _game_addr: &str, params: SubmitEventParams) -> Result<()> {
57        self.tx.send(params.event).await.unwrap();
58        Ok(())
59    }
60    async fn exit_game(&self, _game_addr: &str, _params: ExitGameParams) -> Result<()> {
61        Ok(())
62    }
63}
64
65impl TestClient {
66    pub fn new<S: Into<String>>(addr: S, mode: ClientMode) -> Self {
67        let addr = addr.into();
68        let transport = Arc::new(DummyTransport::default());
69        let encryptor = Arc::new(Encryptor::default());
70        let connection = Arc::new(DummyConnection::default());
71        Self {
72            client: Client::new(
73                addr,
74                test_game_addr(),
75                mode,
76                transport,
77                encryptor,
78                connection,
79            ),
80        }
81    }
82
83    pub fn player<S: Into<String>>(addr: S) -> Self {
84        Self::new(addr, ClientMode::Player)
85    }
86
87    pub fn transactor<S: Into<String>>(addr: S) -> Self {
88        Self::new(addr, ClientMode::Transactor)
89    }
90
91    pub fn validator<S: Into<String>>(addr: S) -> Self {
92        Self::new(addr, ClientMode::Validator)
93    }
94
95    pub fn handle_updated_context(&mut self, ctx: &GameContext) -> Result<Vec<Event>> {
96        self.client.handle_updated_context(ctx)
97    }
98
99    pub fn get_mode(&self) -> ClientMode {
100        self.client.mode.clone()
101    }
102
103    pub fn get_addr(&self) -> String {
104        self.client.addr.clone()
105    }
106
107    pub fn decrypt(
108        &mut self,
109        ctx: &GameContext,
110        random_id: usize,
111    ) -> Result<HashMap<usize, String>> {
112        self.client.decrypt(ctx, random_id)
113    }
114
115    pub fn secret_state(&self) -> &SecretState {
116        &self.client.secret_state
117    }
118
119    pub fn custom_event<E: CustomEvent>(&self, custom_event: E) -> Event {
120        Event::Custom {
121            sender: self.client.addr.to_owned(),
122            raw: custom_event.try_to_vec().unwrap(),
123        }
124    }
125
126    pub fn answer(&mut self, decision_id: DecisionId, answer: String) -> Result<Event> {
127        self.client.answer_event(decision_id, answer)
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::*;
134
135    #[tokio::test]
136    async fn test_dummy_connection() -> Result<()> {
137        let conn = DummyConnection::default();
138        let event = Event::GameStart { access_version: 1 };
139        conn.submit_event(
140            "",
141            SubmitEventParams {
142                event: event.clone(),
143            },
144        )
145        .await?;
146        let event_1 = conn.take().await.unwrap();
147        assert_eq!(event, event_1);
148        Ok(())
149    }
150}