vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
// regression/tests.rs is itself the test module — no inner `mod tests` wrapper.
// Helper fns are private in the parent mod, so we use `super::` to reach them.
#![cfg(test)]

use super::hex::sha256_hex;
use super::{
    decode_hex, encode_hex, from_hex, load, load_failures_versioned, nibble, regression_dir,
    sanitize, save,
};
use crate::spec::types::ParityFailure;
use std::fs;

#[test]
fn hex_roundtrip() {
    let original = vec![0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF];
    let encoded = encode_hex(&original);
    let decoded = decode_hex(&encoded).unwrap();
    assert_eq!(original, decoded);
}

#[test]
fn nibble_values() {
    assert_eq!(nibble(0), '0');
    assert_eq!(nibble(9), '9');
    assert_eq!(nibble(10), 'a');
    assert_eq!(nibble(15), 'f');
}

#[test]
fn from_hex_valid() {
    assert_eq!(from_hex(b'0').unwrap(), 0);
    assert_eq!(from_hex(b'9').unwrap(), 9);
    assert_eq!(from_hex(b'a').unwrap(), 10);
    assert_eq!(from_hex(b'F').unwrap(), 15);
}

#[test]
fn from_hex_invalid() {
    assert!(from_hex(b'G').is_err());
    assert!(from_hex(b' ').is_err());
}

#[test]
fn sha256_deterministic() {
    let a = sha256_hex(b"hello");
    let b = sha256_hex(b"hello");
    assert_eq!(a, b);
    assert_eq!(a.len(), 64);
}

#[test]
fn sha256_differs() {
    let a = sha256_hex(b"hello");
    let b = sha256_hex(b"world");
    assert_ne!(a, b);
}

#[test]
fn load_nonexistent_dir_returns_empty() {
    let result = load("this.op.does.not.exist.test.12345");
    assert!(result.is_empty());
}

#[test]
fn save_and_load_roundtrip() {
    let failure = ParityFailure {
        op_id: "test.roundtrip.op".to_string(),
        generator: "test".to_string(),
        input_label: "case1".to_string(),
        input: vec![0xCA, 0xFE, 0xBA, 0xBE],
        gpu_output: vec![0x00],
        cpu_output: vec![0xFF],
        message: "test failure".to_string(),
        spec_version: 1,
        workgroup_size: 1,
    };
    save(&failure).unwrap();

    let loaded = load("test.roundtrip.op");
    assert!(!loaded.is_empty(), "expected at least one regression input");
    let found = loaded
        .iter()
        .any(|(_, bytes)| *bytes == vec![0xCA, 0xFE, 0xBA, 0xBE]);
    assert!(found, "did not find the saved regression input");

    let failures = load_failures_versioned("test.roundtrip.op", 1);
    assert_eq!(failures, vec![failure]);

    let dir = regression_dir("test.roundtrip.op");
    let _ = fs::remove_dir_all(dir);
}

#[test]
fn sanitize_preserves_distinct_namespaces() {
    assert_ne!(sanitize("math.add"), sanitize("math_add"));
    assert_eq!(sanitize("math.add"), "math%2Eadd");
    assert_eq!(sanitize("math_add"), "math_add");
}