use cougr_core::{
query::SimpleQueryCache,
runtime::{ComponentEvent, ObservedWorld},
CommandQueue, ComponentStorage, GameApp, Plugin, SimpleWorld,
};
use soroban_sdk::{symbol_short, Bytes, Env};
#[test]
fn test_query_empty_world() {
let env = Env::default();
let world = SimpleWorld::new(&env);
let entities = world.get_entities_with_component(&symbol_short!("pos"), &env);
assert_eq!(entities.len(), 0);
let table_entities = world.get_table_entities_with_component(&symbol_short!("pos"), &env);
assert_eq!(table_entities.len(), 0);
let all_entities = world.get_all_entities_with_component(&symbol_short!("pos"), &env);
assert_eq!(all_entities.len(), 0);
}
#[test]
fn test_despawn_nonexistent_entity() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
world.despawn_entity(999);
assert_eq!(world.version(), 1); }
#[test]
fn test_get_component_nonexistent_entity() {
let env = Env::default();
let world = SimpleWorld::new(&env);
let result = world.get_component(999, &symbol_short!("pos"));
assert!(result.is_none());
}
#[test]
fn test_has_component_nonexistent_entity() {
let env = Env::default();
let world = SimpleWorld::new(&env);
assert!(!world.has_component(999, &symbol_short!("pos")));
}
#[test]
fn test_remove_component_nonexistent_entity() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let removed = world.remove_component(999, &symbol_short!("pos"));
assert!(!removed);
}
#[test]
fn test_remove_component_that_doesnt_exist() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
let removed = world.remove_component(e, &symbol_short!("pos"));
assert!(!removed);
}
#[test]
fn test_add_same_component_twice_replaces() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
let data1 = Bytes::from_array(&env, &[1]);
let data2 = Bytes::from_array(&env, &[2]);
world.add_component(e, symbol_short!("pos"), data1);
world.add_component(e, symbol_short!("pos"), data2.clone());
let retrieved = world.get_component(e, &symbol_short!("pos")).unwrap();
assert_eq!(retrieved, data2);
let entities = world.get_entities_with_component(&symbol_short!("pos"), &env);
assert_eq!(entities.len(), 1);
}
#[test]
fn test_despawn_entity_with_no_components() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
world.despawn_entity(e);
assert_eq!(world.version(), 1);
}
#[test]
fn test_empty_bytes_component_data() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
let empty = Bytes::new(&env);
world.add_component(e, symbol_short!("empty"), empty.clone());
assert!(world.has_component(e, &symbol_short!("empty")));
let retrieved = world.get_component(e, &symbol_short!("empty")).unwrap();
assert_eq!(retrieved.len(), 0);
assert_eq!(retrieved, empty);
}
#[test]
fn test_large_bytes_component_data() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
let large: [u8; 4096] = [0xFF; 4096];
let data = Bytes::from_slice(&env, &large);
world.add_component(e, symbol_short!("big"), data.clone());
let retrieved = world.get_component(e, &symbol_short!("big")).unwrap();
assert_eq!(retrieved.len(), 4096);
}
#[test]
fn test_double_plugin_registration() {
struct MyPlugin;
impl Plugin for MyPlugin {
fn name(&self) -> &'static str {
"my_plugin"
}
fn build(&self, app: &mut GameApp) {
app.add_system("sys", |_world: &mut SimpleWorld, _env: &Env| {});
}
}
let env = Env::default();
let mut app = GameApp::new(&env);
app.add_plugin(MyPlugin);
app.add_plugin(MyPlugin);
assert_eq!(app.plugin_count(), 1);
assert_eq!(app.system_count(), 1); }
#[test]
fn test_plugin_app_run_with_no_systems() {
let env = Env::default();
let mut app = GameApp::new(&env);
app.run(&env).unwrap();
assert_eq!(app.system_count(), 0);
}
#[test]
fn test_plugin_app_run_with_no_entities() {
let env = Env::default();
let mut app = GameApp::new(&env);
app.add_system("noop", |_world: &mut SimpleWorld, _env: &Env| {});
app.run(&env).unwrap();
}
#[test]
fn test_observer_for_unregistered_component() {
let env = Env::default();
let world = SimpleWorld::new(&env);
let mut observed = ObservedWorld::new(world);
observed.observers_mut().on_add(
symbol_short!("vel"),
|_event: &ComponentEvent, _world: &SimpleWorld, _env: &Env| {},
);
let e = observed.spawn_entity();
observed.add_component(e, symbol_short!("pos"), Bytes::from_array(&env, &[1]), &env);
assert!(observed.has_component(e, &symbol_short!("pos")));
}
#[test]
fn test_remove_nonexistent_component_observed() {
let env = Env::default();
let world = SimpleWorld::new(&env);
let mut observed = ObservedWorld::new(world);
let e = observed.spawn_entity();
let removed = observed.remove_component(e, &symbol_short!("pos"), &env);
assert!(!removed);
}
#[test]
fn test_empty_command_queue_apply() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let queue = CommandQueue::new();
assert!(queue.is_empty());
let spawned = queue.apply(&mut world);
assert!(spawned.is_empty());
}
#[test]
fn test_despawn_via_queue_then_add_component() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
world.add_component(e, symbol_short!("pos"), Bytes::from_array(&env, &[1]));
let mut queue = CommandQueue::new();
queue.despawn(e);
queue.add_component(e, symbol_short!("new"), Bytes::from_array(&env, &[2]));
queue.apply(&mut world);
assert!(!world.has_component(e, &symbol_short!("pos")));
assert!(world.has_component(e, &symbol_short!("new")));
}
#[test]
fn test_query_cache_manual_invalidation() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let mut cache = SimpleQueryCache::new(symbol_short!("pos"), &env);
let e = world.spawn_entity();
world.add_component(e, symbol_short!("pos"), Bytes::from_array(&env, &[1]));
let results = cache.execute(&world, &env);
assert_eq!(results.len(), 1);
assert!(cache.is_valid(world.version()));
cache.invalidate();
assert!(!cache.is_valid(world.version()));
let results = cache.execute(&world, &env);
assert_eq!(results.len(), 1);
}
#[test]
fn test_query_cache_for_nonexistent_component() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let mut cache = SimpleQueryCache::new(symbol_short!("xyz"), &env);
let e = world.spawn_entity();
world.add_component(e, symbol_short!("pos"), Bytes::from_array(&env, &[1]));
let results = cache.execute(&world, &env);
assert_eq!(results.len(), 0);
}
#[test]
fn test_sparse_to_table_component_switch() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let e = world.spawn_entity();
world.add_component_with_storage(
e,
symbol_short!("comp"),
Bytes::from_array(&env, &[1]),
ComponentStorage::Sparse,
);
assert_eq!(world.table_component_count(&symbol_short!("comp")), 0);
assert_eq!(world.component_count(&symbol_short!("comp")), 1);
world.add_component_with_storage(
e,
symbol_short!("comp"),
Bytes::from_array(&env, &[2]),
ComponentStorage::Table,
);
assert_eq!(world.table_component_count(&symbol_short!("comp")), 1);
assert_eq!(world.component_count(&symbol_short!("comp")), 1);
assert!(world.has_component(e, &symbol_short!("comp")));
let val = world.get_component(e, &symbol_short!("comp")).unwrap();
assert_eq!(val.get(0).unwrap(), 2);
}
#[test]
fn test_multiple_spawns_produce_sequential_ids() {
let env = Env::default();
let mut world = SimpleWorld::new(&env);
let ids: alloc::vec::Vec<u32> = (0..20).map(|_| world.spawn_entity()).collect();
for (i, entity_id) in ids.iter().enumerate().take(20) {
assert_eq!(*entity_id, (i as u32) + 1);
}
assert_eq!(world.next_entity_id(), 21);
}
extern crate alloc;