cranpose-core 0.1.141

Core runtime for a Jetpack Compose inspired UI framework in Rust
Documentation
use super::*;

#[test]
fn state_arena_alloc_skips_free_slot_outside_cell_storage() {
    let runtime = TestRuntime::new();
    let arena = StateArena::default();
    let first = arena.alloc(1_i32, runtime.handle());
    arena.inner.borrow_mut().free.push(u32::MAX);

    let second = arena.alloc(2_i32, runtime.handle());

    assert_eq!(first.slot(), 0);
    assert_eq!(second.slot(), 1);
    assert!(arena.get_typed_opt::<i32>(first).is_some());
    assert!(arena.get_typed_opt::<i32>(second).is_some());
}

#[test]
fn state_arena_alloc_skips_occupied_free_slot() {
    let runtime = TestRuntime::new();
    let arena = StateArena::default();
    let first = arena.alloc(1_i32, runtime.handle());
    arena.inner.borrow_mut().free.push(first.slot());

    let second = arena.alloc(2_i32, runtime.handle());

    assert_ne!(first.slot(), second.slot());
    assert_eq!(second.slot(), 1);
    assert!(arena.get_typed_opt::<i32>(first).is_some());
    assert!(arena.get_typed_opt::<i32>(second).is_some());
}

#[test]
fn state_arena_register_lease_ignores_stale_id() {
    let runtime = TestRuntime::new();
    let arena = StateArena::default();
    let stale_id = StateId::new(99, 0);
    let lease = Rc::new(StateHandleLease {
        id: stale_id,
        runtime: runtime.handle(),
    });

    arena.register_lease(stale_id, &lease);

    assert!(arena.retain_lease(stale_id).is_none());
}

#[test]
fn ui_continuation_type_mismatch_is_ignored_until_matching_payload() {
    let runtime = TestRuntime::new();
    let handle = runtime.handle();
    let received = Rc::new(Cell::new(None));
    let received_for_continuation = Rc::clone(&received);
    let cont_id = handle
        .register_ui_cont(move |value: u32| {
            received_for_continuation.set(Some(value));
        })
        .expect("test runtime is alive");

    handle.dispatcher().post_invoke(cont_id, "wrong payload");
    handle.drain_ui();

    assert_eq!(received.get(), None);
    assert_eq!(handle.debug_stats().ui_conts_len, 1);

    handle.dispatcher().post_invoke(cont_id, 42_u32);
    handle.drain_ui();

    assert_eq!(received.get(), Some(42));
    assert_eq!(handle.debug_stats().ui_conts_len, 0);
}

#[test]
fn ui_dispatcher_failed_send_does_not_leave_pending_work() {
    let runtime = Runtime::new(Arc::new(TestScheduler));
    let dispatcher = runtime.handle().dispatcher();

    drop(runtime);

    assert!(!dispatcher.has_pending());
    dispatcher.post(|| {});
    assert!(!dispatcher.has_pending());
    dispatcher.post_invoke(404, 12_u32);
    assert!(!dispatcher.has_pending());
}

#[test]
fn pending_guard_does_not_wrap_on_underflow() {
    let counter = AtomicUsize::new(0);

    {
        let _guard = PendingGuard::new(&counter);
    }

    assert_eq!(counter.load(Ordering::SeqCst), 0);
}

#[test]
fn pending_guard_decrements_pending_count() {
    let counter = AtomicUsize::new(2);

    {
        let _guard = PendingGuard::new(&counter);
    }

    assert_eq!(counter.load(Ordering::SeqCst), 1);
}

#[test]
fn schedule_frame_without_runtime_is_ignored() {
    let ok = std::thread::spawn(|| std::panic::catch_unwind(super::schedule_frame).is_ok())
        .join()
        .expect("test thread should join");

    assert!(ok);
}

#[test]
fn schedule_node_update_without_runtime_is_ignored() {
    let ok = std::thread::spawn(|| {
        std::panic::catch_unwind(|| {
            super::schedule_node_update(|_| Ok(()));
        })
        .is_ok()
    })
    .join()
    .expect("test thread should join");

    assert!(ok);
}