memkit 0.2.0-beta.1

Deterministic, intent-driven memory allocation for systems requiring predictable performance
Documentation
//! Integration tests for memkit.

use memkit::{MkAllocator, MkConfig};

#[test]
fn test_frame_allocation() {
    let alloc = MkAllocator::with_defaults();

    alloc.begin_frame();

    // Allocate some values
    let boxed = alloc.frame_box(42u64).expect("frame_box failed");
    assert_eq!(*boxed, 42);

    let boxed2 = alloc.frame_box(123i32).expect("frame_box failed");
    assert_eq!(*boxed2, 123);

    alloc.end_frame();
}

#[test]
fn test_frame_slice() {
    let alloc = MkAllocator::with_defaults();

    alloc.begin_frame();

    let mut slice = alloc.frame_slice::<u32>(100).expect("frame_slice failed");
    assert_eq!(slice.len(), 100);

    // Initialize
    for i in 0..100 {
        slice[i] = i as u32;
    }

    // Verify
    for i in 0..100 {
        assert_eq!(slice[i], i as u32);
    }

    alloc.end_frame();
}

#[test]
fn test_frame_vec() {
    let alloc = MkAllocator::with_defaults();

    alloc.begin_frame();

    let mut vec = alloc.frame_vec::<u64>(10).expect("frame_vec failed");
    assert_eq!(vec.len(), 0);
    assert_eq!(vec.capacity(), 10);

    // Push values
    for i in 0..10 {
        vec.push(i).expect("push failed");
    }

    assert_eq!(vec.len(), 10);
    assert_eq!(vec[0], 0);
    assert_eq!(vec[9], 9);

    // Should fail - at capacity
    assert!(vec.push(100).is_err());

    alloc.end_frame();
}

#[test]
fn test_frame_reset() {
    let alloc = MkAllocator::with_defaults();

    alloc.begin_frame();
    let head1 = alloc.frame_head();

    alloc.frame_box(42u64);
    alloc.frame_box(123u64);
    let head2 = alloc.frame_head();

    assert!(head2 > head1);

    alloc.end_frame();

    // After end_frame, head should be reset
    alloc.begin_frame();
    let head3 = alloc.frame_head();
    assert_eq!(head3, 0);

    alloc.end_frame();
}

#[test]
fn test_scope() {
    let alloc = MkAllocator::with_defaults();

    alloc.begin_frame();

    alloc.frame_box(42u64);
    let head_before = alloc.frame_head();

    {
        let _scope = alloc.scope();
        alloc.frame_box(123u64);
        alloc.frame_box(456u64);
        let head_inside = alloc.frame_head();
        assert!(head_inside > head_before);
    }

    // After scope drops, head should be restored
    let head_after = alloc.frame_head();
    assert_eq!(head_after, head_before);

    alloc.end_frame();
}

#[test]
fn test_pool_allocation() {
    let alloc = MkAllocator::with_defaults();

    let boxed = alloc.pool_box(42u64).expect("pool_box failed");
    assert_eq!(*boxed, 42);

    // Pool allocations don't need frame begin/end
    let boxed2 = alloc.pool_box(123i32).expect("pool_box failed");
    assert_eq!(*boxed2, 123);
}

#[test]
fn test_heap_allocation() {
    let alloc = MkAllocator::with_defaults();

    let boxed = alloc.heap_box([0u8; 8192]).expect("heap_box failed");
    assert_eq!(boxed[0], 0);

    // Check stats: MkHeapBox is now independent of global stats/sentinel
    // so we don't expect allocation_count to increase.
    // let stats = alloc.stats();
    // assert!(stats.allocation_count >= 1);
}

#[test]
fn test_frame_counter() {
    let alloc = MkAllocator::with_defaults();

    assert_eq!(alloc.frame(), 0);

    alloc.begin_frame();
    assert_eq!(alloc.frame(), 1);
    alloc.end_frame();

    alloc.begin_frame();
    assert_eq!(alloc.frame(), 2);
    alloc.end_frame();
}

#[test]
fn test_custom_config() {
    let config = MkConfig {
        frame_arena_size: 1024 * 1024, // 1 MB
        ..MkConfig::default()
    };

    let alloc = MkAllocator::new(config);
    assert_eq!(alloc.config().frame_arena_size, 1024 * 1024);

    alloc.begin_frame();
    let boxed = alloc.frame_box(42u64).expect("frame_box failed");
    assert_eq!(*boxed, 42);
    alloc.end_frame();
}

#[test]
fn test_multiple_frames() {
    let alloc = MkAllocator::with_defaults();

    for frame in 1..=10 {
        alloc.begin_frame();
        assert_eq!(alloc.frame(), frame);

        // Allocate in each frame
        let boxed = alloc.frame_box(frame).expect("frame_box failed");
        assert_eq!(*boxed, frame);

        alloc.end_frame();
    }
}