1pub mod opcodes {
5 pub const PUSH: u8 = 0x00;
6 pub const POP: u8 = 0x01;
7 pub const ADD: u8 = 0x06;
8 pub const SUB: u8 = 0x07;
9 pub const MUL: u8 = 0x08;
10 pub const AND: u8 = 0x09;
11 pub const OR: u8 = 0x0A;
12 pub const XOR: u8 = 0x0B;
13 pub const NOT: u8 = 0x0C;
14 pub const EQ: u8 = 0x0F;
15 pub const NEQ: u8 = 0x10;
16 pub const LT: u8 = 0x11;
17 pub const GT: u8 = 0x12;
18 pub const JUMP: u8 = 0x15;
19 pub const JZ: u8 = 0x16;
20 pub const HALT: u8 = 0x1A;
21 pub const ASSERT: u8 = 0x1B;
22 pub const GUARD_TRAP: u8 = 0x20;
23 pub const NOP: u8 = 0x27;
24}
25
26pub struct TestVector {
28 pub name: &'static str,
29 pub bytecode: &'static [u8],
30 pub expected_stack_top: u8,
31 pub should_halt: bool,
32 pub category: &'static str,
33}
34
35pub fn all_vectors() -> Vec<TestVector> {
37 use opcodes::*;
38 vec![
39 TestVector { name: "identity", bytecode: &[PUSH, 42, HALT], expected_stack_top: 42, should_halt: true, category: "basic" },
40 TestVector { name: "add_3_4", bytecode: &[PUSH, 3, PUSH, 4, ADD, HALT], expected_stack_top: 7, should_halt: true, category: "arithmetic" },
41 TestVector { name: "mul_6_7", bytecode: &[PUSH, 6, PUSH, 7, MUL, HALT], expected_stack_top: 42, should_halt: true, category: "arithmetic" },
42 TestVector { name: "sub_10_3", bytecode: &[PUSH, 10, PUSH, 3, SUB, HALT], expected_stack_top: 7, should_halt: true, category: "arithmetic" },
43 TestVector { name: "and_mask", bytecode: &[PUSH, 0xFF, PUSH, 0x0F, AND, HALT], expected_stack_top: 0x0F, should_halt: true, category: "bitwise" },
44 TestVector { name: "or_combine", bytecode: &[PUSH, 0xF0, PUSH, 0x0F, OR, HALT], expected_stack_top: 0xFF, should_halt: true, category: "bitwise" },
45 TestVector { name: "xor_toggle", bytecode: &[PUSH, 0xAA, PUSH, 0x55, XOR, HALT], expected_stack_top: 0xFF, should_halt: true, category: "bitwise" },
46 TestVector { name: "not_invert", bytecode: &[PUSH, 0x00, NOT, HALT], expected_stack_top: 0xFF, should_halt: true, category: "bitwise" },
47 TestVector { name: "eq_same", bytecode: &[PUSH, 7, PUSH, 7, EQ, HALT], expected_stack_top: 1, should_halt: true, category: "comparison" },
48 TestVector { name: "neq_diff", bytecode: &[PUSH, 3, PUSH, 5, NEQ, HALT], expected_stack_top: 1, should_halt: true, category: "comparison" },
49 TestVector { name: "lt_check", bytecode: &[PUSH, 3, PUSH, 5, LT, HALT], expected_stack_top: 1, should_halt: true, category: "comparison" },
50 TestVector { name: "gt_check", bytecode: &[PUSH, 5, PUSH, 3, GT, HALT], expected_stack_top: 1, should_halt: true, category: "comparison" },
51 TestVector { name: "jz_skip", bytecode: &[PUSH, 0, JZ, 7, PUSH, 99, HALT, PUSH, 42, HALT], expected_stack_top: 42, should_halt: true, category: "control_flow" },
52 TestVector { name: "assert_pass", bytecode: &[PUSH, 1, ASSERT, PUSH, 77, HALT], expected_stack_top: 77, should_halt: true, category: "safety" },
53 TestVector { name: "nops", bytecode: &[NOP, NOP, PUSH, 13, HALT], expected_stack_top: 13, should_halt: true, category: "basic" },
54 ]
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use flux_vm::FluxVM;
61
62 #[test]
63 fn run_all_vectors() {
64 for tv in all_vectors() {
65 let mut vm = FluxVM::new(100);
66 let result = vm.execute(tv.bytecode, 100);
67 assert!(result.is_ok(), "Test '{}' failed: {:?}", tv.name, result);
68 assert_eq!(tv.should_halt, vm.is_halted(), "Test '{}' halt mismatch", tv.name);
69 if tv.should_halt {
70 assert_eq!(Some(tv.expected_stack_top), vm.stack_top(), "Test '{}' stack top mismatch", tv.name);
71 }
72 }
73 }
74}