compiler/
op_code_test.rs

1#[cfg(test)]
2mod tests {
3    use crate::op_code::Opcode::{OpAdd, OpClosure, OpConst, OpGetLocal};
4    use crate::op_code::*;
5    use std::collections::HashSet;
6    use strum::EnumCount;
7
8    #[test]
9    fn test_make() {
10        struct Test {
11            op: Opcode,
12            operands: Vec<usize>,
13            expected: Vec<u8>,
14        }
15
16        let tests = vec![
17            Test {
18                op: Opcode::OpConst,
19                operands: vec![65534],
20                expected: vec![OpConst as u8, 255, 254],
21            },
22            Test { op: Opcode::OpAdd, operands: vec![], expected: vec![OpAdd as u8] },
23            Test {
24                op: Opcode::OpGetLocal,
25                operands: vec![255],
26                expected: vec![OpGetLocal as u8, 255],
27            },
28        ];
29
30        for t in tests {
31            let ins = make_instructions(t.op, &t.operands);
32            assert_eq!(ins.data, t.expected)
33        }
34    }
35
36    #[test]
37    fn test_read_operands() {
38        struct Test {
39            op: Opcode,
40            operands: Vec<usize>,
41            bytes_read: usize,
42        }
43
44        let tests = vec![
45            Test { op: Opcode::OpConst, operands: vec![65534], bytes_read: 2 },
46            Test { op: Opcode::OpConst, operands: vec![255], bytes_read: 2 },
47        ];
48
49        for t in tests {
50            let ins = make_instructions(t.op, &t.operands);
51            let (operands_read, n) = read_operands(DEFINITIONS.get(&t.op).unwrap(), &ins.data[1..]);
52            assert_eq!(operands_read, t.operands);
53            assert_eq!(n, t.bytes_read);
54        }
55    }
56    #[test]
57    fn test_instructions_legal() {
58        let opcode_count = Opcode::COUNT;
59        let keys_count = DEFINITIONS.keys().count();
60        let op_keys = DEFINITIONS
61            .values()
62            .map(|d| d.name.to_string())
63            .collect::<HashSet<String>>();
64        assert_eq!(opcode_count, keys_count);
65        // description is distinct
66        assert_eq!(opcode_count, op_keys.len());
67    }
68
69    #[test]
70    fn test_instructions_string() {
71        let ins = vec![
72            make_instructions(OpAdd, &vec![]),
73            make_instructions(OpGetLocal, &vec![1]),
74            make_instructions(OpConst, &vec![2]),
75            make_instructions(OpConst, &vec![65535]),
76            make_instructions(OpClosure, &vec![65535, 255])
77        ];
78
79        let expected = "0000 OpAdd\n\
80                             0001 OpGetLocal 1\n\
81                             0003 OpConst 2\n\
82                             0006 OpConst 65535\n\
83                             0009 OpClosure 65535 255\n";
84        // how-to-concatenate-immutable-vectors-in-one-line
85        // https://stackoverflow.com/a/69578632/1713757
86        let merged_ins = ins
87            .iter()
88            .fold(vec![], |sum, i| [sum.as_slice(), i.data.as_slice()].concat());
89
90        let concatted = Instructions { data: merged_ins }.string();
91
92        assert_eq!(concatted, expected);
93    }
94}