Skip to content

Commit

Permalink
github workflow // integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mekaem committed Oct 26, 2024
1 parent 6d34e64 commit 6a72d47
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Rust

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

env:
CARGO_TERM_COLOR: always

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
154 changes: 154 additions & 0 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
use atomalloc::{block::BlockOps, config::AtomAllocConfig, error::AtomAllocError, AtomAlloc};
use std::{alloc::Layout, sync::Arc, time::Duration};

#[tokio::test]
async fn test_basic_alloc_dealloc() {
let config = AtomAllocConfig::get_default_for_tests();
let allocator = AtomAlloc::with_config(config).await;
let layout = Layout::from_size_align(64, 8).unwrap();

println!("\n=== Starting basic allocation test ===");

// Get initial stats
let stats_before = allocator.stats().await;
println!("Initial stats: {:?}", stats_before);

// Single allocation
let block = allocator.allocate(layout).await.unwrap();
let stats_after_alloc = allocator.stats().await;
println!("Stats after allocation: {:?}", stats_after_alloc);
assert_eq!(block.size(), 64);

// Deallocate
allocator.deallocate(block).await;
let stats_final = allocator.stats().await;
println!("Final stats: {:?}", stats_final);

assert_eq!(stats_final.allocated - stats_before.allocated, 64);
assert_eq!(stats_final.freed - stats_before.freed, 64);
}

#[tokio::test]
async fn test_concurrent_allocations() {
let allocator = Arc::new(AtomAlloc::new().await);
let mut handles = vec![];

for _ in 0..100 {
let allocator = Arc::clone(&allocator);
handles.push(tokio::spawn(async move {
let layout = Layout::from_size_align(64, 8).unwrap();
let block = allocator.allocate(layout).await.unwrap();
tokio::task::yield_now().await;
allocator.deallocate(block).await;
}));
}

for handle in handles {
handle.await.unwrap();
}
}

#[tokio::test]
async fn test_pool_reuse() {
let allocator = AtomAlloc::new().await;
let layout = Layout::from_size_align(64, 8).unwrap();

// First allocation
let block1 = allocator.allocate(layout).await.unwrap();
let gen1 = block1.generation();
allocator.deallocate(block1).await;

// Second allocation should reuse block
let block2 = allocator.allocate(layout).await.unwrap();
let gen2 = block2.generation();
assert_eq!(gen1, gen2, "Block should be reused");
allocator.deallocate(block2).await;
}

#[tokio::test]
async fn test_memory_limits() {
// Configure with 2KB total but only 512B max block size
let config = AtomAllocConfig {
max_memory: 2048, // 2KB total
max_block_size: 512, // But max block still 512B
min_block_size: 64, // Min block 64B
alignment: 8,
cache_ttl: Duration::from_secs(60),
max_caches: 100,
initial_pool_size: 512,
zero_on_dealloc: true,
};

println!("\n=== Starting memory limits test with size classes ===");
println!("Config: {:?}", config);
let allocator = AtomAlloc::with_config(config).await;

// First 512B allocation
let layout1 = Layout::from_size_align(400, 8).unwrap();
let block1 = allocator.allocate(layout1).await.unwrap();
let stats1 = allocator.stats().await;
println!("Stats after first allocation (400B->512B): {:?}", stats1);
assert_eq!(stats1.current, 512);

// Try to allocate more than max block size
let layout2 = Layout::from_size_align(600, 8).unwrap();
let result = allocator.allocate(layout2).await;
println!(
"Second allocation result (600B): {:?}",
result.as_ref().err()
);
assert!(
matches!(result.as_ref(), Err(AtomAllocError::OutOfMemory)),
"Expected OutOfMemory for too-large block"
);

allocator.deallocate(block1).await;
}

#[tokio::test]
async fn test_strict_memory_limits() {
// Configure for 1KB total, but effectively ~768B usable
let config = AtomAllocConfig {
max_memory: 1024, // 1KB total limit
max_block_size: 512, // Largest block is 512B
min_block_size: 64, // Smallest block is 64B
alignment: 8,
cache_ttl: Duration::from_secs(60),
max_caches: 100,
initial_pool_size: 512,
zero_on_dealloc: true,
};

println!("\n=== Starting strict memory limit test ===");
let allocator = AtomAlloc::with_config(config).await;

// First 512B allocation should work
let layout1 = Layout::from_size_align(300, 8).unwrap();
let block1 = allocator.allocate(layout1).await.unwrap();
let stats1 = allocator.stats().await;
println!("After first allocation (300B->512B): {:?}", stats1);
assert_eq!(stats1.current, 512);

// Second 512B should fail due to effective memory limit
let layout2 = Layout::from_size_align(400, 8).unwrap();
let result = allocator.allocate(layout2).await;
println!(
"Second allocation result (400B->512B): {:?}",
result.as_ref().err()
);
assert!(matches!(result.as_ref(), Err(AtomAllocError::OutOfMemory)));

// Free first block
allocator.deallocate(block1).await;
let stats2 = allocator.stats().await;
println!("After deallocation: {:?}", stats2);
assert_eq!(stats2.current, 0);

// Now we can allocate again
let block2 = allocator.allocate(layout2).await.unwrap();
let stats3 = allocator.stats().await;
println!("After final allocation: {:?}", stats3);
assert_eq!(stats3.current, 512);

allocator.deallocate(block2).await;
}

0 comments on commit 6a72d47

Please sign in to comment.