vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
#[cfg(loom)]
use loom::sync::{Mutex, Once};
#[cfg(not(loom))]
use std::sync::{Mutex, Once};
use vyre::ir::{BufferAccess, DataTypeSizeBytes, Program};
use vyre_reference;
use crate::spec::value::Value;

#[cfg(test)]
mod tests {
    use super::*;

    struct GoodBackend {
        output: Vec<Value>,
    }

    impl HarnessBackend for GoodBackend {
        fn name(&self) -> &str {
            "good-mock"
        }

        fn run_with_byte_length(
            &self,
            _program: &Program,
            _inputs: &[Value],
        ) -> Result<(Vec<Value>, usize), String> {
            let bytes = super::values_to_bytes(&self.output)?;
            Ok((self.output.clone(), bytes.len()))
        }
    }

    struct BadBackend;

    impl HarnessBackend for BadBackend {
        fn name(&self) -> &str {
            "bad-mock"
        }

        fn run_with_byte_length(
            &self,
            _program: &Program,
            _inputs: &[Value],
        ) -> Result<(Vec<Value>, usize), String> {
            Err("mock backend failure".to_string())
        }
    }

    #[test]
    fn backend_registry_includes_reference() {
        let backends = backend_registry();
        assert!(
            backends.iter().any(|b| b.name() == "reference"),
            "registry must contain reference backend"
        );
    }

    #[test]
    fn register_backend_extends_registry() {
        let leaked: &'static dyn HarnessBackend = Box::leak(Box::new(GoodBackend {
            output: vec![Value::U32(42)],
        }));
        register_backend(leaked);

        let backends = backend_registry();
        assert!(
            backends.iter().any(|b| b.name() == "good-mock"),
            "registry must contain newly registered backend"
        );
    }

    #[test]
    fn with_every_backend_yields_results() {
        let program = Program::new(vec![], [1, 1, 1], vec![vyre::ir::Node::Return]);
        let inputs: &[Value] = &[];

        let leaked_good: &'static dyn HarnessBackend = Box::leak(Box::new(GoodBackend {
            output: vec![Value::U32(7)],
        }));
        let leaked_bad: &'static dyn HarnessBackend = Box::leak(Box::new(BadBackend));
        register_backend(leaked_good);
        register_backend(leaked_bad);

        let mut names = Vec::new();
        let mut ok_count = 0usize;
        let mut err_count = 0usize;

        with_every_backend(&program, inputs, |name, result| {
            names.push(name.to_string());
            match result {
                Ok(_) => ok_count += 1,
                Err(_) => err_count += 1,
            }
        });

        assert!(
            names.contains(&"reference".to_string()),
            "reference must run"
        );
        assert!(
            names.contains(&"good-mock".to_string()),
            "good-mock must run"
        );
        assert!(names.contains(&"bad-mock".to_string()), "bad-mock must run");
        assert!(ok_count >= 2, "expected at least two successes");
        assert!(err_count >= 1, "expected at least one failure");
    }
}