#[cfg(test)]
mod tests {
use crate::op_code::Opcode::{OpAdd, OpClosure, OpConst, OpGetLocal};
use crate::op_code::*;
use std::collections::HashSet;
use strum::EnumCount;
#[test]
fn test_make() {
struct Test {
op: Opcode,
operands: Vec<usize>,
expected: Vec<u8>,
}
let tests = vec![
Test {
op: Opcode::OpConst,
operands: vec![65534],
expected: vec![OpConst as u8, 255, 254],
},
Test { op: Opcode::OpAdd, operands: vec![], expected: vec![OpAdd as u8] },
Test {
op: Opcode::OpGetLocal,
operands: vec![255],
expected: vec![OpGetLocal as u8, 255],
},
];
for t in tests {
let ins = make_instructions(t.op, &t.operands);
assert_eq!(ins.data, t.expected)
}
}
#[test]
fn test_read_operands() {
struct Test {
op: Opcode,
operands: Vec<usize>,
bytes_read: usize,
}
let tests = vec![
Test { op: Opcode::OpConst, operands: vec![65534], bytes_read: 2 },
Test { op: Opcode::OpConst, operands: vec![255], bytes_read: 2 },
];
for t in tests {
let ins = make_instructions(t.op, &t.operands);
let (operands_read, n) = read_operands(DEFINITIONS.get(&t.op).unwrap(), &ins.data[1..]);
assert_eq!(operands_read, t.operands);
assert_eq!(n, t.bytes_read);
}
}
#[test]
fn test_instructions_legal() {
let opcode_count = Opcode::COUNT;
let keys_count = DEFINITIONS.keys().count();
let op_keys = DEFINITIONS
.values()
.map(|d| d.name.to_string())
.collect::<HashSet<String>>();
assert_eq!(opcode_count, keys_count);
assert_eq!(opcode_count, op_keys.len());
}
#[test]
fn test_instructions_string() {
let ins = vec![
make_instructions(OpAdd, &vec![]),
make_instructions(OpGetLocal, &vec![1]),
make_instructions(OpConst, &vec![2]),
make_instructions(OpConst, &vec![65535]),
make_instructions(OpClosure, &vec![65535, 255])
];
let expected = "0000 OpAdd\n\
0001 OpGetLocal 1\n\
0003 OpConst 2\n\
0006 OpConst 65535\n\
0009 OpClosure 65535 255\n";
let merged_ins = ins
.iter()
.fold(vec![], |sum, i| [sum.as_slice(), i.data.as_slice()].concat());
let concatted = Instructions { data: merged_ins }.string();
assert_eq!(concatted, expected);
}
}