Adding a couple of tests
This commit is contained in:
parent
76302b4ca8
commit
c7828a4940
|
@ -2,6 +2,8 @@ pub mod call_stack;
|
|||
pub mod config;
|
||||
pub mod enviroment_calls;
|
||||
pub mod regs;
|
||||
#[cfg(test)]
|
||||
pub mod tests;
|
||||
|
||||
use {
|
||||
self::call_stack::CallStack,
|
||||
|
@ -66,7 +68,7 @@ pub struct Engine {
|
|||
pub last_timer_count: u32,
|
||||
pub timer_callback: Option<fn() -> u32>,
|
||||
pub memory: memory::Memory,
|
||||
pub enviroment_call_table: [EnviromentCall; 256],
|
||||
pub enviroment_call_table: [Option<EnviromentCall>; 256],
|
||||
pub call_stack: CallStack,
|
||||
}
|
||||
use crate::engine::enviroment_calls::EnviromentCall;
|
||||
|
@ -87,7 +89,7 @@ impl Engine {
|
|||
let _ = mem.set_addr8(addr as u64, byte);
|
||||
}
|
||||
trace!("{:?}", mem.read_addr8(0));
|
||||
|
||||
let ecall_table: [Option<EnviromentCall>; 256] = [None; 256];
|
||||
Self {
|
||||
index: 0,
|
||||
program,
|
||||
|
@ -95,7 +97,7 @@ impl Engine {
|
|||
config: EngineConfig::default(),
|
||||
last_timer_count: 0,
|
||||
timer_callback: None,
|
||||
enviroment_call_table: [empty_enviroment_call; 256],
|
||||
enviroment_call_table: ecall_table,
|
||||
memory: mem,
|
||||
call_stack: Vec::new(),
|
||||
}
|
||||
|
@ -187,6 +189,9 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
|||
}
|
||||
pub fn run(&mut self) -> Result<HaltStatus, RuntimeErrors> {
|
||||
use {HaltStatus::*, RuntimeErrors::*};
|
||||
if self.program.len() == 0 {
|
||||
return Ok(Halted);
|
||||
}
|
||||
loop {
|
||||
// Break out of the loop
|
||||
if self.index + 1 == self.program.len() {
|
||||
|
@ -425,7 +430,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
|||
|
||||
let addr = usize::from_be_bytes(addr_array);
|
||||
if addr > self.program.len() {
|
||||
panic!("Invalid jump address {}", addr)
|
||||
return Err(InvalidJumpAddress(addr as u64));
|
||||
} else {
|
||||
let call = FnCall { ret: self.index };
|
||||
self.call_stack.push(call);
|
||||
|
@ -434,7 +439,6 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
|||
trace!("Jumping to {}", addr);
|
||||
|
||||
self.dump();
|
||||
// panic!();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,9 +456,8 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
|||
self.index += 2;
|
||||
}
|
||||
|
||||
_op_pair => {
|
||||
// println!("OP Pair {}", op_pair.0);
|
||||
self.index += 1;
|
||||
op_pair => {
|
||||
panic!("OP Pair {} - {}", op_pair.0, op_pair.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -465,6 +468,7 @@ F5-F9 {:016X} {:016X} {:016X} {:016X} {:016X}",
|
|||
if (ret - self.last_timer_count) >= self.config.quantum {
|
||||
return Ok(Running);
|
||||
}
|
||||
self.last_timer_count = ret;
|
||||
}
|
||||
}
|
||||
Ok(Halted)
|
||||
|
|
42
hbvm/src/engine/tests/mod.rs
Normal file
42
hbvm/src/engine/tests/mod.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use {
|
||||
super::Engine,
|
||||
crate::{HaltStatus, RuntimeErrors},
|
||||
alloc::vec,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn empty_program() {
|
||||
let prog = vec![];
|
||||
let mut eng = Engine::new(prog);
|
||||
let ret = eng.run();
|
||||
assert_eq!(ret, Ok(HaltStatus::Halted));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn max_quantum_reached() {
|
||||
let prog = vec![0, 0, 0, 0];
|
||||
let mut eng = Engine::new(prog);
|
||||
eng.set_timer_callback(|| {
|
||||
return 1;
|
||||
});
|
||||
eng.config.quantum = 1;
|
||||
let ret = eng.run();
|
||||
assert_eq!(ret, Ok(HaltStatus::Running));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jump_out_of_bounds() {
|
||||
use crate::engine::Operations::JUMP;
|
||||
let prog = vec![JUMP as u8, 0, 0, 0, 0, 0, 0, 1, 0];
|
||||
let mut eng = Engine::new(prog);
|
||||
let ret = eng.run();
|
||||
assert_eq!(ret, Err(RuntimeErrors::InvalidJumpAddress(256)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_system_call() {
|
||||
let prog = vec![255, 0];
|
||||
let mut eng = Engine::new(prog);
|
||||
let ret = eng.run();
|
||||
// assert_eq!(ret, );
|
||||
}
|
|
@ -5,15 +5,17 @@ pub mod bytecode;
|
|||
pub mod engine;
|
||||
pub mod memory;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum RuntimeErrors {
|
||||
InvalidOpcode(u8),
|
||||
RegisterTooSmall,
|
||||
HostError(u64),
|
||||
PageNotMapped(u64),
|
||||
InvalidJumpAddress(u64),
|
||||
}
|
||||
|
||||
// If you solve the halting problem feel free to remove this
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum HaltStatus {
|
||||
Halted,
|
||||
Running,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use holey_bytes::{
|
||||
use hbvm::{
|
||||
bytecode::ops::{Operations::*, RWSubTypes::*, SubTypes::*},
|
||||
engine::Engine,
|
||||
RuntimeErrors,
|
||||
|
@ -8,7 +8,7 @@ fn main() -> Result<(), RuntimeErrors> {
|
|||
#[rustfmt::skip]
|
||||
let prog: Vec<u8> = vec![
|
||||
NOP as u8, NOP as u8,
|
||||
10, 10,
|
||||
255, 10,
|
||||
ADD as u8, EightBit as u8, 100, 20, 0xA7,
|
||||
ADD as u8,
|
||||
EightBit as u8, 1, 0, 0xB0,
|
||||
|
@ -17,11 +17,11 @@ fn main() -> Result<(), RuntimeErrors> {
|
|||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 2, 0xD0,
|
||||
SUB as u8, EightBit as u8, 255, 0, 0xA7,
|
||||
DIV as u8, EightBit as u8, 12, 5, 0xA8,
|
||||
ADD as u8, Register8 as u8, 0xA7, 0xB0, 0xA7,
|
||||
LOAD as u8, AddrToReg as u8,
|
||||
0, 0, 0, 0, 0, 0, 0, 2,
|
||||
0xA0,
|
||||
// JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
JUMP as u8, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue