veilid_tools/tests/common/
test_host_interface.rs

1use crate::*;
2
3cfg_if! {
4    if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
5        use js_sys::*;
6    } else {
7        use std::time::{Duration, SystemTime};
8    }
9}
10
11pub fn test_log() {
12    info!("testing log");
13}
14
15pub fn test_get_timestamp() {
16    info!("testing get_timestamp");
17    let t1 = get_timestamp();
18    let t2 = get_timestamp();
19    assert!(t2 >= t1);
20}
21
22pub async fn test_eventual() {
23    info!("testing Eventual");
24    {
25        let e1 = Eventual::new();
26        let i1 = e1.instance_clone(1u32);
27        let i2 = e1.instance_clone(2u32);
28        let i3 = e1.instance_clone(3u32);
29        drop(i3);
30        let i4 = e1.instance_clone(4u32);
31        drop(i2);
32
33        let jh = spawn("task", async move {
34            sleep(1000).await;
35            e1.resolve().await;
36        });
37
38        assert_eq!(i1.await, 1u32);
39        assert_eq!(i4.await, 4u32);
40
41        jh.await;
42    }
43    {
44        let e1 = Eventual::new();
45        let i1 = e1.instance_clone(1u32);
46        let i2 = e1.instance_clone(2u32);
47        let i3 = e1.instance_clone(3u32);
48        let i4 = e1.instance_clone(4u32);
49        let e1_c1 = e1.clone();
50        let jh = spawn("task", async move {
51            let i5 = e1.instance_clone(5u32);
52            let i6 = e1.instance_clone(6u32);
53            assert_eq!(i1.await, 1u32);
54            assert_eq!(i5.await, 5u32);
55            assert_eq!(i6.await, 6u32);
56        });
57        sleep(1000).await;
58        let resolved = e1_c1.resolve();
59        drop(i2);
60        drop(i3);
61        assert_eq!(i4.await, 4u32);
62        resolved.await;
63        jh.await;
64    }
65    {
66        let e1 = Eventual::new();
67        let i1 = e1.instance_clone(1u32);
68        let i2 = e1.instance_clone(2u32);
69        let e1_c1 = e1.clone();
70        let jh = spawn("task", async move {
71            assert_eq!(i1.await, 1u32);
72            assert_eq!(i2.await, 2u32);
73        });
74        sleep(1000).await;
75        e1_c1.resolve().await;
76
77        jh.await;
78
79        e1_c1.reset();
80        //
81        let j1 = e1.instance_clone(1u32);
82        let j2 = e1.instance_clone(2u32);
83        let jh = spawn("task", async move {
84            assert_eq!(j1.await, 1u32);
85            assert_eq!(j2.await, 2u32);
86        });
87        sleep(1000).await;
88        e1_c1.resolve().await;
89
90        jh.await;
91
92        e1_c1.reset();
93    }
94}
95
96pub async fn test_eventual_value() {
97    info!("testing Eventual Value");
98    {
99        let e1 = EventualValue::<u32>::new();
100        let i1 = e1.instance();
101        let i2 = e1.instance();
102        let i3 = e1.instance();
103        drop(i3);
104        let i4 = e1.instance();
105        drop(i2);
106
107        let e1_c1 = e1.clone();
108        let jh = spawn("task", async move {
109            sleep(1000).await;
110            e1_c1.resolve(3u32);
111        });
112
113        i1.await;
114        i4.await;
115        jh.await;
116        assert_eq!(e1.take_value(), Some(3u32));
117    }
118    {
119        let e1 = EventualValue::new();
120        let i1 = e1.instance();
121        let i2 = e1.instance();
122        let i3 = e1.instance();
123        let i4 = e1.instance();
124        let e1_c1 = e1.clone();
125        let jh = spawn("task", async move {
126            let i5 = e1.instance();
127            let i6 = e1.instance();
128            i1.await;
129            i5.await;
130            i6.await;
131        });
132        sleep(1000).await;
133        let resolved = e1_c1.resolve(4u16);
134        drop(i2);
135        drop(i3);
136        i4.await;
137        resolved.await;
138        jh.await;
139        assert_eq!(e1_c1.take_value(), Some(4u16));
140    }
141    {
142        let e1 = EventualValue::new();
143        assert_eq!(e1.take_value(), None);
144        let i1 = e1.instance();
145        let i2 = e1.instance();
146        let e1_c1 = e1.clone();
147        let jh = spawn("task", async move {
148            i1.await;
149            i2.await;
150        });
151        sleep(1000).await;
152        e1_c1.resolve(5u32).await;
153        jh.await;
154        assert_eq!(e1_c1.take_value(), Some(5u32));
155        e1_c1.reset();
156        assert_eq!(e1_c1.take_value(), None);
157        //
158        let j1 = e1.instance();
159        let j2 = e1.instance();
160        let jh = spawn("task", async move {
161            j1.await;
162            j2.await;
163        });
164        sleep(1000).await;
165        e1_c1.resolve(6u32).await;
166        jh.await;
167        assert_eq!(e1_c1.take_value(), Some(6u32));
168        e1_c1.reset();
169        assert_eq!(e1_c1.take_value(), None);
170    }
171}
172
173pub async fn test_eventual_value_clone() {
174    info!("testing Eventual Value Clone");
175    {
176        let e1 = EventualValueClone::<u32>::new();
177        let i1 = e1.instance();
178        let i2 = e1.instance();
179        let i3 = e1.instance();
180        drop(i3);
181        let i4 = e1.instance();
182        drop(i2);
183
184        let jh = spawn("task", async move {
185            sleep(1000).await;
186            e1.resolve(3u32);
187        });
188
189        assert_eq!(i1.await, 3);
190        assert_eq!(i4.await, 3);
191
192        jh.await;
193    }
194
195    {
196        let e1 = EventualValueClone::new();
197        let i1 = e1.instance();
198        let i2 = e1.instance();
199        let i3 = e1.instance();
200        let i4 = e1.instance();
201        let e1_c1 = e1.clone();
202        let jh = spawn("task", async move {
203            let i5 = e1.instance();
204            let i6 = e1.instance();
205            assert_eq!(i1.await, 4);
206            assert_eq!(i5.await, 4);
207            assert_eq!(i6.await, 4);
208        });
209        sleep(1000).await;
210        let resolved = e1_c1.resolve(4u16);
211        drop(i2);
212        drop(i3);
213        assert_eq!(i4.await, 4);
214        resolved.await;
215        jh.await;
216    }
217
218    {
219        let e1 = EventualValueClone::new();
220        let i1 = e1.instance();
221        let i2 = e1.instance();
222        let e1_c1 = e1.clone();
223        let jh = spawn("task", async move {
224            assert_eq!(i1.await, 5);
225            assert_eq!(i2.await, 5);
226        });
227        sleep(1000).await;
228        e1_c1.resolve(5u32).await;
229        jh.await;
230        e1_c1.reset();
231        //
232        let j1 = e1.instance();
233        let j2 = e1.instance();
234        let jh = spawn("task", async move {
235            assert_eq!(j1.await, 6);
236            assert_eq!(j2.await, 6);
237        });
238        sleep(1000).await;
239        e1_c1.resolve(6u32).await;
240        jh.await;
241        e1_c1.reset();
242    }
243}
244pub async fn test_interval() {
245    info!("testing interval");
246
247    let tick: Arc<Mutex<u32>> = Arc::new(Mutex::new(0u32));
248    let stopper = interval("interval", 1000, move || {
249        let tick = tick.clone();
250        async move {
251            let mut tick = tick.lock();
252            trace!("tick {}", tick);
253            *tick += 1;
254        }
255    });
256
257    sleep(5500).await;
258
259    stopper.await;
260}
261
262#[allow(clippy::await_holding_lock)]
263pub async fn test_timeout() {
264    info!("testing timeout");
265
266    let tick: Arc<Mutex<u32>> = Arc::new(Mutex::new(0u32));
267    let tick_1 = tick.clone();
268    assert!(
269        timeout(2500, async move {
270            let mut tick = tick_1.lock();
271            trace!("tick {}", tick);
272            sleep(1000).await;
273            *tick += 1;
274            trace!("tick {}", tick);
275            sleep(1000).await;
276            *tick += 1;
277            trace!("tick {}", tick);
278            sleep(1000).await;
279            *tick += 1;
280            trace!("tick {}", tick);
281            sleep(1000).await;
282            *tick += 1;
283        })
284        .await
285        .is_err(),
286        "should have timed out"
287    );
288
289    let ticks = *tick.lock();
290    assert!(ticks <= 2);
291}
292
293pub async fn test_sleep() {
294    info!("testing sleep");
295    cfg_if! {
296        if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
297
298            let t1 = Date::now();
299            sleep(1000).await;
300            let t2 = Date::now();
301            assert!((t2-t1) >= 1000.0);
302
303        } else {
304
305            let sys_time = SystemTime::now();
306            let one_sec = Duration::from_secs(1);
307
308            sleep(1000).await;
309            assert!(sys_time.elapsed().unwrap() >= one_sec);
310        }
311    }
312}
313
314macro_rules! assert_split_url {
315    ($url:expr, $scheme:expr, $host:expr) => {
316        assert_eq!(
317            SplitUrl::from_str($url),
318            Ok(SplitUrl::new($scheme, None, $host, None, None))
319        );
320    };
321    ($url:expr, $scheme:expr, $host:expr, $port:expr) => {
322        assert_eq!(
323            SplitUrl::from_str($url),
324            Ok(SplitUrl::new($scheme, None, $host, $port, None))
325        );
326    };
327    ($url:expr, $scheme:expr, $host:expr, $port:expr, $path:expr) => {
328        assert_eq!(
329            SplitUrl::from_str($url),
330            Ok(SplitUrl::new(
331                $scheme,
332                None,
333                $host,
334                $port,
335                Some(SplitUrlPath::new(
336                    $path,
337                    Option::<String>::None,
338                    Option::<String>::None
339                ))
340            ))
341        );
342    };
343    ($url:expr, $scheme:expr, $host:expr, $port:expr, $path:expr, $frag:expr, $query:expr) => {
344        assert_eq!(
345            SplitUrl::from_str($url),
346            Ok(SplitUrl::new(
347                $scheme,
348                None,
349                $host,
350                $port,
351                Some(SplitUrlPath::new($path, $frag, $query))
352            ))
353        );
354    };
355}
356
357macro_rules! assert_split_url_parse {
358    ($url:expr) => {
359        let url = $url;
360        let su1 = SplitUrl::from_str(url).expect("should parse");
361        assert_eq!(su1.to_string(), url);
362    };
363}
364
365fn host<S: AsRef<str>>(s: S) -> SplitUrlHost {
366    SplitUrlHost::Hostname(s.as_ref().to_owned())
367}
368
369fn ip<S: AsRef<str>>(s: S) -> SplitUrlHost {
370    SplitUrlHost::IpAddr(IpAddr::from_str(s.as_ref()).unwrap())
371}
372
373pub fn test_split_url() {
374    info!("testing split_url");
375
376    assert_split_url!("http://foo", "http", host("foo"));
377    assert_split_url!("http://foo:1234", "http", host("foo"), Some(1234));
378    assert_split_url!("http://foo:1234/", "http", host("foo"), Some(1234), "");
379    assert_split_url!(
380        "http://foo:1234/asdf/qwer",
381        "http",
382        host("foo"),
383        Some(1234),
384        "asdf/qwer"
385    );
386    assert_split_url!("http://foo/", "http", host("foo"), None, "");
387    assert_split_url!("http://11.2.3.144/", "http", ip("11.2.3.144"), None, "");
388    assert_split_url!("http://[1111::2222]/", "http", ip("1111::2222"), None, "");
389    assert_split_url!(
390        "http://[1111::2222]:123/",
391        "http",
392        ip("1111::2222"),
393        Some(123),
394        ""
395    );
396
397    assert_split_url!(
398        "http://foo/asdf/qwer",
399        "http",
400        host("foo"),
401        None,
402        "asdf/qwer"
403    );
404    assert_split_url!(
405        "http://foo/asdf/qwer#3",
406        "http",
407        host("foo"),
408        None,
409        "asdf/qwer",
410        Some("3"),
411        Option::<String>::None
412    );
413    assert_split_url!(
414        "http://foo/asdf/qwer?xxx",
415        "http",
416        host("foo"),
417        None,
418        "asdf/qwer",
419        Option::<String>::None,
420        Some("xxx")
421    );
422    assert_split_url!(
423        "http://foo/asdf/qwer#yyy?xxx",
424        "http",
425        host("foo"),
426        None,
427        "asdf/qwer",
428        Some("yyy"),
429        Some("xxx")
430    );
431    assert_err!(SplitUrl::from_str("://asdf"));
432    assert_err!(SplitUrl::from_str(""));
433    assert_err!(SplitUrl::from_str("::"));
434    assert_err!(SplitUrl::from_str("://:"));
435    assert_err!(SplitUrl::from_str("a://:"));
436    assert_err!(SplitUrl::from_str("a://:1243"));
437    assert_err!(SplitUrl::from_str("a://:65536"));
438    assert_err!(SplitUrl::from_str("a://:-16"));
439    assert_err!(SplitUrl::from_str("a:///"));
440    assert_err!(SplitUrl::from_str("a:///qwer:"));
441    assert_err!(SplitUrl::from_str("a:///qwer://"));
442    assert_err!(SplitUrl::from_str("a://qwer://"));
443    assert_err!(SplitUrl::from_str("a://[1111::2222]:/"));
444    assert_err!(SplitUrl::from_str("a://[1111::2222]:"));
445
446    assert_split_url_parse!("sch://foo:bar@baz.com:1234/fnord#qux?zuz");
447    assert_split_url_parse!("sch://foo:bar@baz.com:1234/fnord#qux");
448    assert_split_url_parse!("sch://foo:bar@baz.com:1234/fnord?zuz");
449    assert_split_url_parse!("sch://foo:bar@baz.com:1234/fnord/");
450    assert_split_url_parse!("sch://foo:bar@baz.com:1234//");
451    assert_split_url_parse!("sch://foo:bar@baz.com:1234");
452    assert_split_url_parse!("sch://foo:bar@[1111::2222]:1234");
453    assert_split_url_parse!("sch://foo:bar@[::]:1234");
454    assert_split_url_parse!("sch://foo:bar@1.2.3.4:1234");
455    assert_split_url_parse!("sch://@baz.com:1234");
456    assert_split_url_parse!("sch://baz.com/asdf/asdf");
457    assert_split_url_parse!("sch://baz.com/");
458    assert_split_url_parse!("s://s");
459}
460
461pub fn test_get_random_u64() {
462    info!("testing random number generator for u64");
463    let t1 = get_timestamp();
464    let count = 10000;
465    for _ in 0..count {
466        let _ = get_random_u64();
467    }
468    let t2 = get_timestamp();
469    let tdiff = ((t2 - t1) as f64) / 1000000.0f64;
470    info!(
471        "running get_random_u64 with {} iterations took {} seconds",
472        count, tdiff
473    );
474}
475
476pub fn test_get_random_u32() {
477    info!("testing random number generator for u32");
478    let t1 = get_timestamp();
479    let count = 10000;
480    for _ in 0..count {
481        let _ = get_random_u32();
482    }
483    let t2 = get_timestamp();
484    let tdiff = ((t2 - t1) as f64) / 1000000.0f64;
485    info!(
486        "running get_random_u32 with {} iterations took {} seconds",
487        count, tdiff
488    );
489}
490
491pub async fn test_must_join_single_future() {
492    info!("testing must join single future");
493    let sf = MustJoinSingleFuture::<u32>::new();
494    assert_eq!(sf.check().await, Ok(None));
495    assert_eq!(
496        sf.single_spawn("t1", async {
497            sleep(2000).await;
498            69
499        })
500        .await,
501        Ok((None, true))
502    );
503    assert_eq!(sf.check().await, Ok(None));
504    assert_eq!(
505        sf.single_spawn("t2", async { panic!() }).await,
506        Ok((None, false))
507    );
508    assert_eq!(sf.join().await, Ok(Some(69)));
509    assert_eq!(
510        sf.single_spawn("t3", async {
511            sleep(1000).await;
512            37
513        })
514        .await,
515        Ok((None, true))
516    );
517    sleep(2000).await;
518    assert_eq!(
519        sf.single_spawn("t4", async {
520            sleep(1000).await;
521            27
522        })
523        .await,
524        Ok((Some(37), true))
525    );
526    sleep(2000).await;
527    assert_eq!(sf.join().await, Ok(Some(27)));
528    assert_eq!(sf.check().await, Ok(None));
529}
530
531pub fn test_tools() {
532    info!("testing retry_falloff_log");
533    let mut last_us = 0u64;
534    for x in 0..1024 {
535        let cur_us = x as u64 * 1000000u64;
536        if retry_falloff_log(last_us, cur_us, 10_000_000u64, 6_000_000_000u64, 2.0f64) {
537            info!("   retry at {} secs", timestamp_to_secs(cur_us));
538            last_us = cur_us;
539        }
540    }
541}
542
543pub async fn test_all() {
544    test_log();
545    test_get_timestamp();
546    test_tools();
547    test_split_url();
548    test_get_random_u64();
549    test_get_random_u32();
550    test_sleep().await;
551    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
552    test_must_join_single_future().await;
553    test_eventual().await;
554    test_eventual_value().await;
555    test_eventual_value_clone().await;
556    test_interval().await;
557    test_timeout().await;
558}