Files
endorphin-aster-vm/crates/aster-core/tests/runtime.rs
T
codex-bot 9648b9e8dd
Verify databases and deploy Aster VM / verify-and-deploy (push) Waiting to run
Initialize Aster VM and deploy PostgreSQL host on ces-control
2026-10-17 23:42:39 +08:00

121 lines
4.0 KiB
Rust

use aster_core::{Value, Vm, VmError};
#[test]
fn bootstrap_is_unique_and_root_has_no_parent() {
let mut vm = Vm::new().unwrap();
let root = vm.root_class();
assert_eq!(vm.bootstrap(), root);
assert_eq!(vm.bootstrap(), root);
assert_eq!(vm.object_count(), 1);
assert_eq!(vm.class(root).unwrap().name(), "Object");
assert_eq!(vm.class(root).unwrap().parent(), None);
}
#[test]
fn factories_preserve_class_links_and_distinct_identity() {
let mut vm = Vm::new().unwrap();
let root = vm.root_class();
let class = vm.create_class("Point", root).unwrap();
let child = vm.create_class("ColoredPoint", class).unwrap();
let first = vm.create_instance(class).unwrap();
let second = vm.create_instance(class).unwrap();
let plain = vm.create_instance(root).unwrap();
assert_ne!(first, second);
assert_eq!(vm.class(child).unwrap().parent(), Some(class));
assert_eq!(vm.instance(first).unwrap().class(), class);
assert_eq!(vm.instance(plain).unwrap().class(), root);
vm.set_field(first, "x", Value::Integer(1)).unwrap();
vm.set_field(first, "next", Value::Object(second.into()))
.unwrap();
assert_eq!(
vm.instance(first).unwrap().field("x"),
Some(&Value::Integer(1))
);
assert_eq!(vm.instance(second).unwrap().field("x"), None);
assert_eq!(vm.as_class(class.into()).unwrap(), class);
assert_eq!(vm.as_instance(first.into()).unwrap(), first);
assert_eq!(vm.as_instance(class.into()), Err(VmError::ExpectedInstance));
assert_eq!(vm.as_class(first.into()), Err(VmError::ExpectedClass));
}
#[test]
fn foreign_handles_are_rejected_without_mutation() {
let mut vm = Vm::new().unwrap();
let mut other = Vm::new().unwrap();
let local = vm.create_instance(vm.root_class()).unwrap();
let foreign = other.create_instance(other.root_class()).unwrap();
let count = vm.object_count();
assert_eq!(
vm.create_class("Alien", other.root_class()),
Err(VmError::ForeignHandle)
);
assert_eq!(
vm.create_instance(other.root_class()),
Err(VmError::ForeignHandle)
);
assert!(matches!(
vm.object(foreign.into()),
Err(VmError::ForeignHandle)
));
assert!(matches!(vm.instance(foreign), Err(VmError::ForeignHandle)));
assert_eq!(
vm.set_field(foreign, "x", Value::Nil),
Err(VmError::ForeignHandle)
);
vm.set_field(local, "x", Value::Integer(7)).unwrap();
assert_eq!(
vm.set_field(local, "x", Value::Object(foreign.into())),
Err(VmError::ForeignHandle)
);
assert_eq!(
vm.instance(local).unwrap().field("x"),
Some(&Value::Integer(7))
);
assert_eq!(vm.object_count(), count);
}
#[test]
fn handles_outliving_a_vm_cannot_alias_a_new_vm() {
let old = {
let vm = Vm::new().unwrap();
vm.root_class()
};
let vm = Vm::new().unwrap();
assert_ne!(old, vm.root_class());
assert!(matches!(vm.class(old), Err(VmError::ForeignHandle)));
}
#[test]
fn invalid_names_do_not_allocate_and_names_are_not_a_namespace() {
let mut vm = Vm::new().unwrap();
assert_eq!(
vm.create_class(" ", vm.root_class()),
Err(VmError::EmptyClassName)
);
assert_eq!(
vm.create_class("Object", vm.root_class()),
Err(VmError::ReservedClassName)
);
assert_eq!(vm.object_count(), 1);
let a = vm.create_class("Label", vm.root_class()).unwrap();
let b = vm.create_class("Label", vm.root_class()).unwrap();
assert_ne!(a, b);
}
#[test]
fn handles_remain_valid_when_the_arena_grows() {
let mut vm = Vm::new().unwrap();
let root = vm.root_class();
let first = vm.create_instance(root).unwrap();
vm.set_field(first, "stable", Value::Bool(true)).unwrap();
for _ in 0..4096 {
vm.create_instance(root).unwrap();
}
assert_eq!(vm.instance(first).unwrap().class(), root);
assert_eq!(
vm.instance(first).unwrap().field("stable"),
Some(&Value::Bool(true))
);
assert_eq!(vm.class(root).unwrap().name(), "Object");
}