spectral_vm 0.1.6

HYPERION: Production-ready zero-knowledge virtual machine with spectral analysis
Documentation
/*
 * ═══════════════════════════════════════════════════════════════════════════
 * UNIT TESTS: Sovereign Virtual Machine
 * ═══════════════════════════════════════════════════════════════════════════
 */

use spectral_vm::field::Goldilocks;
use spectral_vm::vm::{SovereignVM, SpectralOp, InstructionRecord};

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

    #[test]
    fn test_vm_creation() {
        let mem_size = 1024;
        let vm = SovereignVM::new(mem_size);

        assert_eq!(vm.registers.len(), 32); // Default register count
        assert_eq!(vm.memory.len(), mem_size);
        assert!(vm.instruction_trace.is_empty());
    }

    #[test]
    fn test_vm_basic_execution() {
        let mut vm = SovereignVM::new(1024);

        // Test ADD instruction: R1 = R2 + R3
        vm.registers[2] = Goldilocks::from_i64(10);
        vm.registers[3] = Goldilocks::from_i64(20);

        let instr = ((SpectralOp::S_ADD as u64) << 16) | (1 << 8) | 2;
        vm.execute_instruction(instr);

        assert_eq!(vm.registers[1].0, 30);
        assert_eq!(vm.instruction_trace.len(), 1);
    }

    #[test]
    fn test_vm_memory_operations() {
        let mut vm = SovereignVM::new(1024);

        // Test STORE: memory[R1] = R2
        vm.registers[1] = Goldilocks::from_i64(100); // address
        vm.registers[2] = Goldilocks::from_i64(42);  // value

        let store_instr = ((SpectralOp::S_STORE as u64) << 16) | (1 << 8) | 2;
        vm.execute_instruction(store_instr);

        // Test LOAD: R3 = memory[R1]
        vm.registers[3] = Goldilocks::from_i64(0); // clear register
        let load_instr = ((SpectralOp::S_LOAD as u64) << 16) | (3 << 8) | 1;
        vm.execute_instruction(load_instr);

        assert_eq!(vm.registers[3].0, 42);
    }

    #[test]
    fn test_vm_arithmetic_operations() {
        let mut vm = SovereignVM::new(1024);

        // Test MUL
        vm.registers[1] = Goldilocks::from_i64(6);
        vm.registers[2] = Goldilocks::from_i64(7);
        let mul_instr = ((SpectralOp::S_MUL as u64) << 16) | (0 << 8) | 1; // R0 = R1 * R2
        vm.execute_instruction(mul_instr);
        assert_eq!(vm.registers[0].0, 42);

        // Test SUB
        vm.registers[3] = Goldilocks::from_i64(100);
        vm.registers[4] = Goldilocks::from_i64(25);
        let sub_instr = ((SpectralOp::S_SUB as u64) << 16) | (5 << 8) | 3; // R5 = R3 - R4
        vm.execute_instruction(sub_instr);
        assert_eq!(vm.registers[5].0, 75);
    }

    #[test]
    fn test_vm_instruction_trace() {
        let mut vm = SovereignVM::new(1024);

        // Execute a few instructions
        vm.registers[1] = Goldilocks::from_i64(10);
        vm.registers[2] = Goldilocks::from_i64(20);

        let add_instr = ((SpectralOp::S_ADD as u64) << 16) | (0 << 8) | 1;
        vm.execute_instruction(add_instr);

        let mul_instr = ((SpectralOp::S_MUL as u64) << 16) | (3 << 8) | 2;
        vm.execute_instruction(mul_instr);

        assert_eq!(vm.instruction_trace.len(), 2);

        // Check first instruction trace
        let trace0 = &vm.instruction_trace[0];
        assert_eq!(trace0.op, SpectralOp::S_ADD);
        assert_eq!(trace0.operand1.0, 10);
        assert_eq!(trace0.operand2.0, 0); // ADD uses two registers
        assert_eq!(trace0.result.0, 10); // Result after ADD
    }

    #[test]
    fn test_vm_edge_cases() {
        let mut vm = SovereignVM::new(1024);

        // Test with zero
        vm.registers[0] = Goldilocks::from_i64(0);
        vm.registers[1] = Goldilocks::from_i64(42);

        let add_instr = ((SpectralOp::S_ADD as u64) << 16) | (2 << 8) | 0;
        vm.execute_instruction(add_instr);
        assert_eq!(vm.registers[2].0, 42);

        // Test invalid register access (should not panic in this implementation)
        // VM should handle gracefully
        let invalid_instr = ((SpectralOp::S_ADD as u64) << 16) | (99 << 8) | 0; // Invalid register
        // This should not crash the VM - implementation dependent
        vm.execute_instruction(invalid_instr);
    }

    #[test]
    fn test_vm_memory_bounds() {
        let mut vm = SovereignVM::new(1024);

        // Test memory access within bounds
        vm.registers[0] = Goldilocks::from_i64(100);
        vm.registers[1] = Goldilocks::from_i64(999);

        let store_instr = ((SpectralOp::S_STORE as u64) << 16) | (0 << 8) | 1;
        vm.execute_instruction(store_instr);

        // Memory should be updated
        assert_eq!(vm.memory[100].0, 999);
    }

    #[test]
    fn test_instruction_record_creation() {
        let record = InstructionRecord {
            pc: 42,
            op: SpectralOp::S_ADD,
            operand1: Goldilocks::from_i64(10),
            operand2: Goldilocks::from_i64(20),
            result: Goldilocks::from_i64(30),
            clk: Goldilocks::from_i64(1),
        };

        assert_eq!(record.pc, 42);
        assert_eq!(record.result.0, 30);
        assert_eq!(record.clk.0, 1);
    }

    #[test]
    fn test_vm_serialization() {
        let mut vm = SovereignVM::new(1024);
        vm.registers[0] = Goldilocks::from_i64(123);

        // Test that VM components can be serialized
        let serialized = serde_json::to_string(&vm.registers).unwrap();
        let deserialized: Vec<Goldilocks> = serde_json::from_str(&serialized).unwrap();

        assert_eq!(vm.registers[0], deserialized[0]);
    }
}