aboutsummaryrefslogtreecommitdiff
path: root/vm/test/vm_test.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-03-02 20:03:52 -0800
committer3gg <3gg@shellblade.net>2023-03-02 20:03:52 -0800
commit664006b1c42aae84a3c749d9b71c1047e0b8ffcf (patch)
treee08f8af944b132742b3bb1d240d8954328e667e5 /vm/test/vm_test.c
Initial commit.HEADmain
Diffstat (limited to 'vm/test/vm_test.c')
-rw-r--r--vm/test/vm_test.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/vm/test/vm_test.c b/vm/test/vm_test.c
new file mode 100644
index 0000000..2d1a91f
--- /dev/null
+++ b/vm/test/vm_test.c
@@ -0,0 +1,182 @@
1#include "vm.h"
2
3#include "test.h"
4
5#include <stdio.h>
6
7/// Create and destroy a vm.
8TEST_CASE(vm_create_destroy) {
9 Vm* vm = vm_new();
10 TEST_TRUE(vm != 0);
11 vm_del(&vm);
12}
13
14// Exit with an implicit 0 exit code.
15TEST_CASE(vm_exit_implicit) {
16 // clang-format off
17 const Inst instructions[] = {
18 vmExit(),
19 };
20 // clang-format on
21
22 Vm* vm = vm_new();
23 TEST_TRUE(vm != 0);
24 const int exit_code =
25 vm_run(vm, instructions, sizeof(instructions) / sizeof(Inst));
26 TEST_TRUE(exit_code == 0);
27 vm_del(&vm);
28}
29
30// Exit with an explicit exit code.
31TEST_CASE(vm_exit_explicit) {
32 const int32_t expected = 17;
33
34 // clang-format off
35 const Inst instructions[] = {
36 vmPushI32(expected),
37 vmExit(),
38 };
39 // clang-format on
40
41 Vm* vm = vm_new();
42 TEST_TRUE(vm != 0);
43 const int exit_code =
44 vm_run(vm, instructions, sizeof(instructions) / sizeof(Inst));
45 TEST_TRUE(exit_code == expected);
46 vm_del(&vm);
47}
48
49/// Add two i32 numbers.
50TEST_CASE(vm_add_i32) {
51 const int n1 = 2;
52 const int n2 = 3;
53
54 // clang-format off
55 const Inst instructions[] = {
56 vmPushI32(n1),
57 vmPushI32(n2),
58 vmAdd(I32),
59 vmExit(),
60 };
61 // clang-format on
62
63 Vm* vm = vm_new();
64 TEST_TRUE(vm != 0);
65 const int exit_code =
66 vm_run(vm, instructions, sizeof(instructions) / sizeof(Inst));
67 TEST_EQUAL(exit_code, n1 + n2);
68 vm_del(&vm);
69}
70
71/// Sum an array of numbers with 4 add instructions.
72TEST_CASE(vm_sum_array_i32_explicit) {
73 const int vals[5] = {1, 2, 3, 4, 5};
74
75 // clang-format off
76 const Inst instructions[] = {
77 vmPushI32(vals[0]),
78 vmPushI32(vals[1]),
79 vmPushI32(vals[2]),
80 vmPushI32(vals[3]),
81 vmPushI32(vals[4]),
82 vmAdd(I32),
83 vmAdd(I32),
84 vmAdd(I32),
85 vmAdd(I32),
86 vmExit(),
87 };
88 // clang-format on
89
90 int sum = 0;
91 for (size_t i = 0; i < sizeof(vals) / sizeof(vals[0]); ++i) {
92 sum += vals[i];
93 }
94
95 Vm* vm = vm_new();
96 TEST_TRUE(vm != 0);
97 const int exit_code =
98 vm_run(vm, instructions, sizeof(instructions) / sizeof(Inst));
99 TEST_EQUAL(exit_code, sum);
100 vm_del(&vm);
101}
102
103/// Sum an array of numbers with a loop.
104TEST_CASE(vm_sum_array_i32_loop) {
105 const int vals[5] = {1, 2, 3, 4, 5};
106
107 const Label loop_label = 0;
108 const Label counter_index = 0;
109
110 // clang-format off
111 const Inst instructions[] = {
112 vmPushI32(vals[0]),
113 vmPushI32(vals[1]),
114 vmPushI32(vals[2]),
115 vmPushI32(vals[3]),
116 vmPushI32(vals[4]),
117 vmLocal(I32, counter_index),
118 vmPushI32(sizeof(vals) / sizeof(vals[0]) - 1),
119 vmLocalWr(I32, counter_index),
120 vmLoop(loop_label),
121 vmAdd(I32),
122 vmLocalRd(I32, counter_index),
123 vmDec(I32),
124 // TODO: Could be useful to have a function that writes the local but
125 // leaves its value on the stack.
126 vmLocalWr(I32, counter_index),
127 vmLocalRd(I32, counter_index),
128 // TODO: Perhaps we should expect the comparison value to also be pushed
129 // to the stack.
130 vmCmpI32(0),
131 vmBr_if(false, loop_label),
132 vmEnd(),
133 vmExit(),
134 };
135 // clang-format on
136
137 int sum = 0;
138 for (size_t i = 0; i < sizeof(vals) / sizeof(vals[0]); ++i) {
139 sum += vals[i];
140 }
141
142 Vm* vm = vm_new();
143 TEST_TRUE(vm != 0);
144 const int exit_code =
145 vm_run(vm, instructions, sizeof(instructions) / sizeof(Inst));
146 TEST_EQUAL(exit_code, sum);
147 vm_del(&vm);
148}
149
150// Call a function to add two numbers.
151TEST_CASE(vm_function_call) {
152 const Label func = 0;
153 const Label a = 0;
154 const Label b = 1;
155 const int32_t a_val = 3;
156 const int32_t b_val = 5;
157 const int32_t expected = a + b;
158
159 // clang-format off
160 const Inst instructions[] = {
161 /* Function definition */
162 vmFunc(func),
163 vmArg(I32, b),
164 vmArg(I32, a),
165 vmAdd(I32),
166 vmEnd(),
167 /* Main program */
168 vmPushI32(a_val),
169 vmPushI32(b_val),
170 vmCall(func),
171 vmExit(),
172 };
173 // clang-format on
174
175 Vm* vm = vm_new();
176 TEST_TRUE(vm != 0);
177 // const int exit_code =
178 // vm_run(vm, instructions, sizeof(instructions) / sizeof(Inst));
179 vm_del(&vm);
180}
181
182int main() { return 0; }