avmnif-rs 0.4.1

Safe NIF toolkit for AtomVM written in Rust
Documentation
# Testing Guide

## Architecture

The testing system uses dependency injection with the `AtomTableOps` trait:

- **Production**: `AtomTable::from_global()` - real AtomVM FFI
- **Testing**: `MockAtomTable::new()` - pure Rust implementation

No global state. Each test gets an isolated atom table instance.

## Core Pattern

```rust
#[test]
fn test_example() {
    let table = MockAtomTable::new();
    
    let user = user_fixture(&table);
    let atom = TermValue::atom("test", &table);
    
    assert_atom_str(&atom, "test", &table);
    assert_map_has_key(&user, "name", &table);
}
```

## Testing Modules

### `testing/mocks.rs`

Mock implementations for testing without AtomVM.

- `MockAtomTable::new()` - Standard table with common atoms
- `MockAtomTable::new_empty()` - Empty table
- `MockAtomTable::new_with_atoms(&["custom"])` - Pre-populated with specific atoms

### `testing/helpers.rs`

Generic test utilities that work with any atom table.

```rust
// Atom creation
let atom = atom("hello", &table);
let atoms = atoms(&["red", "green", "blue"], &table);

// Assertions
assert_atom_str(&term, "expected", &table);
assert_int(&term, 42);
assert_map_has_key(&map, "key", &table);

// Test data
let list = int_list(&[1, 2, 3]);
let map = atom_map(&[("key", value)], &table);
```

### `testing/fixtures.rs`

Pre-built realistic test data.

```rust
let user = user_fixture(&table);              // User with id, name, email
let admin = admin_user_fixture(&table);       // Admin with permissions
let config = config_fixture(&table);          // App configuration
let nested = nested_structure_fixture(&table); // Complex nested data

// Scenarios
let session = scenarios::user_session_scenario(&table);
let error = scenarios::error_scenario(&table);
```

## Key Functions

All functions that need atoms take a table parameter:

```rust
// Generic function
fn process_data<T: AtomTableOps>(data: &TermValue, table: &T) -> TermValue {
    if data.is_atom_str("ok", table) {
        TermValue::atom("success", table)
    } else {
        TermValue::atom("error", table)
    }
}

// Tagged serialization
let tagged = data.to_tagged_map(&table)?;
let restored = MyStruct::from_tagged_map(tagged, &table)?;
```

## Test Isolation

Each `MockAtomTable::new()` creates a completely independent instance. Tests cannot interfere with each other.

```rust
#[test] 
fn test_a() {
    let table = MockAtomTable::new(); // Isolated
    // ... test code
}

#[test]
fn test_b() {
    let table = MockAtomTable::new(); // Isolated
    // ... test code  
}
```