Skip to main content

host/
common.rs

1use rand::{prelude::*, rngs::ChaCha8Rng};
2use std::{collections::VecDeque, time::Duration};
3
4use upc::Class;
5
6pub const VID: u16 = 4;
7pub const PID: u16 = 5;
8
9pub const CLASS: Class = Class::vendor_specific(22, 3);
10pub const TOPIC: &[u8] = b"TEST TOPIC";
11pub const INFO: &[u8] = b"TEST INFO";
12
13pub const HOST_SEED: u64 = 12523;
14pub const DEVICE_SEED: u64 = 23152;
15pub const TEST_PACKETS: usize = 1_000;
16pub const TEST_PACKET_MAX_SIZE: usize = 1_000_000;
17
18pub const DELAY: bool = false;
19
20#[cfg(not(feature = "web"))]
21pub fn init_log() {
22    use std::sync::Once;
23    use tracing_subscriber::{fmt, prelude::*, EnvFilter};
24
25    static ONCE: Once = Once::new();
26    ONCE.call_once(|| {
27        tracing_subscriber::registry().with(fmt::layer()).with(EnvFilter::from_default_env()).init();
28        tracing_log::LogTracer::init().unwrap();
29    });
30}
31
32#[cfg(not(feature = "web"))]
33use tokio::time::sleep;
34
35#[cfg(feature = "web")]
36pub async fn sleep(duration: Duration) {
37    use js_sys::Promise;
38    use wasm_bindgen_futures::JsFuture;
39    use web_sys::window;
40
41    let ms = duration.as_millis() as i32;
42    let promise = Promise::new(&mut |resolve, _reject| {
43        let window = window().unwrap();
44        window.set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, ms).unwrap();
45    });
46    JsFuture::from(promise).await.unwrap();
47}
48
49pub struct TestData {
50    rng: ChaCha8Rng,
51    max_length: usize,
52    pre_lengths: VecDeque<usize>,
53}
54
55impl TestData {
56    pub fn new(seed: u64, max_length: usize) -> Self {
57        Self {
58            rng: ChaCha8Rng::seed_from_u64(seed),
59            max_length,
60            pre_lengths: [
61                0,
62                1,
63                2,
64                3,
65                511,
66                512,
67                513,
68                1023,
69                1024,
70                1025,
71                0,
72                2000,
73                2048,
74                0,
75                4096,
76                5000,
77                8191,
78                8192,
79                8193,
80                0,
81                8193,
82                TEST_PACKET_MAX_SIZE,
83            ]
84            .into(),
85        }
86    }
87
88    pub fn generate(&mut self) -> Vec<u8> {
89        let len = match self.pre_lengths.pop_front() {
90            Some(len) => len,
91            None => self.rng.random_range(0..self.max_length),
92        };
93        let mut data = vec![0; len];
94        self.rng.fill_bytes(&mut data);
95        data
96    }
97
98    pub fn validate(&mut self, data: &[u8]) {
99        let expected = self.generate();
100        assert_eq!(data.len(), expected.len(), "data length mismatch");
101        assert_eq!(data, &expected, "data mismatch");
102    }
103}
104
105pub struct TestDelayer {
106    rng: ChaCha8Rng,
107}
108
109impl TestDelayer {
110    pub fn new(seed: u64) -> Self {
111        Self { rng: ChaCha8Rng::seed_from_u64(seed) }
112    }
113
114    pub async fn delay(&mut self) {
115        if !DELAY {
116            return;
117        }
118
119        if self.rng.random_ratio(1, 1000) {
120            let ms = self.rng.random_range(0..1000);
121            sleep(Duration::from_millis(ms)).await;
122        }
123    }
124}