soft3/neuron/node/tests/runtime.rs

use cell_engine::{Config, Engine, Error, Progress};
use cell_model::Lifecycle;
use cell_node::{Graph, Rune};
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};

struct StorePath(PathBuf);
impl StorePath {
    fn new() -> Self {
        static NEXT: AtomicU64 = AtomicU64::new(0);
        let root = std::env::temp_dir().join(format!(
            "cell-runtime-{}-{}",
            std::process::id(),
            NEXT.fetch_add(1, Ordering::Relaxed)
        ));
        std::fs::create_dir(&root).unwrap();
        Self(root)
    }
    fn open(&self) -> Engine<Graph, Rune> {
        Engine::with_ward(
            Graph::open(self.0.join("bbg")).unwrap(),
            Rune,
            cell_node::LocalWard,
        )
    }
}
impl Drop for StorePath {
    fn drop(&mut self) {
        let _ = std::fs::remove_dir_all(&self.0);
    }
}
fn value(source: &str) -> Vec<u8> {
    cell_rune::value(source).unwrap()
}
fn drive(engine: &Engine<Graph, Rune>, cell: [u8; 32]) -> Result<Progress, Error> {
    for _ in 0..100 {
        match engine.tick(cell)? {
            Progress::Advanced(_) => (),
            other => return Ok(other),
        }
    }
    panic!("runtime did not reach a boundary")
}

#[test]
fn two_births_isolate_state_and_reopen_preserves_results_and_deduplication() {
    let path = StorePath::new();
    let (first, second, receipt);
    {
        let engine = path.open();
        first = engine
            .create(
                b"~mem + event".to_vec(),
                value("0"),
                [1; 32],
                Config::default(),
            )
            .unwrap();
        second = engine
            .create(
                b"~mem + event".to_vec(),
                value("0"),
                [2; 32],
                Config::default(),
            )
            .unwrap();
        assert_ne!(first, second);
        receipt = engine
            .submit(first, [3; 32], value("7"), Some(first))
            .unwrap();
        assert!(matches!(
            drive(&engine, first).unwrap(),
            Progress::Complete(_)
        ));
        assert_eq!(engine.inspect(first).unwrap().state, value("7"));
        assert_eq!(engine.inspect(second).unwrap().state, value("0"));
    }
    let engine = path.open();
    assert_eq!(engine.inspect(first).unwrap().state, value("7"));
    assert_eq!(
        engine
            .submit(first, [3; 32], value("7"), Some(first))
            .unwrap(),
        receipt
    );
    assert!(matches!(
        engine.submit(second, [3; 32], value("7"), Some(first)),
        Err(Error::Conflict)
    ));
    assert!(matches!(
        engine.submit(first, [3; 32], value("8"), Some(first)),
        Err(Error::Conflict)
    ));
    engine.submit(first, [4; 32], value("5"), None).unwrap();
    assert!(matches!(
        drive(&engine, first).unwrap(),
        Progress::Complete(_)
    ));
    assert_eq!(engine.inspect(first).unwrap().state, value("12"));
}

#[test]
fn accepted_effect_is_unknown_after_restart_and_recorded_result_resumes_once() {
    const HOST: u64 = 0xAC75_0000_0000_0006;
    let path = StorePath::new();
    let (cell, operation, attempt);
    {
        let engine = path.open();
        cell = engine
            .create(
                b"let x = host(7); ~mem + x".to_vec(),
                value("10"),
                [5; 32],
                Config {
                    allowed_acts: vec![HOST],
                    ..Config::default()
                },
            )
            .unwrap();
        engine
            .submit(cell, [6; 32], value("0"), Some(cell))
            .unwrap();
        operation = match drive(&engine, cell).unwrap() {
            Progress::Awaiting { operation, .. } => operation,
            other => panic!("{other:?}"),
        };
        let receipt = engine.begin_attempt(cell, operation).unwrap();
        attempt = receipt.attempt;
        assert!(matches!(
            engine.begin_attempt(cell, operation),
            Err(Error::UnknownOutcome)
        ));
    }
    let engine = path.open();
    assert!(
        matches!(drive(&engine, cell).unwrap(), Progress::Unknown { operation: op, attempt: at } if op == operation && at == attempt)
    );
    assert_eq!(
        engine.inspect(cell).unwrap().live.unwrap().context,
        Some(cell)
    );
    assert!(matches!(engine.cancel(cell), Err(Error::UnknownOutcome)));
    let receipt = engine
        .record_outcome(cell, operation, attempt, value("32"))
        .unwrap();
    assert!(matches!(
        drive(&engine, cell).unwrap(),
        Progress::Complete(_)
    ));
    assert_eq!(engine.inspect(cell).unwrap().state, value("42"));
    assert_eq!(
        engine
            .record_outcome(cell, operation, attempt, value("32"))
            .unwrap(),
        receipt
    );
    assert!(matches!(
        engine.record_outcome(cell, operation, attempt, value("99")),
        Err(Error::Conflict)
    ));
    assert!(matches!(drive(&engine, cell).unwrap(), Progress::Idle));
}

#[test]
fn lifecycle_and_denied_effects_preserve_state() {
    let path = StorePath::new();
    let engine = path.open();
    let cell = engine
        .create(b"host(1)".to_vec(), value("9"), [7; 32], Config::default())
        .unwrap();
    engine.manage(cell, Lifecycle::Paused).unwrap();
    assert!(matches!(
        engine.submit(cell, [8; 32], value("0"), None),
        Err(Error::Lifecycle)
    ));
    engine.manage(cell, Lifecycle::Active).unwrap();
    engine.submit(cell, [8; 32], value("0"), None).unwrap();
    let op = match drive(&engine, cell).unwrap() {
        Progress::Awaiting { operation, .. } => operation,
        other => panic!("{other:?}"),
    };
    assert!(matches!(engine.begin_attempt(cell, op), Err(Error::Denied)));
    assert_eq!(engine.inspect(cell).unwrap().state, value("9"));
    engine.cancel(cell).unwrap();
    engine.manage(cell, Lifecycle::Retiring).unwrap();
    engine.manage(cell, Lifecycle::Retired).unwrap();
    assert!(matches!(
        engine.manage(cell, Lifecycle::Active),
        Err(Error::Lifecycle)
    ));
}

Homonyms

soft3/radio/iroh/src/runtime.rs
neural/rs/core/src/runtime.rs

Graph