#[cfg(test)]
mod tests {
use crate::class_file::ClassFile;
use crate::class_file::ParseError;
use crate::class_loader::{ClassLoader, parse_classpath};
use crate::debug::{DebugConfig, JvmDebugger};
use crate::error::{
ClassLoadingError, JvmError, to_class_loading_error, to_parse_error, to_runtime_error,
};
use crate::memory::{Heap, HeapArray, Monitor, StackFrame, Value};
use std::path::PathBuf;
fn minimal_class_file_bytes() -> Vec<u8> {
vec![
0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x34, 0x00, 0x03, 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x07, 0x00, 0x01, 0x00, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]
}
#[test]
fn test_class_file_invalid_magic() {
let bad_magic = vec![
0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00, 0x34, 0x00, 0x03, 0x01, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F,
0x07, 0x00, 0x01, 0x00, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
];
let result = ClassFile::parse(&bad_magic);
assert!(result.is_err());
if let Err(ParseError::InvalidMagic(magic)) = result {
assert_eq!(magic, 0xDEADBEEF);
} else {
panic!("Expected InvalidMagic error");
}
}
#[test]
fn test_class_file_invalid_constant_pool_tag() {
let bad_tag = vec![
0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x34, 0x00, 0x03, 0xFF, 0x00, 0x05, 0x48,
0x65, 0x6C, 0x6C, 0x6F, ];
let result = ClassFile::parse(&bad_tag);
assert!(result.is_err());
if let Err(ParseError::InvalidConstantPoolTag(tag)) = result {
assert_eq!(tag, 0xFF);
} else {
panic!("Expected InvalidConstantPoolTag error");
}
}
#[test]
fn test_class_file_incomplete_parse() {
let class_bytes = vec![
0xCA, 0xFE, 0xBA, 0xBE, 0x00, 0x00, 0x00, 0x34, 0x00,
0x10, ];
let result = ClassFile::parse(&class_bytes);
assert!(
result.is_err(),
"Should fail to parse incomplete class file"
);
}
#[test]
fn test_class_file_valid_parse() {
let class_bytes = minimal_class_file_bytes();
let result = ClassFile::parse(&class_bytes);
assert!(
result.is_ok(),
"Should parse valid minimal class file: {:?}",
result
);
let class_file = result.unwrap();
assert_eq!(class_file.magic, 0xCAFEBABE);
assert_eq!(class_file.major_version, 52);
assert_eq!(class_file.get_class_name(), Some("Hello".to_string()));
assert_eq!(class_file.get_super_class_name(), None);
assert_eq!(class_file.get_string(1), Some("Hello".to_string()));
assert!(class_file.find_method("main", "()V").is_none()); }
#[test]
fn test_class_loader_classpath_parsing() {
let cp = parse_classpath("a:b:c");
assert_eq!(cp.len(), 3);
assert_eq!(cp[0], PathBuf::from("a"));
assert_eq!(cp[1], PathBuf::from("b"));
assert_eq!(cp[2], PathBuf::from("c"));
}
#[test]
fn test_class_loader_classpath_parsing_empty() {
let cp = parse_classpath("");
assert!(cp.is_empty());
}
#[test]
fn test_class_loader_classpath_parsing_whitespace() {
let cp = parse_classpath(" a : b : c ");
assert_eq!(cp.len(), 3);
assert_eq!(cp[0], PathBuf::from("a"));
assert_eq!(cp[1], PathBuf::from("b"));
assert_eq!(cp[2], PathBuf::from("c"));
}
#[test]
fn test_error_display() {
use crate::error::{MemoryError, NativeError};
let err = JvmError::ParseError(crate::error::ParseError::InvalidMagic(0xDEADBEEF));
assert_eq!(
format!("{}", err),
"Parse error: Invalid magic number: 0xDEADBEEF (expected 0xCAFEBABE)"
);
let out_of_memory = MemoryError::OutOfMemory;
assert_eq!(format!("{}", out_of_memory), "Out of memory");
let class_file_not_found = ClassLoadingError::ClassFileNotFound("Test.class".to_string());
assert_eq!(
format!("{}", class_file_not_found),
"Class file not found: Test.class"
);
let native_method_not_found = NativeError::NativeMethodNotFound(
"java.lang.System".to_string(),
"currentTimeMillis".to_string(),
);
assert_eq!(
format!("{}", native_method_not_found),
"Native method java.lang.System.currentTimeMillis not found"
);
}
#[test]
fn test_descriptor_count_parameters() {
use crate::interpreter::descriptor;
assert_eq!(descriptor::count_parameters("()V"), 0);
assert_eq!(descriptor::count_parameters("(I)I"), 1);
assert_eq!(descriptor::count_parameters("(II)I"), 2);
assert_eq!(descriptor::count_parameters("(J)J"), 2); assert_eq!(descriptor::count_parameters("(D)D"), 2); assert_eq!(descriptor::count_parameters("([Ljava/lang/String;)V"), 1);
assert_eq!(descriptor::count_parameters("(Ljava/lang/String;)V"), 1);
}
#[test]
fn test_descriptor_parse_params() {
use crate::interpreter::descriptor;
assert!(descriptor::parse_method_params("()V").is_empty());
assert_eq!(descriptor::parse_method_params("(I)I"), ["int"]);
assert_eq!(descriptor::parse_method_params("(II)I"), ["int", "int"]);
assert_eq!(descriptor::parse_method_params("(F)F"), ["float"]);
assert_eq!(
descriptor::parse_method_params("(Ljava/lang/String;)V"),
["object"]
);
assert_eq!(
descriptor::parse_method_params("([I[[Ljava/lang/String;J)V"),
["array", "array", "long"]
);
}
#[test]
fn test_descriptor_malformed_inputs_do_not_panic() {
use crate::interpreter::descriptor;
assert_eq!(descriptor::count_parameters("I)V"), 0);
assert_eq!(descriptor::count_parameters("([Ljava/lang/String)V"), 0);
assert_eq!(
descriptor::parse_method_params("([Ljava/lang/String)V"),
Vec::<String>::new()
);
}
#[test]
fn test_heap_array_get_set() {
use crate::memory::HeapArray;
let mut heap = Heap::new();
let addr = heap.allocate_array(HeapArray::IntArray(vec![0, 0, 0]));
heap.array_set(addr, 1, Value::Int(42)).unwrap();
let val = heap.array_get(addr, 1).unwrap();
assert_eq!(val, Value::Int(42));
}
#[test]
fn test_heap_array_length() {
use crate::memory::HeapArray;
let mut heap = Heap::new();
let addr = heap.allocate_array(HeapArray::IntArray(vec![1, 2, 3, 4, 5]));
assert_eq!(heap.array_length(addr).unwrap(), 5);
}
#[test]
fn test_heap_get_field_set_field() {
let mut heap = Heap::new();
let addr = heap.allocate("Test".to_string());
heap.set_field(addr, "x".to_string(), Value::Int(100))
.unwrap();
let val = heap.get_field(addr, "x").unwrap();
assert_eq!(val, Value::Int(100));
}
#[test]
fn test_memory_static_fields() {
use crate::memory::Memory;
let mut mem = Memory::new();
mem.set_static("Test".to_string(), "field".to_string(), Value::Int(123));
let val = mem.get_static("Test", "field").unwrap();
assert_eq!(*val, Value::Int(123));
}
#[test]
fn test_interpreter_run_minimal() {
use crate::interpreter::Interpreter;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let result = interpreter.run_main("Minimal");
assert!(result.is_ok(), "run_main Minimal failed: {:?}", result);
}
#[test]
fn test_interpreter_run_test_get_static() {
use crate::interpreter::Interpreter;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let result = interpreter.run_main("TestGetStatic");
assert!(
result.is_ok(),
"run_main TestGetStatic failed: {:?}",
result
);
}
#[test]
fn test_interpreter_run_test_ldc() {
use crate::interpreter::Interpreter;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let result = interpreter.run_main("TestLdc");
assert!(result.is_ok(), "run_main TestLdc failed: {:?}", result);
}
#[test]
fn test_interpreter_memory_access() {
use crate::interpreter::Interpreter;
let interpreter = Interpreter::new();
let memory = interpreter.memory();
assert_eq!(memory.heap.object_count(), 0);
assert_eq!(memory.heap.array_count(), 0);
}
#[test]
fn test_class_loader_load_minimal() {
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut loader = ClassLoader::new(vec![examples]);
let result = loader.load_class("Minimal");
assert!(result.is_ok(), "load Minimal: {:?}", result);
assert!(loader.is_class_loaded("Minimal"));
let class = loader.get_class("Minimal").unwrap();
assert_eq!(class.get_class_name(), Some("Minimal".to_string()));
}
#[test]
fn test_annotations_on_minimal_class() {
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut loader = ClassLoader::new(vec![examples]);
if loader.load_class("Minimal").is_err() {
return;
}
let class = match loader.get_class("Minimal") {
Some(c) => c,
None => return,
};
let annotations = class.get_class_annotations();
assert!(annotations.is_empty() || !annotations.is_empty());
}
#[test]
fn test_aop_create_proxy() {
use crate::aop::create_proxy;
let _proxy = create_proxy("java/lang/Object".to_string(), 1, None);
}
#[test]
fn test_interpreter_stack_ops() {
use crate::interpreter::Interpreter;
use crate::memory::{StackFrame, Value};
use crate::class_file::ClassFile;
let mut interpreter = Interpreter::new();
let class = ClassFile::parse(&minimal_class_file_bytes()).unwrap();
let code = vec![];
let mut frame = StackFrame::new(10, 10, "test".to_string());
frame.push(Value::Int(1)).unwrap();
frame.push(Value::Int(2)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x58).unwrap();
assert!(frame.stack.is_empty());
frame.push(Value::Long(123)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x58).unwrap();
assert!(frame.stack.is_empty());
frame.push(Value::Int(1)).unwrap();
frame.push(Value::Int(2)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x5c).unwrap();
assert_eq!(frame.stack.len(), 4);
assert_eq!(frame.pop().unwrap(), Value::Int(2));
assert_eq!(frame.pop().unwrap(), Value::Int(1));
assert_eq!(frame.pop().unwrap(), Value::Int(2));
assert_eq!(frame.pop().unwrap(), Value::Int(1));
frame.push(Value::Long(123)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x5c).unwrap();
assert_eq!(frame.stack.len(), 2);
assert_eq!(frame.pop().unwrap(), Value::Long(123));
assert_eq!(frame.pop().unwrap(), Value::Long(123));
frame.push(Value::Int(3)).unwrap();
frame.push(Value::Int(2)).unwrap();
frame.push(Value::Int(1)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x5d).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(1));
assert_eq!(frame.pop().unwrap(), Value::Int(2));
assert_eq!(frame.pop().unwrap(), Value::Int(3));
assert_eq!(frame.pop().unwrap(), Value::Int(1));
assert_eq!(frame.pop().unwrap(), Value::Int(2));
assert!(frame.stack.is_empty());
}
#[test]
fn test_interpreter_arithmetic_ops() {
use crate::interpreter::Interpreter;
use crate::memory::{StackFrame, Value};
use crate::class_file::ClassFile;
let mut interpreter = Interpreter::new();
let class = ClassFile::parse(&minimal_class_file_bytes()).unwrap();
let code = vec![];
let mut frame = StackFrame::new(10, 10, "test".to_string());
frame.push(Value::Int(2)).unwrap(); frame.push(Value::Int(1)).unwrap(); interpreter.dispatch_instruction(&class, &code, &mut frame, 0x78).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(4));
frame.push(Value::Int(0b1100)).unwrap();
frame.push(Value::Int(0b1010)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x7e).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(0b1000));
frame.push(Value::Long(2)).unwrap(); frame.push(Value::Int(1)).unwrap(); interpreter.dispatch_instruction(&class, &code, &mut frame, 0x79).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Long(4));
}
#[test]
fn test_interpreter_conversions() {
use crate::interpreter::Interpreter;
use crate::memory::{StackFrame, Value};
use crate::class_file::ClassFile;
let mut interpreter = Interpreter::new();
let class = ClassFile::parse(&minimal_class_file_bytes()).unwrap();
let code = vec![];
let mut frame = StackFrame::new(10, 10, "test".to_string());
frame.push(Value::Int(123)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x85).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Long(123));
frame.push(Value::Int(100)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x86).unwrap();
let val = frame.pop().unwrap();
match val {
Value::Float(f) => assert_eq!(f, 100.0),
_ => panic!("Expected float"),
}
}
#[test]
fn test_interpreter_arith_cmp_ops() {
use crate::interpreter::Interpreter;
use crate::memory::{StackFrame, Value};
use crate::class_file::ClassFile;
let mut interpreter = Interpreter::new();
let class = ClassFile::parse(&minimal_class_file_bytes()).unwrap();
let code = vec![];
let mut frame = StackFrame::new(10, 10, "test".to_string());
frame.push(Value::Long(100)).unwrap();
frame.push(Value::Long(200)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x61).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Long(300));
frame.push(Value::Float(1.5)).unwrap();
frame.push(Value::Float(2.5)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x62).unwrap();
match frame.pop().unwrap() {
Value::Float(f) => assert_eq!(f, 4.0),
_ => panic!("Expected float"),
}
frame.push(Value::Double(1.5)).unwrap();
frame.push(Value::Double(2.5)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x63).unwrap();
match frame.pop().unwrap() {
Value::Double(d) => assert_eq!(d, 4.0),
_ => panic!("Expected double"),
}
frame.push(Value::Long(10)).unwrap();
frame.push(Value::Long(20)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x94).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(-1));
frame.push(Value::Long(20)).unwrap();
frame.push(Value::Long(10)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x94).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(1));
frame.push(Value::Long(10)).unwrap();
frame.push(Value::Long(10)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x94).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(0));
frame.push(Value::Float(1.0)).unwrap();
frame.push(Value::Float(f32::NAN)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x95).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(-1));
frame.push(Value::Float(1.0)).unwrap();
frame.push(Value::Float(f32::NAN)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x96).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(1));
frame.push(Value::Double(1.0)).unwrap();
frame.push(Value::Double(2.0)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x97).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(-1)); }
#[test]
fn test_interpreter_array_ops() {
use crate::interpreter::Interpreter;
use crate::memory::{StackFrame, Value, HeapArray};
use crate::class_file::ClassFile;
let mut interpreter = Interpreter::new();
let class = ClassFile::parse(&minimal_class_file_bytes()).unwrap();
let code = vec![];
let mut frame = StackFrame::new(10, 10, "test".to_string());
let addr = interpreter.memory.heap.allocate_array(HeapArray::ByteArray(vec![0xFF]));
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x33).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(-1));
let addr = interpreter.memory.heap.allocate_array(HeapArray::CharArray(vec![0xFFFF]));
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x34).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(65535));
let addr = interpreter.memory.heap.allocate_array(HeapArray::ShortArray(vec![-1]));
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x35).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Int(-1));
let addr = interpreter.memory.heap.allocate_array(HeapArray::LongArray(vec![0; 1]));
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
frame.push(Value::Long(1234567890123)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x50).unwrap();
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x2f).unwrap();
assert_eq!(frame.pop().unwrap(), Value::Long(1234567890123));
let addr = interpreter.memory.heap.allocate_array(HeapArray::FloatArray(vec![0.0; 1]));
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
frame.push(Value::Float(3.14)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x51).unwrap();
frame.push(Value::ArrayRef(addr)).unwrap();
frame.push(Value::Int(0)).unwrap();
interpreter.dispatch_instruction(&class, &code, &mut frame, 0x30).unwrap();
match frame.pop().unwrap() {
Value::Float(f) => assert!((f - 3.14).abs() < 1e-6),
_ => panic!("Expected float"),
}
}
#[test]
fn test_serialize_deserialize_value() {
use crate::serialization::{deserialize_value, serialize_value};
let v = Value::Int(42);
let bytes = serialize_value(&v).unwrap();
let restored = deserialize_value(&bytes).unwrap();
assert_eq!(v, restored);
let v2 = Value::Reference(100);
let bytes2 = serialize_value(&v2).unwrap();
let restored2 = deserialize_value(&bytes2).unwrap();
assert_eq!(v2, restored2);
}
#[test]
fn test_serialize_deserialize_object() {
use crate::memory::HeapObject;
use crate::serialization::{deserialize_object, serialize_object};
use std::collections::HashMap;
let mut fields = HashMap::new();
fields.insert("x".to_string(), Value::Int(10));
fields.insert("y".to_string(), Value::Int(20));
let obj = HeapObject {
fields,
class_name: "TestClass".to_string(),
marked: false,
string_data: None,
monitor: None,
};
let bytes = serialize_object(&obj).unwrap();
let restored = deserialize_object(&bytes, "TestClass").unwrap();
assert_eq!(obj.class_name, restored.class_name);
assert_eq!(obj.fields.get("x"), restored.fields.get("x"));
assert_eq!(obj.fields.get("y"), restored.fields.get("y"));
}
#[test]
fn test_serialize_deserialize_object_with_string() {
use crate::memory::HeapObject;
use crate::serialization::{deserialize_object, serialize_object};
use std::collections::HashMap;
let obj = HeapObject {
fields: HashMap::new(),
class_name: "java/lang/String".to_string(),
marked: false,
string_data: Some("hello".to_string()),
monitor: None,
};
let bytes = serialize_object(&obj).unwrap();
let restored = deserialize_object(&bytes, "java/lang/String").unwrap();
assert_eq!(obj.class_name, restored.class_name);
assert_eq!(restored.string_data, Some("hello".to_string()));
}
#[test]
fn test_serialize_all_value_types() {
use crate::serialization::{deserialize_value, serialize_value};
let cases = [
Value::Null,
Value::Int(-1),
Value::Long(12345678901234),
Value::Float(3.14),
Value::Double(2.718),
Value::Reference(999),
Value::ArrayRef(100),
];
for v in cases {
let bytes = serialize_value(&v).unwrap();
let restored = deserialize_value(&bytes).unwrap();
assert_eq!(v, restored, "Failed for {:?}", v);
}
}
#[test]
fn test_is_serializable_class() {
use crate::class_file::ClassFile;
use crate::serialization::is_serializable_class;
let class = ClassFile::parse(&minimal_class_file_bytes()).unwrap();
assert!(!is_serializable_class(&class));
}
#[test]
fn test_interpreter_new_instance() {
use crate::interpreter::Interpreter;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let obj = interpreter.new_instance("Minimal", &[]).unwrap();
let addr = obj.as_reference().unwrap();
assert!(addr > 0);
}
#[test]
fn test_interpreter_get_object_class() {
use crate::interpreter::Interpreter;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let obj = interpreter.new_instance("Minimal", &[]).unwrap();
let class_name = interpreter.get_object_class(&obj).unwrap();
assert_eq!(class_name, "Minimal");
}
#[test]
fn test_interpreter_get_set_field_value() {
use crate::interpreter::Interpreter;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let obj = interpreter.new_instance("Minimal", &[]).unwrap();
interpreter.set_field_value(&obj, "x", Value::Int(42)).ok();
let val = interpreter.get_field_value(&obj, "x");
if val.is_ok() {
assert_eq!(val.unwrap(), Value::Int(42));
}
}
#[test]
fn test_interpreter_memory_mut() {
use crate::interpreter::Interpreter;
use crate::memory::HeapArray;
let mut interpreter = Interpreter::new();
let mem = interpreter.memory_mut();
let addr = mem.heap.allocate_array(HeapArray::IntArray(vec![1, 2, 3]));
assert_eq!(mem.heap.array_length(addr).unwrap(), 3);
}
#[test]
fn test_reflection_api_delegates_to_interpreter() {
use crate::interpreter::Interpreter;
use crate::reflection::ReflectionApi;
use std::path::PathBuf;
let examples = PathBuf::from("examples");
if !examples.exists() {
return;
}
let mut interpreter = Interpreter::with_classpath(vec![examples]);
interpreter.set_jit_enabled(false);
let api = ReflectionApi::new();
let obj = api.new_instance(&mut interpreter, "Minimal", &[]).unwrap();
let class_name = api.get_object_class(&interpreter, &obj).unwrap();
assert_eq!(class_name, "Minimal");
}
#[test]
fn test_interpreter_reflection_errors() {
use crate::interpreter::Interpreter;
use crate::memory::Value;
let interpreter = Interpreter::new();
let err = interpreter.get_field_value(&Value::Int(1), "x");
assert!(err.is_err());
let err2 = interpreter.get_object_class(&Value::Int(1));
assert!(err2.is_err());
}
}