euv-engine 0.30.2

A high-performance 2D game engine built on the euv framework, featuring ECS, fixed-timestep game loop, canvas rendering, physics, collision detection, sprite animation, and audio.
Documentation
use super::*;

fn handle() -> EngineHandle {
    EngineHandle::new(Engine::default_config(), None, None, None, None)
}

#[test]
fn the_default_engine_config_is_the_default_config() {
    assert_eq!(
        Engine::default_config(),
        EngineConfig::default(),
        "default_config must be a plain default, not a second opinion about it"
    );
}

#[test]
fn a_handle_that_was_never_started_is_not_running() {
    assert!(
        !handle().is_running(),
        "the game loop is off until start is called"
    );
}

#[test]
fn a_handle_without_a_scheduler_can_still_be_stopped() {
    let engine: EngineHandle = handle();
    engine.stop();
    assert!(!engine.is_running(), "stopping an idle engine is a no-op");
}

#[test]
fn registering_a_task_returns_a_handle_that_unregisters_it() {
    let engine: EngineHandle = handle();
    let handle_id: TaskHandle = engine.register_task(Timer::create(1.0));
    assert!(
        engine.unregister_task(&handle_id),
        "the handle returned by register_task must remove that task"
    );
}

#[test]
fn unregistering_a_handle_twice_reports_false_the_second_time() {
    let engine: EngineHandle = handle();
    let handle_id: TaskHandle = engine.register_task(Timer::create(1.0));
    assert!(engine.unregister_task(&handle_id));
    assert!(
        !engine.unregister_task(&handle_id),
        "a removed handle is stale, so the second removal must report false"
    );
}

#[test]
fn removing_an_earlier_task_stales_every_later_handle() {
    let engine: EngineHandle = handle();
    let first: TaskHandle = engine.register_task(Timer::create(1.0));
    let second: TaskHandle = engine.register_task(Timer::create(1.0));
    assert!(engine.unregister_task(&first));
    assert!(
        !engine.unregister_task(&second),
        "a handle stores its insertion index, so removing an earlier task \
         shifts every later slot and stales the handle — this is the documented contract"
    );
}

#[test]
fn a_later_handle_outliving_an_earlier_removal_still_holds_a_task() {
    let engine: EngineHandle = handle();
    let first: TaskHandle = engine.register_task(Timer::create(1.0));
    let second: TaskHandle = engine.register_task(Timer::create(1.0));
    assert!(engine.unregister_task(&first));
    assert!(
        !engine.unregister_task(&second),
        "the stale removal must report false rather than silently dropping a survivor"
    );
    assert!(
        !engine.unregister_task(&second),
        "a second stale attempt must stay false instead of double-removing"
    );
}

#[test]
fn unregistering_the_most_recently_registered_task_always_succeeds() {
    let engine: EngineHandle = handle();
    let first: TaskHandle = engine.register_task(Timer::create(1.0));
    let second: TaskHandle = engine.register_task(Timer::create(1.0));
    let third: TaskHandle = engine.register_task(Timer::create(1.0));
    assert!(
        engine.unregister_task(&third),
        "the last handle is the one nothing registered before it can invalidate"
    );
    assert!(engine.unregister_task(&first));
    assert!(
        !engine.unregister_task(&second),
        "second sat after first, so removing first shifted it out from under its handle"
    );
}

#[test]
fn a_fresh_handle_registers_no_asset_loader() {
    let engine: EngineHandle = handle();
    assert!(
        engine.asset_loader().is_none(),
        "assets are opt-in, so nothing may be created before register_assets"
    );
}

#[test]
fn an_engine_with_no_tasks_reports_no_asset_loader_after_stop() {
    let engine: EngineHandle = handle();
    engine.stop();
    assert!(engine.asset_loader().is_none());
    assert!(!engine.is_running());
}

#[test]
fn a_task_registered_after_a_removal_is_still_removable() {
    let engine: EngineHandle = handle();
    let first: TaskHandle = engine.register_task(Timer::create(1.0));
    let removed: bool = engine.unregister_task(&first);
    assert!(removed);
    let late: TaskHandle = engine.register_task(Timer::create(1.0));
    assert!(
        engine.unregister_task(&late),
        "a handle returned after the list settled must be valid immediately"
    );
}