From 7e044abb53e3890de3b5cf45a45dc33dad26d6f2 Mon Sep 17 00:00:00 2001 From: Jur van den Berg Date: Wed, 23 May 2018 13:40:24 +0200 Subject: [PATCH] Most tests yay --- src/machine.rs | 40 ++++++- src/ops.rs | 33 +++--- src/stack.rs | 10 +- tests/advanced1.rs | 242 +++++++++++++++++++++++++++++++++++++++++ tests/advanced2.rs | 61 +++++++++++ tests/advanced3.rs | 37 +++++++ tests/advanced4.rs | 21 ++++ tests/advancedstack.rs | 69 ++++++++++++ tests/task2.rs | 31 +++--- tests/task3.rs | 128 ++++++++++++++++++++++ tests/task4.rs | 123 +++++++++++++++++++++ tests/task5.rs | 66 +++++++++++ 12 files changed, 820 insertions(+), 41 deletions(-) create mode 100644 tests/advanced1.rs create mode 100644 tests/advanced2.rs create mode 100644 tests/advanced3.rs create mode 100644 tests/advanced4.rs create mode 100644 tests/advancedstack.rs create mode 100644 tests/task3.rs create mode 100644 tests/task4.rs create mode 100644 tests/task5.rs diff --git a/src/machine.rs b/src/machine.rs index 6c3b663..6361961 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -1,5 +1,6 @@ -use block::Block; +use std::io::{Read, Write}; +use block::Block; use ops::Operation; use ijvmreader::IJVMReader; use binread::{BinRead, BinReadable}; @@ -8,26 +9,36 @@ use stack::Stack; use pool::Pool; use netstack::NetStack; use Result; +use std::sync::Mutex; +use std::rc::Rc; const MAGIC_HEADER:u32 = 0x1DEA_DFAD; const ANTI_BS_SIZE:usize = 0xFFFF; pub struct Machine { pub wide: bool, + pub halted: bool, pub pool: Pool, pub block: Block, pub frame: Vec, - pub net: NetStack + pub net: NetStack, + + pub stream_in: Box, + pub stream_out: Rc>, + } impl Machine { pub fn new(pool: Pool, block: Block) -> Machine{ Machine { wide: false, + halted: false, pool, block, frame: vec![Frame::new(ANTI_BS_SIZE)], net: NetStack::new(), + stream_in: Box::new(::std::io::stdin()), + stream_out: Rc::new(Mutex::new(::std::io::stdout())), } } @@ -72,14 +83,25 @@ impl Machine { } } + pub fn run(&mut self) -> Result<()> { + while self.has_step() { + self.step()?; + } + Ok(()) + } + pub fn has_step(&self) -> bool { - self.block.has_i8() + !self.halted && self.block.has_i8() } pub fn get_program_counter(&self) -> usize { self.block.cur() } + pub fn get_tos(&mut self) -> Result { + self.cur_stack().top() + } + pub fn cur_frame(&mut self) -> &mut Frame { self.frame.last_mut().unwrap() } @@ -88,6 +110,10 @@ impl Machine { &mut self.cur_frame().stack } + pub fn cur_instruction(&mut self) -> u8 { + self.block[self.get_program_counter()] + } + // pub fn get_stack_pointer(&self) -> usize { // return self.frame.last().unwrap().stack.len(); // } @@ -99,4 +125,12 @@ impl Machine { } Ok(self.block.read_u8()? as usize) } + + pub fn set_input(&mut self, instream: Box) { + self.stream_in = instream; + } + + pub fn set_output(&mut self, outstream: Rc>) { + self.stream_out = outstream; + } } \ No newline at end of file diff --git a/src/ops.rs b/src/ops.rs index 0ed2c30..9bdff0a 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -2,8 +2,7 @@ use binread::BinRead; use machine::Machine; use frame::Frame; use Result; -use std::io::Write; -use std::io::Read; +use std::io::{Read}; pub type OpFunc = fn(&mut Machine) -> Result<()>; @@ -79,8 +78,10 @@ fn dup(machine: &mut Machine) -> Result<()> { fn out(machine: &mut Machine) -> Result<()> { let val = machine.cur_stack().pop()?; - print!("{}", val as u8 as char); - ::std::io::stdout().flush().unwrap(); + let buffer = [val as u8]; + let mut out = machine.stream_out.lock().unwrap(); + out.write_all(&buffer).unwrap(); + out.flush().unwrap(); Ok(()) } @@ -104,14 +105,10 @@ fn isub(machine: &mut Machine) -> Result<()> { } fn _in(machine: &mut Machine) -> Result<()> { - let char: Option = - ::std::io::stdin() - .bytes() - .next() - .and_then(|r| r.ok()); - let val = match char { - None => 0i32, - Some(i) => i32::from(i) + let mut buffer = [0; 1]; + let val = match machine.stream_in.read_exact(&mut buffer) { + Err(_) => 0i32, + Ok(_) => i32::from(buffer[0]), }; machine.cur_stack().push(val); Ok(()) @@ -122,8 +119,9 @@ fn goto(machine: &mut Machine) -> Result<()> { machine.block.jump(offset) } -fn halt(_: &mut Machine) -> Result<()> { - Err("Halt") +fn halt(machine: &mut Machine) -> Result<()> { + machine.halted = true; + Ok(()) } fn ifeq(machine: &mut Machine) -> Result<()> { @@ -181,7 +179,7 @@ fn swap(machine: &mut Machine) -> Result<()> { fn wide(machine: &mut Machine) -> Result<()> { machine.wide = true; - Ok(()) + machine.step() } fn iload(machine: &mut Machine) -> Result<()> { @@ -208,7 +206,7 @@ fn invokevirtual(machine: &mut Machine) -> Result<()> { let method_index = machine.block.read_u16()?; let invoke_addr = machine.pool.get(method_index as usize)?; let return_addr = machine.get_program_counter(); -// println!("METHOD {}", method_index); + machine.block.seek(invoke_addr as usize)?; let arg_count = machine.block.read_u16()?; let var_count = machine.block.read_u16()?; @@ -224,7 +222,6 @@ fn invokevirtual(machine: &mut Machine) -> Result<()> { cur_stack.pop()?; // Nuke the OBJREF } -// println!("retaddr set {}" ,return_addr); newframe.set(0, return_addr as i32)?; machine.frame.push(newframe); @@ -237,10 +234,8 @@ fn ireturn(machine: &mut Machine) -> Result<()> { Some(a) => a, None => return Err("Got no frame... somehow...") }; -// println!("stack: {:?}", prev_frame.stack); let result = prev_frame.stack.pop()?; let return_addr = prev_frame.get(0)?; -// println!("result: {}\nretaddr: {}", result, return_addr); machine.cur_stack().push(result); machine.block.seek(return_addr as usize) } diff --git a/src/stack.rs b/src/stack.rs index 4466118..2a1f118 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -12,9 +12,13 @@ impl Stack { } } -// pub fn len(&self) -> usize { -// return self.data.len(); -// } + pub fn len(&self) -> usize { + self.data.len() + } + + pub fn get(&self, i: usize) -> i32 { + self.data[i] + } pub fn top(&self) -> Result { Ok(match self.data.last() { diff --git a/tests/advanced1.rs b/tests/advanced1.rs new file mode 100644 index 0000000..8b498a6 --- /dev/null +++ b/tests/advanced1.rs @@ -0,0 +1,242 @@ +extern crate rustijvm; + +use std::rc::Rc; +use std::sync::Mutex; +use std::io::{Cursor, Seek, SeekFrom, Read}; + +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn advanced1() { + let output: Rc>>> = Rc::new(Mutex::new(Cursor::new(Vec::new()))); + let input = Box::new("A".as_bytes()); + let mut machine = rustijvm::Machine::new_from_file("files/task5/all_regular.ijvm").unwrap(); + machine.set_input(input); + machine.set_output(output.clone()); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(16)); + + assert_eq!(0x59, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(16)); + + assert_eq!(0xa7, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x60, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(32)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(33)); + + assert_eq!(0x7e, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(32)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(1)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(2)); + + assert_eq!(0xB0, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(3)); + + assert_eq!(0x64, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(29)); + + assert_eq!(0x00, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(29)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(68)); + + assert_eq!(0x60, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(97)); + + assert_eq!(0xFD, machine.cur_instruction()); + steps(&mut machine, 1); + + { + let mut outstream = output.lock().unwrap(); + outstream.seek(SeekFrom::Start(0)).unwrap(); + let mut buf = [0; 1]; + outstream.read_exact(&mut buf).unwrap(); + assert_eq!(buf[0], 'a' as u8); + } + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0)); + + assert_eq!(0x99, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(-22)); + + assert_eq!(0x9B, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x13, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(65)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x41)); + + assert_eq!(0x9F, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(1)); + + assert_eq!(0x36, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(1)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x84, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(2)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0xFC, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok('A' as i32)); + + assert_eq!(0xFC, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0)); + + assert_eq!(0x99, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(1)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(2)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(3)); + + assert_eq!(0xB6, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(1)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(2)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(3)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(5)); + + assert_eq!(0xB6, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(10)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0)); + + assert_eq!(0x10, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(1)); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(5)); + + assert_eq!(0xB6, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0x15, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(5)); + + assert_eq!(0xAC, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(5)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(10)); + + assert_eq!(0xAC, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(10)); + + assert_eq!(0x00, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0xAC, machine.cur_instruction()); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(10)); + + assert_eq!(0x57, machine.cur_instruction()); + steps(&mut machine, 1); + + assert_eq!(0xFF, machine.cur_instruction()); + steps(&mut machine, 1); +} + diff --git a/tests/advanced2.rs b/tests/advanced2.rs new file mode 100644 index 0000000..993e441 --- /dev/null +++ b/tests/advanced2.rs @@ -0,0 +1,61 @@ +extern crate rustijvm; + +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn advanced2_nested_invoke_simple() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/test-nestedinvoke-simple.ijvm").unwrap(); + + steps(&mut machine, 1); + let pc_main = machine.get_program_counter() + 3; + steps(&mut machine, 1); + + assert_ne!(machine.get_program_counter(), pc_main); + steps(&mut machine, 1); + assert_ne!(machine.get_tos(), Ok(0x9)); + + let pc_magic = machine.get_program_counter() + 3; + steps(&mut machine, 1); + assert_ne!(machine.get_program_counter(), pc_magic); + + let pc_addone = machine.get_program_counter() + 3; + steps(&mut machine, 2); + assert_ne!(machine.get_program_counter(), pc_addone); + assert_eq!(machine.get_program_counter(), pc_magic); + + steps(&mut machine, 1); + assert_ne!(machine.get_program_counter(), pc_magic); + assert_eq!(machine.get_program_counter(), pc_main); +} + +#[test] +fn advanced2_nested_invoke() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/test-nestedinvoke.ijvm").unwrap(); + + steps(&mut machine, 8); + assert_eq!(machine.get_tos(), Ok(0x6)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x9)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x9)); + steps(&mut machine, 1); + assert_ne!(machine.get_tos(), Ok(0x9)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x9)); + steps(&mut machine, 1); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x9)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0xA)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0xA)); + steps(&mut machine, 3); + assert_eq!(machine.get_tos(), Ok(0xA)); +} diff --git a/tests/advanced3.rs b/tests/advanced3.rs new file mode 100644 index 0000000..5370d59 --- /dev/null +++ b/tests/advanced3.rs @@ -0,0 +1,37 @@ +extern crate rustijvm; + +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn advanced3_wide1() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/test-wide1.ijvm").unwrap(); + + steps(&mut machine, 6); + assert_eq!(machine.cur_frame().get(1), Ok(0x1)); + steps(&mut machine, 2); + assert_eq!(machine.cur_frame().get(257), Ok(0x2)); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); +} + +#[test] +fn advanced3_wide2() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/test-wide2.ijvm").unwrap(); + + steps(&mut machine, 6); + assert_eq!(machine.cur_frame().get(1), Ok(0x1)); + steps(&mut machine, 2); + assert_eq!(machine.cur_frame().get(32768), Ok(0x2)); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); +} diff --git a/tests/advanced4.rs b/tests/advanced4.rs new file mode 100644 index 0000000..4ef1d75 --- /dev/null +++ b/tests/advanced4.rs @@ -0,0 +1,21 @@ +extern crate rustijvm; + +use std::rc::Rc; +use std::sync::Mutex; +use std::io::{Cursor, Seek, SeekFrom, Read}; + +#[test] +fn advanced4_tanenbaum() { + let rc = Rc::new(Mutex::new(Cursor::new(Vec::new()))); + let mut machine = rustijvm::Machine::new_from_file("files/advanced/Tanenbaum.ijvm").unwrap(); + machine.set_output(rc.clone()); + machine.run().unwrap(); + + let mut out = rc.lock().unwrap(); + let mut string = String::new(); + + out.seek(SeekFrom::Start(0)).unwrap(); + out.read_to_string(&mut string).unwrap(); + + assert_eq!(string, "OK"); +} diff --git a/tests/advancedstack.rs b/tests/advancedstack.rs new file mode 100644 index 0000000..8f79bc1 --- /dev/null +++ b/tests/advancedstack.rs @@ -0,0 +1,69 @@ +extern crate rustijvm; + +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn advancedstack_100() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/teststack.ijvm").unwrap(); + + steps(&mut machine, 1); + steps(&mut machine, 2 * 100); + assert_eq!(machine.get_tos(), Ok(0x2)); +} + +#[test] +fn advancedstack_3000() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/teststack.ijvm").unwrap(); + + steps(&mut machine, 1); + steps(&mut machine, 2 * 3000); + assert_eq!(machine.get_tos(), Ok(0x2)); +} + +#[test] +fn advancedstack_50000() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/teststack.ijvm").unwrap(); + + steps(&mut machine, 1); + steps(&mut machine, 2 * 50000); + assert_eq!(machine.get_tos(), Ok(0x2)); +} + +#[test] +fn advancedstack_contents() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/teststack.ijvm").unwrap(); + + steps(&mut machine, 1); + steps(&mut machine, 2 * 100); + + let stack = machine.cur_stack(); + let size = stack.len(); + assert!(size >= 100); + + let markers = (0..size).filter(|i| { stack.get(*i) == 0x2 }).count(); + assert!(markers >= 99); +} + +#[test] +fn advancedstack_method() { + let mut machine = rustijvm::Machine::new_from_file("files/advanced/teststack2.ijvm").unwrap(); + + steps(&mut machine, 8); + { + let stack = machine.cur_stack(); + let markers = (0..stack.len()).filter(|i| { stack.get(*i) == 0x2 }).count(); + assert_eq!(markers, 4); + } + + steps(&mut machine, 1); + steps(&mut machine, 2 * 5000); + { + let stack = machine.cur_stack(); + let markers = (0..stack.len()).filter(|i| { stack.get(*i) == 0x2 }).count(); + assert!(markers > 4000); + } +} diff --git a/tests/task2.rs b/tests/task2.rs index 649de47..cf75571 100644 --- a/tests/task2.rs +++ b/tests/task2.rs @@ -2,7 +2,6 @@ extern crate rustijvm; fn steps(machine: &mut rustijvm::Machine, num: usize) { for _ in 0..num { - println!("step"); machine.step().unwrap(); } } @@ -11,78 +10,78 @@ fn steps(machine: &mut rustijvm::Machine, num: usize) { fn task2_simple_bipush() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestBipush1.ijvm").unwrap(); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(42)); + assert_eq!(machine.get_tos(), Ok(42)); } #[test] fn task2_signed_bipush() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestBipush2.ijvm").unwrap(); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(-42)); + assert_eq!(machine.get_tos(), Ok(-42)); } #[test] fn task2_simple_iadd() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestIadd1.ijvm").unwrap(); steps(&mut machine, 3); - assert_eq!(machine.cur_stack().top(), Ok(60)); + assert_eq!(machine.get_tos(), Ok(60)); } #[test] fn task2_signed_iadd() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestIadd2.ijvm").unwrap(); steps(&mut machine, 3); - assert_eq!(machine.cur_stack().top(), Ok(-60)); + assert_eq!(machine.get_tos(), Ok(-60)); } #[test] fn task2_simple_isub() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestIsub1.ijvm").unwrap(); steps(&mut machine, 3); - assert_eq!(machine.cur_stack().top(), Ok(-10)); + assert_eq!(machine.get_tos(), Ok(-10)); } #[test] fn task2_signed_isub() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestIsub2.ijvm").unwrap(); steps(&mut machine, 3); - assert_eq!(machine.cur_stack().top(), Ok(10)); + assert_eq!(machine.get_tos(), Ok(10)); } #[test] fn task2_simple_iand() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestIAND1.ijvm").unwrap(); steps(&mut machine, 5); - assert_eq!(machine.cur_stack().top(), Ok(1)); + assert_eq!(machine.get_tos(), Ok(1)); } #[test] fn task2_simple_ior() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestIOR1.ijvm").unwrap(); steps(&mut machine, 5); - assert_eq!(machine.cur_stack().top(), Ok(127)); + assert_eq!(machine.get_tos(), Ok(127)); } #[test] fn task2_swap() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestSwap1.ijvm").unwrap(); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(10)); + assert_eq!(machine.get_tos(), Ok(10)); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(20)); + assert_eq!(machine.get_tos(), Ok(20)); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(10)); + assert_eq!(machine.get_tos(), Ok(10)); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(20)); + assert_eq!(machine.get_tos(), Ok(20)); } #[test] fn task2_simple_stack_operations() { let mut machine = rustijvm::Machine::new_from_file("files/task2/TestPop1.ijvm").unwrap(); steps(&mut machine, 3); - assert_eq!(machine.cur_stack().top(), Ok(10)); + assert_eq!(machine.get_tos(), Ok(10)); steps(&mut machine, 3); - assert_eq!(machine.cur_stack().top(), Ok(50)); + assert_eq!(machine.get_tos(), Ok(50)); steps(&mut machine, 1); - assert_eq!(machine.cur_stack().top(), Ok(10)); + assert_eq!(machine.get_tos(), Ok(10)); } diff --git a/tests/task3.rs b/tests/task3.rs new file mode 100644 index 0000000..206b74d --- /dev/null +++ b/tests/task3.rs @@ -0,0 +1,128 @@ +extern crate rustijvm; + +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn task3_goto1() { + let mut machine = rustijvm::Machine::new_from_file("files/task3/GOTO1.ijvm").unwrap(); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x31)); + steps(&mut machine, 3); + assert_eq!(machine.get_tos(), Ok(0x33)); + steps(&mut machine, 1); +} + +#[test] +fn task3_goto2() { + let mut machine = rustijvm::Machine::new_from_file("files/task3/GOTO2.ijvm").unwrap(); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x31)); + steps(&mut machine, 3); + assert_eq!(machine.get_tos(), Ok(0x33)); + steps(&mut machine, 3); + assert_eq!(machine.get_tos(), Ok(0x32)); + steps(&mut machine, 1); +} + +#[test] +fn task3_ifeq1() { + let mut machine = rustijvm::Machine::new_from_file("files/task3/IFEQ1.ijvm").unwrap(); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x5)); + + // L2 iteration 1 + steps(&mut machine, 6); + assert_eq!(machine.get_tos(), Ok(0x4)); + steps(&mut machine, 3); + let pc = machine.get_program_counter(); + + // L2 iteration 2 + steps(&mut machine, 6); + assert_eq!(machine.get_tos(), Ok(0x3)); + steps(&mut machine, 3); + assert_eq!(machine.get_program_counter(), pc); + + // L2 iteration 3 + steps(&mut machine, 6); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 3); + assert_eq!(machine.get_program_counter(), pc); + + // L2 iteration 4 + steps(&mut machine, 6); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 3); + assert_eq!(machine.get_program_counter(), pc); + + // L2 iteration 5 + steps(&mut machine, 6); + assert_eq!(machine.get_tos(), Ok(0x0)); + steps(&mut machine, 2); + assert_eq!(machine.get_program_counter(), pc + 15); +} + +#[test] +fn task3_iflt1() { + let mut machine = rustijvm::Machine::new_from_file("files/task3/IFLT1.ijvm").unwrap(); + let mut pc = 0; + + // L1 + steps(&mut machine, 2); + assert_eq!(machine.get_program_counter(), pc + 5); + pc = machine.get_program_counter(); + + // L2 + steps(&mut machine, 2); + assert_eq!(machine.get_program_counter(), pc + 5); + pc = machine.get_program_counter(); + + // L3 + steps(&mut machine, 2); + assert_eq!(machine.get_program_counter(), pc + 5); + pc = machine.get_program_counter(); + + // L4 + steps(&mut machine, 4); + assert_eq!(machine.get_program_counter(), pc + 19); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x37)); +} + +#[test] +fn task3_ificmpeq1() { + let mut machine = rustijvm::Machine::new_from_file("files/task3/IFICMPEQ1.ijvm").unwrap(); + let mut pc = 0; + + // L1 + steps(&mut machine, 3); + assert_eq!(machine.get_program_counter(), pc + 7); + pc = machine.get_program_counter(); + + // L2 + steps(&mut machine, 5); + assert_eq!(machine.get_program_counter(), pc + 10); + pc = machine.get_program_counter(); + + // L3 + steps(&mut machine, 4); + assert_eq!(machine.get_program_counter(), pc + 8); + pc = machine.get_program_counter(); + + // L4 + for _ in 0..3 { + steps(&mut machine, 3); + assert_eq!(machine.get_program_counter(), pc); + pc = machine.get_program_counter() + } + + // L6 + steps(&mut machine, 2); + assert_eq!(machine.get_program_counter(), pc + 9); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x13)); +} diff --git a/tests/task4.rs b/tests/task4.rs new file mode 100644 index 0000000..41f598b --- /dev/null +++ b/tests/task4.rs @@ -0,0 +1,123 @@ +extern crate rustijvm; + +use std::io::{Cursor, Read, Seek, SeekFrom}; +use std::rc::Rc; +use std::sync::Mutex; + +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn task4_ldcw1() { + let mut machine = rustijvm::Machine::new_from_file("files/task4/LoadTest1.ijvm").unwrap(); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); +} + +#[test] +fn task4_simple_load() { + let mut machine = rustijvm::Machine::new_from_file("files/task4/LoadTest3.ijvm").unwrap(); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2a)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2a)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2a)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2a)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 3); + assert_eq!(machine.get_tos(), Ok(0x2a)); +} + +#[test] +fn task4_complex_load() { + let mut machine = rustijvm::Machine::new_from_file("files/task4/LoadTest2.ijvm").unwrap(); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2a)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x0)); + + steps(&mut machine, 2); + assert_eq!(machine.get_tos(), Ok(0x3)); + + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2a)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x0)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x4f)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x4b)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); +} + +#[test] +fn task4_iteration_load() { + let rc = Rc::new(Mutex::new(Cursor::new(Vec::new()))); + + let mut machine = rustijvm::Machine::new_from_file("files/task4/LoadTest4.ijvm").unwrap(); + machine.set_output(rc.clone()); + machine.run().unwrap(); + + let mut out = rc.lock().unwrap(); + let mut string = String::new(); + + out.seek(SeekFrom::Start(0)).unwrap(); + out.read_to_string(&mut string).unwrap(); + + assert_eq!(string, "kjihgfedcbaabcd"); +} + +#[test] +fn task4_iinc() { + let mut machine = rustijvm::Machine::new_from_file("files/task4/IINCTest.ijvm").unwrap(); + + steps(&mut machine, 4); + assert_eq!(machine.cur_frame().get(0), Ok(0)); + assert_eq!(machine.cur_frame().get(1), Ok(0)); + + steps(&mut machine, 1); + assert_eq!(machine.cur_frame().get(0), Ok(0)); + steps(&mut machine, 1); + assert_eq!(machine.cur_frame().get(0), Ok(1)); + steps(&mut machine, 1); + assert_eq!(machine.cur_frame().get(0), Ok(4)); + + steps(&mut machine, 1); + assert_eq!(machine.cur_frame().get(1), Ok(0)); + steps(&mut machine, 1); + assert_eq!(machine.cur_frame().get(1), Ok(-1)); + steps(&mut machine, 1); + assert_eq!(machine.cur_frame().get(1), Ok(-4)); +} diff --git a/tests/task5.rs b/tests/task5.rs new file mode 100644 index 0000000..4529afa --- /dev/null +++ b/tests/task5.rs @@ -0,0 +1,66 @@ +extern crate rustijvm; +fn steps(machine: &mut rustijvm::Machine, num: usize) { + for _ in 0..num { + machine.step().unwrap(); + } +} + +#[test] +fn task5_invokenoargs() { + let mut machine = rustijvm::Machine::new_from_file("files/task5/TestInvokeNoArgs.ijvm").unwrap(); + + steps(&mut machine, 2); + assert_eq!(machine.get_tos(), Ok(0x42)); + steps(&mut machine, 2); + assert_eq!(machine.get_tos(), Ok(0x43)); + steps(&mut machine, 2); + assert_eq!(machine.get_tos(), Ok(0x43)); +} + +#[test] +fn task5_invoke1() { + let mut machine = rustijvm::Machine::new_from_file("files/task5/test-invokevirtual1.ijvm").unwrap(); + + steps(&mut machine, 3); + let pc = machine.get_program_counter(); + steps(&mut machine, 1); + assert_ne!(machine.get_program_counter(), pc + 1); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 2); +} + +#[test] +fn task5_ireturn1() { + let mut machine = rustijvm::Machine::new_from_file("files/task5/test-invokevirtual1.ijvm").unwrap(); + + steps(&mut machine, 6); + assert_eq!(machine.get_tos(), Ok(0x1)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); +} + +#[test] +fn task5_invoke2() { + let mut machine = rustijvm::Machine::new_from_file("files/task5/test-invokevirtual2.ijvm").unwrap(); + + steps(&mut machine, 5); + let pc = machine.get_program_counter(); + steps(&mut machine, 1); + assert_ne!(machine.get_program_counter(), pc + 1); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x3)); + steps(&mut machine, 3); +} + +#[test] +fn task5_ireturn2() { + let mut machine = rustijvm::Machine::new_from_file("files/task5/test-invokevirtual2.ijvm").unwrap(); + + steps(&mut machine, 10); + assert_eq!(machine.get_tos(), Ok(0x5)); + steps(&mut machine, 1); + assert_eq!(machine.get_tos(), Ok(0x2)); +}