//! Integration tests for rs-lang proc-macros.
//!
//! This crate verifies that generated code from all proc-macros compiles
//! and behaves correctly when used against the rs-lang runtime types.

use core::time::Duration;
use rs_lang::prelude::*;
use rs_lang::{cell, step, Addressed, deterministic};

// ---------------------------------------------------------------------------
// #[derive(Addressed)] — canonical serialization + particle
// ---------------------------------------------------------------------------

#[derive(Addressed)]
struct SimpleRecord {
    id: u32,
    value: u64,
    flag: bool,
}

#[derive(Addressed)]
struct WithOption {
    data: u32,
    extra: Option<u64>,
}

#[derive(Addressed)]
struct WithArray {
    hash: [u8; 32],
}

#[derive(Addressed)]
enum Status {
    Active,
    Inactive,
    Suspended(u32),
}

// ---------------------------------------------------------------------------
// #[step] — struct reset
// ---------------------------------------------------------------------------

#[step]
struct StepCounters {
    count: u32,
    total: u64,
    active: bool,
    maybe: Option<u32>,
}

// ---------------------------------------------------------------------------
// #[deterministic] — token-level checks (should compile fine)
// ---------------------------------------------------------------------------

#[deterministic]
fn add_checked(a: u32, b: u32) -> Option<u32> {
    a.checked_add(b)
}

#[deterministic]
fn multiply_fixed(a: u64, b: u64) -> u64 {
    a.wrapping_mul(b)
}

// ---------------------------------------------------------------------------
// cell! — full cell declaration
// ---------------------------------------------------------------------------

cell! {
    name: Counter,
    version: 1,
    budget: Duration::from_millis(100),
    heartbeat: Duration::from_secs(1),

    state {
        value: u64,
        limit: u32,
    }

    step_state {
        increments: u32,
    }

    pub fn get(&self) -> u64 {
        self.state.value
    }

    pub fn increment(&mut self) -> Result<u64> {
        if self.step_state.increments >= self.state.limit {
            return Err(Error::LimitReached);
        }
        self.state.value = self.state.value.wrapping_add(1);
        self.step_state.increments += 1;
        Ok(self.state.value)
    }

    fn internal_check(&self) -> bool {
        self.state.value < u64::MAX
    }
}

// ---------------------------------------------------------------------------
// cell! — minimal cell (no step_state, no migrate)
// ---------------------------------------------------------------------------

