Error handling
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
use vasm::assemble_snippet;
|
||||
use vcore::memory::{Memory, PeekPokeExt};
|
||||
use vcore::word::Word;
|
||||
use vcore::CPU;
|
||||
|
||||
fn cpu_test<'a, T: IntoIterator<Item = &'a str>>(code: T) -> CPU {
|
||||
@@ -25,11 +26,15 @@ fn test_rstack<'a, T: IntoIterator<Item = &'a str>>(
|
||||
assert_eq!(cpu.get_call(), expected_rstack);
|
||||
}
|
||||
|
||||
fn test_mem<'a, T: IntoIterator<Item = &'a str>>(code: T, expected_memory: BTreeMap<u32, u8>) {
|
||||
fn test_mem<'a, T: IntoIterator<Item = &'a str>>(
|
||||
code: T,
|
||||
expected_memory: BTreeMap<u32, u8>,
|
||||
) -> CPU {
|
||||
let cpu = cpu_test(code);
|
||||
for (addr, byte) in expected_memory {
|
||||
assert_eq!(cpu.peek8(addr), byte)
|
||||
}
|
||||
cpu
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -174,6 +179,17 @@ fn test_pick() {
|
||||
hlt"
|
||||
.lines(),
|
||||
vec![10, 20, 10],
|
||||
);
|
||||
|
||||
test_stack(
|
||||
".org 1024
|
||||
nop 10
|
||||
nop 20
|
||||
pick 2
|
||||
pick 5
|
||||
hlt"
|
||||
.lines(),
|
||||
vec![10, 20, 0, 0],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -188,7 +204,7 @@ fn test_store() {
|
||||
hlt"
|
||||
.lines(),
|
||||
[(201, 10), (203, 0x56), (204, 0x34), (205, 0x12)].into(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -232,3 +248,176 @@ fn test_sdp() {
|
||||
vec![10, 1021, 265],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_underflow() {
|
||||
test_mem(
|
||||
".org 0x400
|
||||
push 100
|
||||
store 10
|
||||
push onunder
|
||||
setiv 1
|
||||
add 3
|
||||
hlt
|
||||
onunder: push 200
|
||||
store 10
|
||||
hlt"
|
||||
.lines(),
|
||||
[(10, 200)].into(),
|
||||
);
|
||||
|
||||
test_mem(
|
||||
".org 0x400
|
||||
push 100
|
||||
store 10
|
||||
push onrunder
|
||||
setiv 2
|
||||
peekr
|
||||
hlt
|
||||
onrunder: push 200
|
||||
store 10
|
||||
hlt"
|
||||
.lines(),
|
||||
[(10, 200)].into(),
|
||||
);
|
||||
|
||||
test_mem(
|
||||
".org 0x400
|
||||
push 100
|
||||
store 10
|
||||
push onunder
|
||||
setiv 1
|
||||
div 0 ; This div should be an underflow, not a div 0
|
||||
hlt
|
||||
onunder: push 200
|
||||
store 10
|
||||
hlt"
|
||||
.lines(),
|
||||
[(10, 200)].into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_div_zero() {
|
||||
test_mem(
|
||||
".org 0x400
|
||||
push 100
|
||||
store 10
|
||||
push ondiv0
|
||||
setiv 0
|
||||
push 5
|
||||
div 0
|
||||
hlt
|
||||
ondiv0: push 200
|
||||
store 10
|
||||
hlt"
|
||||
.lines(),
|
||||
[(10, 200)].into(),
|
||||
);
|
||||
|
||||
test_mem(
|
||||
".org 0x400
|
||||
push 100
|
||||
store 10
|
||||
push ondiv0
|
||||
setiv 0
|
||||
push 5
|
||||
mod 0 ; Mods can raise this too
|
||||
hlt
|
||||
ondiv0: push 200
|
||||
store 10
|
||||
hlt"
|
||||
.lines(),
|
||||
[(10, 200)].into(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_overflow() {
|
||||
let cpu = test_mem(
|
||||
".org 0x400
|
||||
push onover
|
||||
setiv 3 ; set the overflow handler
|
||||
push 25
|
||||
setsdp 10 ; new stack of five cells
|
||||
pushr 0
|
||||
dup 0 ; spare room for handler; 2 cells left
|
||||
push 1
|
||||
push 2 ; fine so far
|
||||
.org 0x4ff ; bunch of nops and then...
|
||||
push 3 ; boom!
|
||||
store ; never happens
|
||||
onover: hlt"
|
||||
.lines(),
|
||||
[(16, 1), (19, 2)].into(), // expect the two successful pushes to be still there
|
||||
);
|
||||
|
||||
// Data stack now contains the collided pointers
|
||||
assert_eq!(vec![Word::from(22), Word::from(22)], cpu.get_stack());
|
||||
|
||||
// Call stack contains the address of the offending instruction
|
||||
assert_eq!(vec![Word::from(0x4ff)], cpu.get_call());
|
||||
|
||||
// Stack is now the previous bottom values, minus three cells:
|
||||
assert_eq!((22.into(), 16.into()), cpu.sdp());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple_overflow() {
|
||||
let cpu = test_mem(
|
||||
".org 0x400
|
||||
push onover
|
||||
setiv 3 ; set the overflow handler
|
||||
push 25
|
||||
setsdp 10 ; new stack of five cells
|
||||
pushr 0
|
||||
dup 0 ; spare room for handler; 2 cells left
|
||||
push 1
|
||||
push 2 ; fine so far
|
||||
.org 0x4ff ; bunch of nops and then...
|
||||
add 5 ; full stack + argument!
|
||||
store ; never happens
|
||||
onover: hlt"
|
||||
.lines(),
|
||||
[(16, 1), (19, 2)].into(), // expect the two successful pushes to be still there
|
||||
);
|
||||
|
||||
// Data stack now contains the collided pointers
|
||||
assert_eq!(vec![Word::from(22), Word::from(22)], cpu.get_stack());
|
||||
|
||||
// Call stack contains the address of the offending instruction
|
||||
assert_eq!(vec![Word::from(0x4ff)], cpu.get_call());
|
||||
|
||||
// Stack is now the previous bottom values, minus three cells:
|
||||
assert_eq!((22.into(), 16.into()), cpu.sdp());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_overflow_promotion() {
|
||||
let cpu = test_mem(
|
||||
".org 0x400
|
||||
push onover
|
||||
setiv 3 ; set the overflow handler
|
||||
push 25
|
||||
setsdp 10 ; new stack of five cells
|
||||
pushr 0
|
||||
dup 0 ; spare room for handler; 2 cells left
|
||||
push 1
|
||||
push 0 ; fine so far
|
||||
.org 0x4ff ; bunch of nops and then...
|
||||
div ; This is a div 0, but there's no room to handle it, so it's promoted to overflow
|
||||
store ; never happens
|
||||
onover: hlt"
|
||||
.lines(),
|
||||
[(16, 1), (19, 0)].into(), // expect the two successful pushes to be still there
|
||||
);
|
||||
|
||||
// Data stack now contains the collided pointers
|
||||
assert_eq!(vec![Word::from(22), Word::from(22)], cpu.get_stack());
|
||||
|
||||
// Call stack contains the address of the offending instruction
|
||||
assert_eq!(vec![Word::from(0x4ff)], cpu.get_call());
|
||||
|
||||
// Stack is now the previous bottom values, minus three cells:
|
||||
assert_eq!((22.into(), 16.into()), cpu.sdp());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user