namaste 0.18.0

Simple locks between processes
Documentation
// License: see LICENSE file at root directory of main branch

//! # Tests

use core::{
    sync::atomic::{AtomicUsize, Ordering},
    time::Duration,
};

use std::{
    sync::Arc,
    thread,
    time::Instant,
};

use namaste::Result;

use {
    blackhole::{BlackHole, OneTime},
    zeros::Hash,
};

#[test]
fn tests() -> Result<()> {
    const HALF_THREAD_COUNT: usize = 5;
    const THREAD_COUNT: usize = HALF_THREAD_COUNT * 2;
    const TIMEOUT: Duration = Duration::from_millis(500);
    const DELAY: Duration = Duration::from_millis(100);
    const SMALL_DELAY: Duration = Duration::from_millis(50);
    const ORDERING: Ordering = Ordering::Relaxed;

    assert!(SMALL_DELAY < DELAY);

    let ids = (0..THREAD_COUNT).into_iter().map(|i| Hash::Sha3_512.hash_iter([
        namaste::ID.as_bytes(),
        &[
            0xa2, 0x56, 0x0c, 0xcd, 0x5f, 0xb3, 0x9d, 0x93, 0xd4, 0x1c, 0xe2, 0x0a, 0x5d, 0x12, 0xeb, 0xaf, 0xe8, 0x3f, 0x34, 0x0e, 0x8f, 0x74,
            0x93, 0x20, 0x76, 0xb6, 0xaa, 0x7b, 0x54, 0x8f, 0x93, 0x34, 0xe4, 0x8d, 0x85, 0xc1, 0x25, 0x64, 0xdb, 0xfd, 0x0f, 0x93, 0x53, 0x10,
            0x28, 0x7e, 0xfd, 0x4d, 0x1e, 0x23, 0xd7, 0x9b, 0xa1, 0xe7, 0x13, 0x30, 0xcb, 0x9c, 0x16, 0xdb, 0x85, 0x85, 0x83, 0x7b,
        ],
        &(i % HALF_THREAD_COUNT).to_be_bytes(),
    ].iter()));

    let counter = Arc::new(AtomicUsize::new(usize::min_value()));
    let blackhole = BlackHole::make(blackhole::available_parallelism()?, THREAD_COUNT)?;
    let start = Instant::now();
    for (index, id) in ids.enumerate() {
        let counter = counter.clone();
        assert!(blackhole.throw(OneTime::new(move || unsafe {
            if index < HALF_THREAD_COUNT {
                let _namaste = namaste::make(id, TIMEOUT).unwrap();
                thread::sleep(DELAY);
            } else {
                thread::sleep(SMALL_DELAY);
                let _namaste = namaste::make_wait(id, TIMEOUT).unwrap();
            }
            counter.fetch_add(1, ORDERING);
        }))?.is_none());
    }

    blackhole.escape_on_idle()?;
    let duration = Instant::now().duration_since(start).as_millis();
    assert_eq!(counter.load(ORDERING), THREAD_COUNT);
    assert!(duration >= DELAY.as_millis() && duration <= DELAY.as_millis().checked_mul(HALF_THREAD_COUNT.try_into().unwrap()).unwrap());

    Ok(())
}