mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-31 01:25:21 +00:00
feat(tests): add C, C++, Scala, Fortran, Octave test harnesses
Test harnesses added for all remaining AVM ISA ports: - C (9 tests): arithmetic, saturation, comparison, overflow, control flow, locals - C++ (9 tests): same test suite with std::optional-based error handling - Scala (9 tests): functional style with Option return - Fortran (4 tests): add, div, saturation, control flow (minimal Fortran test) - Octave/MATLAB (4 tests): basic operations test Milestone: 10/12 ports have test harnesses. Coq still pending.
This commit is contained in:
parent
f6cbddcbf2
commit
64e54d937d
6 changed files with 455 additions and 5 deletions
152
c/test_avm.c
Normal file
152
c/test_avm.c
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/* AVM ISA v1 — C Test Harness */
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "avm.c"
|
||||
|
||||
void test_basic_add() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_Q16, 5 * Q16_SCALE, 0},
|
||||
{OP_PUSH_Q16, 3 * Q16_SCALE, 0},
|
||||
{OP_PRIM, PRIM_ADD_Q16, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, 4, 100);
|
||||
assert(err == 0);
|
||||
assert(s.halted);
|
||||
assert(s.stack[0].val.i == 8 * Q16_SCALE);
|
||||
printf(" ✅ basic_add: 5 + 3 = 8\n");
|
||||
}
|
||||
|
||||
void test_div_q16() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_Q16, 3 * Q16_SCALE, 0},
|
||||
{OP_PUSH_Q16, 5 * Q16_SCALE, 0},
|
||||
{OP_PRIM, PRIM_DIV_Q16, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, 4, 100);
|
||||
assert(err == 0);
|
||||
int expected = (3 * Q16_SCALE) / 5;
|
||||
assert(s.stack[0].val.i == expected);
|
||||
printf(" ✅ div_q16: 3/5 = 0.6\n");
|
||||
}
|
||||
|
||||
void test_saturation() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_Q16, AVM_CLAMP_MAX - 1, 0},
|
||||
{OP_PUSH_Q16, 2, 0},
|
||||
{OP_PRIM, PRIM_ADD_Q16, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, 4, 100);
|
||||
assert(err == 0);
|
||||
assert(s.stack[0].val.i == AVM_CLAMP_MAX);
|
||||
printf(" ✅ saturation: max-1+2 = max\n");
|
||||
}
|
||||
|
||||
void test_v6_lt() {
|
||||
struct { int a, b; int exp; } cases[] = {
|
||||
{-5*Q16_SCALE, -3*Q16_SCALE, 1},
|
||||
{-3*Q16_SCALE, -5*Q16_SCALE, 0},
|
||||
{5*Q16_SCALE, 3*Q16_SCALE, 0},
|
||||
{3*Q16_SCALE, 5*Q16_SCALE, 1},
|
||||
{-1*Q16_SCALE, 2*Q16_SCALE, 1},
|
||||
};
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_Q16, cases[i].a, 0},
|
||||
{OP_PUSH_Q16, cases[i].b, 0},
|
||||
{OP_PRIM, PRIM_LT_Q16, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
run(&s, prog, 4, 100);
|
||||
assert(s.stack[0].val.b == cases[i].exp);
|
||||
}
|
||||
printf(" ✅ v6_lt: 5 cases pass\n");
|
||||
}
|
||||
|
||||
void test_type_mismatch() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_BOOL, 0, 1},
|
||||
{OP_PUSH_Q16, Q16_SCALE, 0},
|
||||
{OP_PRIM, PRIM_ADD_Q16, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, 3, 100);
|
||||
assert(err != 0);
|
||||
printf(" ✅ type_mismatch: rejected\n");
|
||||
}
|
||||
|
||||
void test_div_by_zero() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_Q16, Q16_SCALE, 0},
|
||||
{OP_PUSH_Q16, 0, 0},
|
||||
{OP_PRIM, PRIM_DIV_Q16, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, 3, 100);
|
||||
assert(err != 0);
|
||||
printf(" ✅ div_by_zero: rejected\n");
|
||||
}
|
||||
|
||||
void test_stack_overflow() {
|
||||
Instr prog[AVM_MAX_STACK + 2];
|
||||
for (int i = 0; i < AVM_MAX_STACK + 1; i++)
|
||||
prog[i] = (Instr){OP_PUSH_Q16, 0, 0};
|
||||
prog[AVM_MAX_STACK + 1] = (Instr){OP_HALT, 0, 0};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, AVM_MAX_STACK + 2, 100);
|
||||
assert(err != 0);
|
||||
printf(" ✅ stack_overflow: rejected\n");
|
||||
}
|
||||
|
||||
void test_control_flow() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_BOOL, 0, 1},
|
||||
{OP_JUMP_IF, 4, 0},
|
||||
{OP_PUSH_Q16, 0, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
{OP_PUSH_Q16, Q16_SCALE, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
};
|
||||
State s; init_state(&s, 0);
|
||||
int err = run(&s, prog, 6, 100);
|
||||
assert(err == 0);
|
||||
assert(s.stack[0].val.i == Q16_SCALE);
|
||||
printf(" ✅ control_flow: jump_if true\n");
|
||||
}
|
||||
|
||||
void test_locals() {
|
||||
Instr prog[] = {
|
||||
{OP_PUSH_Q16, 42 * Q16_SCALE, 0},
|
||||
{OP_STORE, 0, 0},
|
||||
{OP_LOAD, 0, 0},
|
||||
{OP_HALT, 0, 0},
|
||||
};
|
||||
State s; init_state(&s, 1);
|
||||
int err = run(&s, prog, 4, 100);
|
||||
assert(err == 0);
|
||||
assert(s.stack[0].val.i == 42 * Q16_SCALE);
|
||||
printf(" ✅ locals: store+load\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("AVM C Port — Test Harness\n");
|
||||
printf("=========================\n");
|
||||
test_basic_add();
|
||||
test_div_q16();
|
||||
test_saturation();
|
||||
test_v6_lt();
|
||||
test_type_mismatch();
|
||||
test_div_by_zero();
|
||||
test_stack_overflow();
|
||||
test_control_flow();
|
||||
test_locals();
|
||||
printf("\nAll C tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
102
cpp/test_avm.cpp
Normal file
102
cpp/test_avm.cpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// AVM ISA v1 — C++ Test Harness
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include "avm.hpp"
|
||||
using namespace avm;
|
||||
|
||||
#define QS Q16_SCALE
|
||||
|
||||
void test_basic_add() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushQ16, 5 * QS}, {Op::PushQ16, 3 * QS},
|
||||
{Op::Primitive, static_cast<int32_t>(Prim::AddSatQ16)}, {Op::Halt}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
assert(s->stack[0].val == 8 * QS);
|
||||
std::cout << " ✅ basic_add: 5 + 3 = 8\n";
|
||||
}
|
||||
|
||||
void test_div_q16() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushQ16, 3 * QS}, {Op::PushQ16, 5 * QS},
|
||||
{Op::Primitive, static_cast<int32_t>(Prim::DivSatQ16)}, {Op::Halt}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
int exp = (3 * QS) / 5;
|
||||
assert(std::get<int32_t>(s->stack[0].val) == exp);
|
||||
std::cout << " ✅ div_q16: 3/5 = 0.6\n";
|
||||
}
|
||||
|
||||
void test_saturation() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushQ16, AVM_CLAMP_MAX - 1}, {Op::PushQ16, 2},
|
||||
{Op::Primitive, static_cast<int32_t>(Prim::AddSatQ16)}, {Op::Halt}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
assert(std::get<int32_t>(s->stack[0].val) == AVM_CLAMP_MAX);
|
||||
std::cout << " ✅ saturation: max-1+2 = max\n";
|
||||
}
|
||||
|
||||
void test_v6_lt() {
|
||||
struct Case { int32_t a, b; bool exp; } cases[] = {
|
||||
{-5*QS, -3*QS, true}, {-3*QS, -5*QS, false},
|
||||
{5*QS, 3*QS, false}, {3*QS, 5*QS, true}, {-1*QS, 2*QS, true}};
|
||||
for (auto c : cases) {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushQ16, c.a}, {Op::PushQ16, c.b},
|
||||
{Op::Primitive, static_cast<int32_t>(Prim::LtQ16)}, {Op::Halt}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
assert(std::get<bool>(s->stack[0].val) == c.exp);
|
||||
}
|
||||
std::cout << " ✅ v6_lt: 5 cases pass\n";
|
||||
}
|
||||
|
||||
void test_type_mismatch() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushBool, 0, true}, {Op::PushQ16, QS},
|
||||
{Op::Primitive, static_cast<int32_t>(Prim::AddSatQ16)}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
assert(!s.has_value());
|
||||
std::cout << " ✅ type_mismatch: rejected\n";
|
||||
}
|
||||
|
||||
void test_div_by_zero() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushQ16, QS}, {Op::PushQ16, 0},
|
||||
{Op::Primitive, static_cast<int32_t>(Prim::DivSatQ16)}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
assert(!s.has_value());
|
||||
std::cout << " ✅ div_by_zero: rejected\n";
|
||||
}
|
||||
|
||||
void test_stack_overflow() {
|
||||
auto prog = std::vector<Instr>(AVM_MAX_STACK + 1, Instr{Op::PushQ16, 0});
|
||||
auto s = run(init_state(), prog, 10000);
|
||||
assert(!s.has_value());
|
||||
std::cout << " ✅ stack_overflow: rejected\n";
|
||||
}
|
||||
|
||||
void test_control_flow() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushBool, 0, true}, {Op::JumpIf, 4},
|
||||
{Op::PushQ16, 0}, {Op::Halt},
|
||||
{Op::PushQ16, QS}, {Op::Halt}};
|
||||
auto s = run(init_state(), prog, 100);
|
||||
assert(std::get<int32_t>(s->stack[0].val) == QS);
|
||||
std::cout << " ✅ control_flow: jump_if true\n";
|
||||
}
|
||||
|
||||
void test_locals() {
|
||||
auto prog = std::vector<Instr>{
|
||||
{Op::PushQ16, 42 * QS}, {Op::Store, 0},
|
||||
{Op::Load, 0}, {Op::Halt}};
|
||||
auto s = run(init_state(1), prog, 100);
|
||||
assert(std::get<int32_t>(s->stack[0].val) == 42 * QS);
|
||||
std::cout << " ✅ locals: store+load\n";
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "AVM C++ Port — Test Harness\n=========================\n";
|
||||
test_basic_add(); test_div_q16(); test_saturation(); test_v6_lt();
|
||||
test_type_mismatch(); test_div_by_zero(); test_stack_overflow();
|
||||
test_control_flow(); test_locals();
|
||||
std::cout << "\nAll C++ tests passed.\n";
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -14,12 +14,12 @@ test harness.
|
|||
| 4 | Coq | `coq-lsp` | `coq/AVMIsa/avm.v` | ❌ | ❌ | 🔄 |
|
||||
| 5 | R | — | `r/AVMIsa/avm.r` | `test_avm.r` | ✅ | ✅ |
|
||||
| 6 | Julia | — | `julia/AVMIsa/avm.jl` | `test_avm.jl` | ✅ | ✅ |
|
||||
| 7 | Scala | `metals` | `scala/avm.scala` | ❌ | ❌ | 🔄 |
|
||||
| 7 | Scala | `metals` | `scala/avm.scala` | `scala/TestAVM.scala` | ❌ | 🔄 |
|
||||
| 8 | Go | — | `go/avm.go` | `go/avm_test.go` | ❌ | 🔄 |
|
||||
| 9 | C | `clangd` | `c/avm.c` | ❌ | ❌ | 🔄 |
|
||||
| 10 | C++ | `clangd` | `cpp/avm.hpp` | ❌ | ❌ | 🔄 |
|
||||
| 11 | Fortran | `fortls` | `fortran/avm.f90` | ❌ | ❌ | 🔄 |
|
||||
| 12 | Octave | — | `octave/avm.m` | ❌ | ❌ | 🔄 |
|
||||
| 9 | C | `clangd` | `c/avm.c` | `c/test_avm.c` | ❌ | 🔄 |
|
||||
| 10 | C++ | `clangd` | `cpp/avm.hpp` | `cpp/test_avm.cpp` | ❌ | 🔄 |
|
||||
| 11 | Fortran | `fortls` | `fortran/avm.f90` | `fortran/test_avm.f90` | ❌ | 🔄 |
|
||||
| 12 | Octave | — | `octave/avm.m` | `octave/test_avm.m` | ❌ | 🔄 |
|
||||
|
||||
## 1:1 Verification Protocol
|
||||
|
||||
|
|
|
|||
58
fortran/test_avm.f90
Normal file
58
fortran/test_avm.f90
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
! AVM ISA v1 — Fortran Test Harness
|
||||
program test_avm
|
||||
use avm
|
||||
implicit none
|
||||
|
||||
type(State) :: s
|
||||
type(Instr), target :: prog(10)
|
||||
integer :: err, expected
|
||||
|
||||
print *, "AVM Fortran Port — Test Harness"
|
||||
print *, "==============================="
|
||||
|
||||
! Test basic add: 5 + 3 = 8
|
||||
prog(1)%op = OP_PUSH_Q16; prog(1)%arg = 5 * Q16_SCALE
|
||||
prog(2)%op = OP_PUSH_Q16; prog(2)%arg = 3 * Q16_SCALE
|
||||
prog(3)%op = OP_PRIM; prog(3)%arg = PRIM_ADD_Q16
|
||||
prog(4)%op = OP_HALT
|
||||
s = State(0, .false.); s%pc = 0
|
||||
err = step(s, prog, 4)
|
||||
if (s%stack(s%sp)%i == 8 * Q16_SCALE) then; print *, " ✅ basic_add: 5+3=8"
|
||||
else; print *, " ❌ basic_add"; end if
|
||||
|
||||
! Test div: 3/5 = 0.6
|
||||
s = State(0, .false.); s%pc = 0
|
||||
prog(1)%op = OP_PUSH_Q16; prog(1)%arg = 3 * Q16_SCALE
|
||||
prog(2)%op = OP_PUSH_Q16; prog(2)%arg = 5 * Q16_SCALE
|
||||
prog(3)%op = OP_PRIM; prog(3)%arg = PRIM_DIV_Q16
|
||||
prog(4)%op = OP_HALT
|
||||
err = step(s, prog, 4)
|
||||
expected = (3 * Q16_SCALE) / 5
|
||||
if (s%stack(s%sp)%i == expected) then; print *, " ✅ div_q16: 3/5=0.6"
|
||||
else; print *, " ❌ div_q16"; end if
|
||||
|
||||
! Test saturation
|
||||
s = State(0, .false.); s%pc = 0
|
||||
prog(1)%op = OP_PUSH_Q16; prog(1)%arg = AVM_CLAMP_MAX - 1
|
||||
prog(2)%op = OP_PUSH_Q16; prog(2)%arg = 2
|
||||
prog(3)%op = OP_PRIM; prog(3)%arg = PRIM_ADD_Q16
|
||||
prog(4)%op = OP_HALT
|
||||
err = step(s, prog, 4)
|
||||
if (s%stack(s%sp)%i == AVM_CLAMP_MAX) then; print *, " ✅ saturation: ok"
|
||||
else; print *, " ❌ saturation"; end if
|
||||
|
||||
! Test control flow
|
||||
s = State(0, .false.); s%pc = 0
|
||||
prog(1)%op = OP_PUSH_BOOL; prog(1)%arg = 0; prog(1)%arg2 = .true.
|
||||
prog(2)%op = OP_JUMP_IF; prog(2)%arg = 4
|
||||
prog(3)%op = OP_PUSH_Q16; prog(3)%arg = 0
|
||||
prog(4)%op = OP_HALT
|
||||
prog(5)%op = OP_PUSH_Q16; prog(5)%arg = Q16_SCALE
|
||||
prog(6)%op = OP_HALT
|
||||
err = step(s, prog, 6)
|
||||
if (s%stack(s%sp)%i == Q16_SCALE) then; print *, " ✅ control_flow: ok"
|
||||
else; print *, " ❌ control_flow"; end if
|
||||
|
||||
print *, ""
|
||||
print *, "All Fortran tests passed."
|
||||
end program test_avm
|
||||
58
octave/test_avm.m
Normal file
58
octave/test_avm.m
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
% AVM ISA v1 — Octave/MATLAB Test Harness
|
||||
% Run with: octave test_avm.m
|
||||
|
||||
QS = 65536;
|
||||
|
||||
function check(cond, msg)
|
||||
if cond; printf(" ✅ %s\n", msg);
|
||||
else; printf(" ❌ %s\n", msg); end
|
||||
end
|
||||
|
||||
function test_basic_add()
|
||||
prog = {struct('op', AVM.OP_PUSH_Q16, 'arg', int32(5*65536), 'arg2', false), ...
|
||||
struct('op', AVM.OP_PUSH_Q16, 'arg', int32(3*65536), 'arg2', false), ...
|
||||
struct('op', AVM.OP_PRIM, 'arg', int32(AVM.PRIM_ADD_Q16), 'arg2', false), ...
|
||||
struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false)};
|
||||
s = AVM.init_state(0);
|
||||
[s, err] = AVM.step(s, prog);
|
||||
check(s.stack{1}.i == 8*65536, 'basic_add: 5+3=8');
|
||||
end
|
||||
|
||||
function test_div()
|
||||
prog = {struct('op', AVM.OP_PUSH_Q16, 'arg', int32(3*65536), 'arg2', false), ...
|
||||
struct('op', AVM.OP_PUSH_Q16, 'arg', int32(5*65536), 'arg2', false), ...
|
||||
struct('op', AVM.OP_PRIM, 'arg', int32(AVM.PRIM_DIV_Q16), 'arg2', false), ...
|
||||
struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false)};
|
||||
s = AVM.init_state(0);
|
||||
[s, err] = AVM.step(s, prog);
|
||||
expected = floor(double(3*65536) / double(5*65536)) * 65536;
|
||||
check(s.stack{1}.i == expected, 'div_q16: 3/5');
|
||||
end
|
||||
|
||||
function test_saturation()
|
||||
prog = {struct('op', AVM.OP_PUSH_Q16, 'arg', int32(AVM.AVM_CLAMP_MAX - 1), 'arg2', false), ...
|
||||
struct('op', AVM.OP_PUSH_Q16, 'arg', int32(2), 'arg2', false), ...
|
||||
struct('op', AVM.OP_PRIM, 'arg', int32(AVM.PRIM_ADD_Q16), 'arg2', false), ...
|
||||
struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false)};
|
||||
s = AVM.init_state(0);
|
||||
[s, err] = AVM.step(s, prog);
|
||||
check(s.stack{1}.i == AVM.AVM_CLAMP_MAX, 'saturation');
|
||||
end
|
||||
|
||||
function test_locals()
|
||||
prog = {struct('op', AVM.OP_PUSH_Q16, 'arg', int32(42*65536), 'arg2', false), ...
|
||||
struct('op', AVM.OP_STORE, 'arg', int32(0), 'arg2', false), ...
|
||||
struct('op', AVM.OP_LOAD, 'arg', int32(0), 'arg2', false), ...
|
||||
struct('op', AVM.OP_HALT, 'arg', int32(0), 'arg2', false)};
|
||||
s = AVM.init_state(1);
|
||||
[s, err] = AVM.step(s, prog);
|
||||
check(s.stack{1}.i == 42*65536, 'locals: store+load');
|
||||
end
|
||||
|
||||
printf("AVM Octave Port — Test Harness\n");
|
||||
printf("===============================\n");
|
||||
test_basic_add();
|
||||
test_div();
|
||||
test_saturation();
|
||||
test_locals();
|
||||
printf("\nAll Octave tests passed.\n");
|
||||
80
scala/TestAVM.scala
Normal file
80
scala/TestAVM.scala
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// AVM ISA v1 — Scala Test Harness
|
||||
import silversight.avm.AVM._
|
||||
import silversight.avm.AVM
|
||||
|
||||
object TestAVM {
|
||||
val QS = Q16Scale
|
||||
|
||||
def check(cond: Boolean, msg: String): Unit = {
|
||||
if (cond) println(s" ✅ $msg")
|
||||
else println(s" ❌ $msg")
|
||||
}
|
||||
|
||||
def test_basic_add(): Unit = {
|
||||
val prog = Vector(PushQ16(5 * QS), PushQ16(3 * QS), Primitive(AddSatQ16), Halt)
|
||||
val s = run(initState(), prog, 100).get
|
||||
check(s.stack.head.i == 8 * QS, "basic_add: 5 + 3 = 8")
|
||||
}
|
||||
|
||||
def test_div_q16(): Unit = {
|
||||
val prog = Vector(PushQ16(3 * QS), PushQ16(5 * QS), Primitive(DivSatQ16), Halt)
|
||||
val s = run(initState(), prog, 100).get
|
||||
val exp = (3 * QS) / 5
|
||||
check(s.stack.head.i == exp, "div_q16: 3/5 = 0.6")
|
||||
}
|
||||
|
||||
def test_saturation(): Unit = {
|
||||
val prog = Vector(PushQ16(AVMClampMax - 1), PushQ16(2), Primitive(AddSatQ16), Halt)
|
||||
val s = run(initState(), prog, 100).get
|
||||
check(s.stack.head.i == AVMClampMax, "saturation: max-1+2 = max")
|
||||
}
|
||||
|
||||
def test_v6_lt(): Unit = {
|
||||
val cases = Seq((-5*QS, -3*QS, true), (-3*QS, -5*QS, false),
|
||||
(5*QS, 3*QS, false), (3*QS, 5*QS, true), (-1*QS, 2*QS, true))
|
||||
cases.foreach { case (a, b, exp) =>
|
||||
val prog = Vector(PushQ16(a), PushQ16(b), Primitive(LtQ16), Halt)
|
||||
val s = run(initState(), prog, 100).get
|
||||
check(s.stack.head.b == exp, s"v6_lt($a,$b) = $exp")
|
||||
}
|
||||
}
|
||||
|
||||
def test_type_mismatch(): Unit = {
|
||||
val prog = Vector(PushBool(true), PushQ16(QS), Primitive(AddSatQ16))
|
||||
val s = run(initState(), prog, 100)
|
||||
check(s.isEmpty, "type_mismatch: rejected")
|
||||
}
|
||||
|
||||
def test_div_by_zero(): Unit = {
|
||||
val prog = Vector(PushQ16(QS), PushQ16(0), Primitive(DivSatQ16))
|
||||
val s = run(initState(), prog, 100)
|
||||
check(s.isEmpty, "div_by_zero: rejected")
|
||||
}
|
||||
|
||||
def test_stack_overflow(): Unit = {
|
||||
val prog = Vector.fill(AVMMaxStack + 1)(PushQ16(0: Int))
|
||||
val s = run(initState(), prog, 10000)
|
||||
check(s.isEmpty, "stack_overflow: rejected")
|
||||
}
|
||||
|
||||
def test_control_flow(): Unit = {
|
||||
val prog = Vector(PushBool(true), JumpIf(4), PushQ16(0), Halt, PushQ16(QS), Halt)
|
||||
val s = run(initState(), prog, 100).get
|
||||
check(s.stack.head.i == QS, "control_flow: jump_if true")
|
||||
}
|
||||
|
||||
def test_locals(): Unit = {
|
||||
val prog = Vector(PushQ16(42 * QS), Store(0), Load(0), Halt)
|
||||
val s = run(initState(1), prog, 100).get
|
||||
check(s.stack.head.i == 42 * QS, "locals: store+load")
|
||||
}
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
println("AVM Scala Port — Test Harness")
|
||||
println("==============================")
|
||||
test_basic_add(); test_div_q16(); test_saturation(); test_v6_lt()
|
||||
test_type_mismatch(); test_div_by_zero(); test_stack_overflow()
|
||||
test_control_flow(); test_locals()
|
||||
println("\nAll Scala tests passed.")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue