use std::sync::Arc;
use crate::{
emulation::{HeapRef, ManagedHeap},
metadata::token::Token,
};
#[derive(Debug, Clone)]
pub struct FakeObjects {
assembly: Option<HeapRef>,
app_domain: Option<HeapRef>,
}
impl Default for FakeObjects {
fn default() -> Self {
Self::new()
}
}
impl FakeObjects {
#[must_use]
pub const fn new() -> Self {
Self {
assembly: None,
app_domain: None,
}
}
#[must_use]
pub fn initialize(heap: &ManagedHeap) -> Self {
let assembly = heap.alloc_object(Token::new(0x0100_0010)).ok();
let app_domain = heap.alloc_object(Token::new(0x0100_0011)).ok();
Self {
assembly,
app_domain,
}
}
#[must_use]
pub fn assembly(&self) -> Option<HeapRef> {
self.assembly
}
#[must_use]
pub fn app_domain(&self) -> Option<HeapRef> {
self.app_domain
}
}
#[derive(Clone, Debug)]
pub struct SharedFakeObjects {
inner: Arc<FakeObjects>,
}
impl SharedFakeObjects {
#[must_use]
pub fn new(heap: &ManagedHeap) -> Self {
Self {
inner: Arc::new(FakeObjects::initialize(heap)),
}
}
#[must_use]
pub fn from_fake_objects(fake_objects: FakeObjects) -> Self {
Self {
inner: Arc::new(fake_objects),
}
}
#[must_use]
pub fn get(&self) -> &FakeObjects {
&self.inner
}
#[must_use]
pub fn assembly(&self) -> Option<HeapRef> {
self.inner.assembly()
}
#[must_use]
pub fn app_domain(&self) -> Option<HeapRef> {
self.inner.app_domain()
}
}
impl Default for SharedFakeObjects {
fn default() -> Self {
Self {
inner: Arc::new(FakeObjects::new()),
}
}
}
#[cfg(test)]
mod tests {
use crate::emulation::{FakeObjects, ManagedHeap, SharedFakeObjects};
#[test]
fn test_fake_objects_new_empty() {
let fake = FakeObjects::new();
assert!(fake.assembly().is_none());
assert!(fake.app_domain().is_none());
}
#[test]
fn test_fake_objects_initialize() {
let heap = ManagedHeap::new(1024 * 1024);
let fake = FakeObjects::initialize(&heap);
assert!(fake.assembly().is_some());
assert!(fake.app_domain().is_some());
assert_ne!(fake.assembly(), fake.app_domain());
}
#[test]
fn test_shared_fake_objects() {
let heap = ManagedHeap::new(1024 * 1024);
let shared = SharedFakeObjects::new(&heap);
assert!(shared.assembly().is_some());
assert!(shared.app_domain().is_some());
let cloned = shared.clone();
assert_eq!(shared.assembly(), cloned.assembly());
assert_eq!(shared.app_domain(), cloned.app_domain());
}
#[test]
fn test_consistency_across_calls() {
let heap = ManagedHeap::new(1024 * 1024);
let fake = FakeObjects::initialize(&heap);
let asm1 = fake.assembly();
let asm2 = fake.assembly();
assert_eq!(asm1, asm2);
let domain1 = fake.app_domain();
let domain2 = fake.app_domain();
assert_eq!(domain1, domain2);
}
}