Files
endorphin-aster-vm/crates/objects/tests/store.rs
T
codex-bot f77b8370ea
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 7m34s
refactor: extract core objects into a standalone package
2026-10-19 13:33:24 +08:00

97 lines
3.3 KiB
Rust

use std::sync::Arc;
use objects::{
CodeLayout, EndorCode, EndorCodeObject, EndorFunctionObject, Instruction, ObjectStore, Opcode,
Value, VmError,
};
#[test]
fn standalone_storage_preserves_identity_validates_edges_and_collects_cycles() {
let mut store = ObjectStore::new().unwrap();
let mut other = ObjectStore::new().unwrap();
let dictionary = store.new_dict().unwrap();
let cell = store.new_cell(Some(Value::Object(dictionary))).unwrap();
let foreign = other.new_object().unwrap();
let address = store.object(dictionary).unwrap() as *const _;
let key = Value::Text("cell".into());
store
.dict_set(dictionary, key.clone(), Value::Object(cell))
.unwrap();
assert_eq!(store.object(dictionary).unwrap() as *const _, address);
assert_eq!(
store.dict_set(dictionary, key.clone(), Value::Object(foreign)),
Err(VmError::ForeignHandle)
);
assert_eq!(
store.dict_get(dictionary, &key).unwrap(),
Some(Value::Object(cell))
);
assert_eq!(store.ref_count(cell).unwrap(), 2);
store.release(dictionary).unwrap();
store.release(cell).unwrap();
assert_eq!(store.collect_cycles(), 2);
assert_eq!(store.object_count(), 0);
assert!(matches!(store.object(cell), Err(VmError::InvalidHandle)));
other.release(foreign).unwrap();
}
#[test]
fn standalone_function_factories_validate_and_own_shared_executable_data() {
let mut store = ObjectStore::new().unwrap();
let constant = store.new_string("kept by code").unwrap();
let globals = store.new_dict().unwrap();
let code = EndorCode::from_instructions(
&[
Instruction::new(Opcode::LoadConst, 0),
Instruction::simple(Opcode::ReturnValue),
],
vec![Value::Object(constant)],
CodeLayout::default(),
)
.unwrap();
let code = store.new_code(code).unwrap();
let before = store.object_count();
assert_eq!(
store.new_function("bad", code, globals, vec![Value::Nil], vec![]),
Err(VmError::InvalidArgument(
"function defaults or closure do not match code"
))
);
assert_eq!(store.object_count(), before);
assert_eq!(store.ref_count(code).unwrap(), 1);
let first = store
.new_function("first", code, globals, vec![], vec![])
.unwrap();
let second = store
.new_function("second", code, globals, vec![], vec![])
.unwrap();
let first_code = store
.payload::<EndorFunctionObject>(first, "function")
.unwrap()
.code();
let second_code = store
.payload::<EndorFunctionObject>(second, "function")
.unwrap()
.code();
let first_executable = store
.payload::<EndorCodeObject>(first_code, "code")
.unwrap()
.shared_code();
let second_executable = store
.payload::<EndorCodeObject>(second_code, "code")
.unwrap()
.shared_code();
assert!(Arc::ptr_eq(&first_executable, &second_executable));
drop(first_executable);
drop(second_executable);
store.release(constant).unwrap();
store.release(code).unwrap();
store.release(globals).unwrap();
assert_eq!(store.str(constant).unwrap(), "kept by code");
store.release(first).unwrap();
assert_eq!(store.ref_count(code).unwrap(), 1);
store.release(second).unwrap();
assert_eq!(store.object_count(), 0);
}