cranpose-services 0.1.161

Multiplatform system services for Cranpose (HTTP, URI, and OS integrations)
Documentation
use std::sync::{Arc, PoisonError};

use super::*;

fn navigation_lock() -> std::sync::MutexGuard<'static, ()> {
    static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
    LOCK.lock().unwrap_or_else(PoisonError::into_inner)
}

#[test]
fn requests_accumulate_and_drain() {
    let _guard = navigation_lock();
    let _ = take_back_requests();
    push_back_request();
    push_back_request();
    assert_eq!(take_back_requests(), 2);
    assert_eq!(take_back_requests(), 0);
}

#[test]
fn a_registered_listener_hears_every_request() {
    let _guard = navigation_lock();
    let heard = Arc::new(AtomicUsize::new(0));
    let counter = Arc::clone(&heard);
    let _observer = observe_back_requests(move || {
        counter.fetch_add(1, Ordering::SeqCst);
    });
    let before = heard.load(Ordering::SeqCst);
    push_back_request();
    push_back_request();
    assert_eq!(heard.load(Ordering::SeqCst), before + 2);
    let _ = take_back_requests();

    let before = heard.load(Ordering::SeqCst);
    request_exit();
    assert_eq!(
        heard.load(Ordering::SeqCst),
        before + 1,
        "an exit request has to wake an idle app the way a back request does"
    );
    let _ = take_exit_request();
}

#[test]
fn the_latest_back_observer_wins_until_it_is_dropped() {
    let _guard = navigation_lock();
    let first = Arc::new(AtomicUsize::new(0));
    let second = Arc::new(AtomicUsize::new(0));
    let first_seen = Arc::clone(&first);
    let first_observer = observe_back_requests(move || {
        first_seen.fetch_add(1, Ordering::SeqCst);
    });
    let second_seen = Arc::clone(&second);
    let second_observer = observe_back_requests(move || {
        second_seen.fetch_add(1, Ordering::SeqCst);
    });
    push_back_request();
    assert_eq!(first.load(Ordering::SeqCst), 0);
    assert_eq!(second.load(Ordering::SeqCst), 1);
    drop(second_observer);
    push_back_request();
    assert_eq!(first.load(Ordering::SeqCst), 1);
    drop(first_observer);
    let _ = take_back_requests();
}

#[test]
fn an_exit_request_is_taken_once() {
    let _guard = navigation_lock();
    let _ = take_exit_request();
    assert!(!take_exit_request());
    request_exit();
    request_exit();
    assert!(take_exit_request());
    assert!(
        !take_exit_request(),
        "a drained request came back; the platform would close twice"
    );
}

#[test]
fn a_backend_can_look_at_the_request_without_consuming_it() {
    let _guard = navigation_lock();
    let _ = take_exit_request();
    assert!(!exit_requested());

    request_exit();
    assert!(exit_requested());
    assert!(
        exit_requested(),
        "looking at the request consumed it, which is the bug"
    );

    assert!(take_exit_request());
    assert!(!exit_requested());
}

#[test]
fn interception_defaults_off_and_toggles() {
    let _guard = navigation_lock();
    set_back_interception(false);
    assert!(!back_interception_enabled());
    set_back_interception(true);
    assert!(back_interception_enabled());
    set_back_interception(false);
}