cell! {
    name: Minimal,
    version: 1,
    budget: Duration::from_millis(50),
    heartbeat: Duration::from_secs(5),

    state {
        alive: bool,
    }

    pub fn is_alive(&self) -> bool {
        self.state.alive
    }
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

#[cfg(test)]
mod tests {
    use super::*;
    use rs_lang::{Cell, CellMetadata, StepReset};

    // --- Addressed ---

    #[test]
    fn addressed_serialize_deterministic() {
        let rec = SimpleRecord { id: 42, value: 100, flag: true };
        let p1 = rec.particle();
        let p2 = rec.particle();
        assert_eq!(p1, p2, "same value must produce same particle");
    }

    #[test]
    fn addressed_different_values_different_particles() {
        let a = SimpleRecord { id: 1, value: 0, flag: false };
        let b = SimpleRecord { id: 2, value: 0, flag: false };
        assert_ne!(a.particle(), b.particle());
    }

    #[test]
    fn addressed_option_some_vs_none() {
        let some = WithOption { data: 1, extra: Some(99) };
        let none = WithOption { data: 1, extra: None };
        assert_ne!(some.particle(), none.particle());
    }

    #[test]
    fn addressed_array_field() {
        let rec = WithArray { hash: [0xAA; 32] };
        let p = rec.particle();
        assert_ne!(p, Particle::ZERO);
    }

    #[test]
    fn addressed_enum_variants() {
        let a = Status::Active;
        let b = Status::Inactive;
        let c = Status::Suspended(42);
        assert_ne!(a.particle(), b.particle());
        assert_ne!(b.particle(), c.particle());
    }

    // --- Step ---

    #[test]
    fn step_reset_zeros_fields() {
        let mut counters = StepCounters {
            count: 42,
            total: 999,
            active: true,
            maybe: Some(7),
        };
        counters.reset();
        assert_eq!(counters.count, 0);
        assert_eq!(counters.total, 0);
        assert!(!counters.active);
        assert!(counters.maybe.is_none());
    }

    // --- Deterministic ---

    #[test]
    fn deterministic_fn_works() {
        assert_eq!(add_checked(1, 2), Some(3));
        assert_eq!(add_checked(u32::MAX, 1), None);
        assert_eq!(multiply_fixed(3, 7), 21);
    }

    // --- Cell: Counter ---

    #[test]
    fn cell_trait_constants() {
        assert_eq!(Counter::NAME, "Counter");
        assert_eq!(Counter::VERSION, 1);
        assert_eq!(Counter::BUDGET, Duration::from_millis(100));
        assert_eq!(Counter::HEARTBEAT, Duration::from_secs(1));
    }

    #[test]
    fn cell_constructor() {
        let cell = Counter::new();
        assert_eq!(cell.current_step(), 0);
        assert_eq!(cell.get(), 0);
    }

    #[test]
    fn cell_increment_and_limit() {
        let mut cell = Counter::new();
        // limit defaults to 0, so first increment should fail
        // Actually Default for u32 is 0, so limit is 0
        let result = cell.increment();
        assert!(result.is_err());
    }

    #[test]
    fn cell_health_check() {
        let cell = Counter::new();
        assert_eq!(cell.health_check(), HealthStatus::Healthy);
    }

    #[test]
    fn cell_step_reset() {
        let mut cell = Counter::new();
        // step_state.increments starts at 0 (default)
        cell.reset_step_state();
        // Should still be 0 after reset
        assert_eq!(cell.get(), 0);
    }

    #[test]
    fn cell_metadata_interface() {
        let sigs = Counter::interface();
        let names: Vec<&str> = sigs.iter().map(|s| s.name).collect();
        assert!(names.contains(&"get"), "missing 'get' in interface");
        assert!(names.contains(&"increment"), "missing 'increment' in interface");
        // internal_check is private — should not appear
        assert!(!names.contains(&"internal_check"), "private fn leaked to interface");
    }

    #[test]
    fn cell_error_type_exists() {
        // CounterError should exist and have LimitReached variant
        let _err: CounterError = CounterError::LimitReached;
        // Debug should be derived
        let _ = format!("{:?}", _err);
    }

    // --- Cell: Minimal ---

    #[test]
    fn minimal_cell() {
        let cell = Minimal::new();
        assert_eq!(Minimal::NAME, "Minimal");
        assert_eq!(Minimal::VERSION, 1);
        assert!(!cell.is_alive()); // bool defaults to false
    }

    #[test]
    fn minimal_cell_metadata() {
        let sigs = Minimal::interface();
        assert_eq!(sigs.len(), 1);
        assert_eq!(sigs[0].name, "is_alive");
    }
}

Homonyms

cyb/optica/src/lib.rs
soft3/strata/src/lib.rs
cyb/honeycrisp/src/lib.rs
warriors/trisha/honeycrisp/lib.rs
warriors/trisha/wgpu/lib.rs
soft3/glia/import/lib.rs
soft3/foculus/src/lib.rs
soft3/nox/rs/lib.rs
soft3/cybergraph/src/lib.rs
soft3/tru/rs/lib.rs
soft3/mudra/src/lib.rs
soft3/glia/run/lib.rs
cyb/prysm/rs/lib.rs
warriors/trisha/rs/lib.rs
cyb/src-tauri/src/lib.rs
soft3/mir/src/lib.rs
soft3/lens/src/lib.rs
neural/trident/src/lib.rs
neural/rune/rs/subject/lib.rs
cyb/cyb/cyb-services/src/lib.rs
soft3/strata/nebu/rs/lib.rs
soft3/lens/core/src/lib.rs
neural/rs/mir-format/src/lib.rs
soft3/zheng/rs/src/lib.rs
neural/rune/rs/interp/lib.rs
soft3/radio/iroh-willow/src/lib.rs
neural/rune/rs/parse/lib.rs
neural/eidos/rs/src/lib.rs
neural/rs/darwin-sys/src/lib.rs
soft3/radio/iroh-gossip/src/lib.rs
soft3/radio/iroh-ffi/src/lib.rs
soft3/radio/iroh-car/src/lib.rs
soft3/radio/iroh-relay/src/lib.rs
soft3/bbg/rs/src/lib.rs
soft3/radio/iroh-docs/src/lib.rs
soft3/lens/ikat/src/lib.rs
neural/rune/rs/lex/lib.rs
cyb/honeycrisp/aruminium/src/lib.rs
soft3/hemera/rs/src/lib.rs
neural/rune/rs/ast/lib.rs
soft3/radio/iroh-blobs/src/lib.rs
cyb/honeycrisp/acpu/src/lib.rs
soft3/lens/porphyry/src/lib.rs
cyb/honeycrisp/rane/src/lib.rs
neural/rune/rs/compile/lib.rs
neural/rune/rs/parse-pure/lib.rs
neural/rs/codegen/src/lib.rs
soft3/lens/binius/src/lib.rs
neural/rune/rs/prysm/lib.rs
neural/rs/link/src/lib.rs
neural/rune/rs/mold/lib.rs
soft3/strata/proof/src/lib.rs
soft3/lens/brakedown/src/lib.rs
soft3/strata/kuro/rs/lib.rs
soft3/lens/assayer/src/lib.rs
neural/rs/core/src/lib.rs
neural/rs/macros/src/lib.rs
soft3/radio/cyber-bao/src/lib.rs
soft3/strata/compute/src/lib.rs
soft3/radio/iroh-base/src/lib.rs
soft3/radio/iroh-dns-server/src/lib.rs
neural/rune/rs/lower/lib.rs
soft3/strata/ext/src/lib.rs
soft3/strata/core/src/lib.rs
soft3/hemera/wgsl/src/lib.rs
soft3/radio/iroh/src/lib.rs
cyb/honeycrisp/unimem/src/lib.rs
cyb/evy/crates/evy_engine_tasks/src/lib.rs
cyb/evy/crates/evy_dialect/src/lib.rs
cyb/wysm/crates/wasi/src/lib.rs
cyb/wysm/crates/fuzz/src/lib.rs
soft3/strata/genies/rs/src/lib.rs
cyb/evy/crates/evy_platform_caps/src/lib.rs
neural/inf/rs/oracle/src/lib.rs
soft3/strata/jali/wgsl/src/lib.rs
cyb/evy/forks/bevy_transform/src/lib.rs
soft3/tape/impl/rust/src/lib.rs
cyb/wysm/crates/wasmi/src/lib.rs
cyb/evy/forks/bevy_render/src/lib.rs
cyb/evy/crates/evy_ecs_storage/src/lib.rs
cyb/evy/forks/naga/src/lib.rs
soft3/strata/trop/wgsl/src/lib.rs
cyb/wysm/crates/c_api/artifact/lib.rs
cyb/evy/forks/bevy_ecs/src/lib.rs
cyb/wysm/crates/ir/src/lib.rs
cyb/evy/forks/bevy_animation/src/lib.rs
cyb/evy/forks/bevy_sprite_render/src/lib.rs
cyb/wysm/crates/c_api/src/lib.rs
neural/inf/rs/parse/src/lib.rs
soft3/strata/trop/rs/src/lib.rs
soft3/strata/kuro/wgsl/src/lib.rs
neural/trident/editor/zed/src/lib.rs
cyb/evy/forks/bevy_mesh/src/lib.rs
cyb/evy/crates/evy_radio/src/lib.rs
cyb/evy/forks/bevy_anti_alias/src/lib.rs
soft3/strata/jali/rs/src/lib.rs
cyb/wysm/crates/wast/src/lib.rs
neural/inf/rs/plan/src/lib.rs
soft3/radio/iroh-ffi/iroh-js/src/lib.rs
cyb/evy/forks/bevy_image/src/lib.rs
cyb/evy/forks/bevy_post_process/src/lib.rs
neural/inf/rs/source/src/lib.rs
cyb/wysm/crates/core/src/lib.rs
cyb/evy/crates/evy_diagnostic/src/lib.rs
cyb/evy/crates/evy_engine_dispatch/src/lib.rs
cyb/evy/forks/bevy_pbr/src/lib.rs
cyb/evy/forks/bevy_gizmos/src/lib.rs
cyb/evy/forks/bevy_gizmos_render/src/lib.rs
soft3/radio/iroh/bench/src/lib.rs
neural/inf/rs/lex/src/lib.rs
neural/inf/rs/ast/src/lib.rs
soft3/strata/genies/wgsl/src/lib.rs
soft3/strata/nebu/wgsl/src/lib.rs
cyb/wysm/crates/collections/src/lib.rs
neural/inf/rs/lower/src/lib.rs
cyb/evy/forks/bevy_sprite/src/lib.rs
cyb/evy/forks/bevy_diagnostic/src/lib.rs
neural/inf/rs/eval/src/lib.rs
cyb/wysm/crates/c_api/macro/lib.rs
cyb/evy/forks/bevy_tasks/src/lib.rs
cyb/evy/forks/bevy_core_pipeline/src/lib.rs
cyb/evy/crates/evy_prysm_core/src/lib.rs
neural/inf/rs/value/src/lib.rs
cyb/evy/crates/evy_engine_core/src/lib.rs
soft3/radio/tests/integration/src/lib.rs
bootloader/go-cyber/cw/packages/cyber-std-test/src/lib.rs
bootloader/go-cyber/cw/contracts/std-test/src/lib.rs
bootloader/go-cyber/cw/contracts/graph-filter/src/lib.rs
bootloader/go-cyber/cw/packages/cyber-std/src/lib.rs

Graph