Skip to content

5.1 Propagation Contract Tests

Raul Cardenas Montoya edited this page Sep 19, 2026 · 1 revision

Propagation Contract Tests

Relevant source files

The following files were used as context for generating this wiki page:

Purpose and Scope

This wiki page covers the integration and contract test suites defined in tests/propagate_contract.rs, tests/propagate_into.rs, and tests/propagate_into_alloc.rs. These tests pin the core behavioral contracts of SynapticMesh, ensuring exact mathematical consistency, input validation atomicity, and strict zero-allocation performance guarantees across allocating and buffer-reusing propagation paths.

Sources: tests/propagate_contract.rs:1-49, tests/propagate_into.rs:1-9, tests/propagate_into_alloc.rs:1-9


1. Core Consumer Contract and Fixture (tests/propagate_contract.rs)

The consumer contract test suite establishes the ground-truth semantics for spike delivery, synaptic delays, polarity signs, and current summation tests/propagate_contract.rs:3-31. It evaluates these against a deterministic, hand-built 4-neuron, 5-synapse fixture graph that complies with Dale's law tests/propagate_contract.rs:32-88.

Title: "Propagation Fixture and Contract Flow"

graph TD
    subgraph NaturalLanguage["Natural Language Space"]
        A["SourceSpike"] -->|Delay0| B["ImmediateDelivery"]
        A -->|Delay1| C["BufferedDelivery"]
        A -->|Delay2| D["DelayedDelivery"]
        E["InhibitoryPolarity"] -->|SignFlip| F["SubtractedCurrent"]
    end

    subgraph CodeSpace["Code Entity Space"]
        SM["SynapticMesh::propagate"] -->|Descriptors| SG["SynapticGraph::from_descriptors"]
        SG -->|MeshState| TM["SynapticMesh::new"]
        TM -->|BufferTick| P["Polarity::Inhibitory / Excitatory"]
    end

    NaturalLanguage -.-> CodeSpace

Sources: tests/propagate_contract.rs:3-48, tests/propagate_contract.rs:50-88

The test file enforces five primary rules of the propagation contract:

  1. Delay & Timing: A spike from source $s$ on tick $t$ delivers weight to targets on tick $t + \text{delay}$. A delay of 0 results in same-tick delivery appearing in the return value of the active SynapticMesh::propagate call tests/propagate_contract.rs:11-14.
  2. Polarity: Synaptic weight magnitude is scaled by the descriptor's Polarity; Polarity::Inhibitory subtracts current tests/propagate_contract.rs:15-19.
  3. Summation: Currents arriving at the same neuron on the same tick are summed tests/propagate_contract.rs:20.
  4. Single-Hop Semantics: SynapticMesh::propagate executes exactly one network hop. Received currents never trigger spikes internally; spike generation is the responsibility of the external consumer neuron model tests/propagate_contract.rs:21-23.
  5. Determinism: Identical graphs and spike sequences yield bit-identical current traces, both across runs and following SynapticMesh::reset tests/propagate_contract.rs:24-25.

Sources: tests/propagate_contract.rs:3-31, tests/propagate_contract.rs:113-169


2. Buffer Reuse Equivalence and Error Atomicity (tests/propagate_into.rs)

The tests/propagate_into.rs integration suite verifies that zero-allocation caller-buffer methods (SynapticMesh::propagate_into and SynapticMesh::propagate_graded_into) are functionally equivalent to their allocating counterparts across diverse structural topologies (small-world, scale-free, random, and layered) [tests/propagate_into.rs:3-8], tests/propagate_into.rs:64-167.

Title: "Buffer Reuse Equivalence and Error Atomicity Architecture"

graph TD
    subgraph NaturalLanguage["Natural Language Space"]
        T1["AllocatingPath"] -->|Equals| T2["BufferReusePath"]
        E1["InvalidInputSize"] -->|TriggersError| E2["FullStateRollback"]
    end

    subgraph CodeSpace["Code Entity Space"]
        SM1["SynapticMesh::propagate"] -->|CompareVectors| SM2["SynapticMesh::propagate_into"]
        GM1["SynapticMesh::propagate_graded"] -->|CompareVectors| GM2["SynapticMesh::propagate_graded_into"]
        ERR["MeshErrorInfo"] -->|PreservesTick| TICK["SynapticMesh::tick"]
    end

    NaturalLanguage -.-> CodeSpace

Sources: tests/propagate_into.rs:3-8, tests/propagate_into.rs:64-102, tests/propagate_into.rs:170-201

Error Atomicity Guarantees

When propagation inputs fail validation (e.g., mismatched slice lengths or overflow conditions), the mesh guarantees strict atomicity:

Sources: tests/propagate_into.rs:3-9, tests/propagate_into.rs:170-201


3. Allocation Guarantees and Global Allocator (tests/propagate_into_alloc.rs)

To guarantee that runtime simulation loops remain free of heap allocations, tests/propagate_into_alloc.rs implements a dedicated integration test binary equipped with a custom global allocator tests/propagate_into_alloc.rs:3-9.

struct CountingAlloc;

static ALLOCATIONS: AtomicU64 = AtomicU64::new(0);

unsafe impl GlobalAlloc for CountingAlloc {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        ALLOCATIONS.fetch_add(1, Ordering::SeqCst);
        unsafe { System.alloc(layout) }
    }
    // ... realloc, alloc_zeroed, dealloc forwarded to System
}

#[global_allocator]
static GLOBAL: CountingAlloc = CountingAlloc;

Sources: tests/propagate_into_alloc.rs:10-46

Allocation Verification Flow

  1. Initialization occurs outside the measured window via SynapticMesh::new, which allocates internal ring buffers and graph structures [tests/propagate_into_alloc.rs:5-8], tests/propagate_into_alloc.rs:57-60.
  2. The test loop executes multiple consecutive ticks of boolean and graded propagation into pre-allocated scratch buffers tests/propagate_into_alloc.rs:67-93.
  3. allocation_delta asserts that the allocation counter delta during propagate_into and propagate_graded_into is strictly 0 [tests/propagate_into.rs:48-53], tests/propagate_into_alloc.rs:81-93.

Sources: tests/propagate_into_alloc.rs:3-9, tests/propagate_into_alloc.rs:48-94

Clone this wiki locally