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));
+}