zng-task 0.12.7

Part of the zng project.
Documentation
use std::time::Instant;

use rayon::prelude::*;

use super::*;
use zng_unit::TimeUnits;

#[track_caller]
fn async_test<F>(test: F) -> F::Output
where
    F: Future,
{
    block_on(with_deadline(test, 20.secs())).unwrap()
}

#[test]
fn any_one() {
    let r = async_test(async { any!(async { true }).await });

    assert!(r);
}

#[test]
fn any_nine() {
    let t = Instant::now();
    let one_s = 1.secs();
    let r = async_test(async {
        any!(
            async {
                deadline(one_s).await;
                1
            },
            async {
                deadline(one_s).await;
                2
            },
            async {
                deadline(one_s).await;
                3
            },
            async {
                deadline(one_s).await;
                4
            },
            async {
                deadline(one_s).await;
                5
            },
            async {
                deadline(one_s).await;
                6
            },
            async {
                deadline(one_s).await;
                7
            },
            async {
                deadline(one_s).await;
                8
            },
            async { 9 },
        )
        .await
    });

    assert_eq!(9, r);
    assert!(2.secs() > t.elapsed());
}

#[test]
fn run_wake_immediately() {
    async_test(async {
        run(async {
            yield_now().await;
        })
        .await;
    });
}

#[test]
fn run_panic_handling() {
    async_test(async {
        let r = run_catch(async {
            run(async {
                deadline(1.ms()).await;
                panic!("test panic")
            })
            .await;
        })
        .await;

        assert!(r.is_err());
    })
}

#[test]
fn run_panic_handling_parallel() {
    async_test(async {
        let r = run_catch(async {
            run(async {
                deadline(1.ms()).await;
                (0..100000).into_par_iter().for_each(|i| {
                    if i == 50005 {
                        panic!("test panic");
                    }
                });
            })
            .await;
        })
        .await;

        assert!(r.is_err());
    })
}

#[test]
fn fn_all() {
    let expected: Vec<_> = (0..20).collect();
    let tasks: Vec<_> = expected
        .iter()
        .map(|&i| async move {
            crate::deadline(((20 - i) * 50).ms()).await;
            i
        })
        .collect();

    let t = Instant::now();

    let results = async_test(async move { crate::all(tasks).await });

    assert_eq!(expected, results);
    assert!((30 * 50).ms() > t.elapsed())
}

#[test]
fn fn_all_ok_ok() {
    let expected: Vec<_> = (0..20).collect();
    let tasks: Vec<_> = expected
        .iter()
        .map(|&i| async move {
            crate::deadline(((20 - i) * 50).ms()).await;
            Ok::<_, String>(i)
        })
        .collect();

    let t = Instant::now();

    let results = async_test(async move { crate::all_ok(tasks).await }).unwrap();

    assert_eq!(expected, results);
    assert!((30 * 50).ms() > t.elapsed())
}

#[test]
fn fn_all_ok_err() {
    let expected: Vec<_> = (0..20).collect();
    let tasks: Vec<_> = expected
        .iter()
        .map(|&i| async move {
            crate::deadline(((20 - i) * 50).ms()).await;
            if i == 10 {
                return Err("error".to_owned());
            }
            Ok::<_, String>(i)
        })
        .collect();

    let t = Instant::now();

    let results = async_test(async move { crate::all_ok(tasks).await }).unwrap_err();

    assert_eq!("error", results);
    assert!((30 * 50).ms() > t.elapsed())
}

#[test]
fn fn_all_some_some() {
    let expected: Vec<_> = (0..20).collect();
    let tasks: Vec<_> = expected
        .iter()
        .map(|&i| async move {
            crate::deadline(((20 - i) * 50).ms()).await;
            Some(i)
        })
        .collect();

    let t = Instant::now();

    let results = async_test(async move { crate::all_some(tasks).await }).unwrap();

    assert_eq!(expected, results);
    assert!((30 * 50).ms() > t.elapsed())
}

#[test]
fn fn_all_some_none() {
    let expected: Vec<_> = (0..20).collect();
    let tasks: Vec<_> = expected
        .iter()
        .map(|&i| async move {
            crate::deadline(((20 - i) * 50).ms()).await;
            if i == 10 {
                return None;
            }
            Some(i)
        })
        .collect();

    let t = Instant::now();

    let results = async_test(async move { crate::all_some(tasks).await });

    assert!(results.is_none());
    assert!((30 * 50).ms() > t.elapsed())
}