host/
common.rs

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