From ee7c0cb713891ae480407f56823289f3fe3b9807 Mon Sep 17 00:00:00 2001 From: HampusM Date: Mon, 17 Mar 2025 22:08:45 +0100 Subject: fix(ecs): correct oversights made in component storage rewrite --- ecs/tests/query.rs | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 ecs/tests/query.rs (limited to 'ecs/tests') diff --git a/ecs/tests/query.rs b/ecs/tests/query.rs new file mode 100644 index 0000000..010ffc9 --- /dev/null +++ b/ecs/tests/query.rs @@ -0,0 +1,244 @@ +use ecs::component::{Component, RefSequence as ComponentRefSequence}; +use ecs::uid::Uid; +use ecs::{Component, World}; +use parking_lot::{Mutex, Once}; + +pub static SETUP: Once = Once::new(); + +pub static TEST_LOCK: Mutex<()> = Mutex::new(()); + +#[derive(Component)] +struct A; + +#[derive(Component)] +struct B; + +#[derive(Component)] +struct C; + +#[derive(Component)] +struct D; + +#[derive(Component)] +struct E; + +#[derive(Component)] +struct F; + +#[derive(Component)] +struct G; + +fn setup() +{ + SETUP.call_once(|| { + assert_eq!(A::id().id(), 1); + assert_eq!(B::id().id(), 2); + assert_eq!(C::id().id(), 3); + assert_eq!(D::id().id(), 4); + assert_eq!(E::id().id(), 5); + assert_eq!(F::id().id(), 6); + assert_eq!(G::id().id(), 7); + }); +} + +fn assert_query_finds_ents(world: &World, mut expected_ent_ids: Vec) +where + Comps: ComponentRefSequence, +{ + assert!( + world + .query::() + .iter_with_euids() + .all(|(ent_id, _)| { + let Some(index) = expected_ent_ids + .iter() + .position(|expected_id| *expected_id == ent_id) + else { + return false; + }; + + expected_ent_ids.remove(index); + + true + }), + "Unexpected entity was found. Expected entities left: {expected_ent_ids:?}" + ); + + assert_eq!( + expected_ent_ids.len(), + 0, + concat!( + "Not all entities expected to be found was found. ", + "Expected entities left: {:?}" + ), + expected_ent_ids + ); +} + +#[test] +fn query_archetype_exists_with_edges_to_next_archetypes() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, C)); + let ent_2_id = world.create_entity((A, B, C, D, E)); + let ent_3_id = world.create_entity((A, B, C, E)); + let ent_4_id = world.create_entity((A, B, C, G, F)); + + assert_query_finds_ents::<(&A, &B, &C)>( + &world, + vec![ent_1_id, ent_2_id, ent_3_id, ent_4_id], + ); +} + +#[test] +fn query_archetype_exists_with_2_comps_diff_to_next_archetype() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, C, D, F)); + + let ent_2_id = world.create_entity((A, B, F)); + + assert_query_finds_ents::<(&A, &B, &F)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_exists_with_2_comps_diff_to_next_archetype_rev() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, F)); + + let ent_2_id = world.create_entity((A, B, C, D, F)); + + assert_query_finds_ents::<(&A, &B, &F)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_exists_with_3_comps_diff_to_next_archetype() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, C, D, E, F)); + + let ent_2_id = world.create_entity((A, B, F)); + + assert_query_finds_ents::<(&A, &B, &F)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_exists_with_3_comps_diff_to_next_archetype_rev() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, F)); + + let ent_2_id = world.create_entity((A, B, C, D, E, F)); + + assert_query_finds_ents::<(&A, &B, &F)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_exists_with_4_comps_diff_to_next_archetype() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, C, D, E, F, G)); + + let ent_2_id = world.create_entity((A, B, G)); + + assert_query_finds_ents::<(&A, &B, &G)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_exists_with_4_comps_diff_to_next_archetype_rev() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, G)); + + let ent_2_id = world.create_entity((A, B, C, D, E, F, G)); + + assert_query_finds_ents::<(&A, &B, &G)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_exists_with_4_comps_diff_to_next_archetype_and_opt_comp() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + let ent_1_id = world.create_entity((A, B, C, D, E, F, G)); + + let ent_2_id = world.create_entity((A, B, G)); + + assert_query_finds_ents::<(&A, &Option, &G)>(&world, vec![ent_1_id, ent_2_id]); +} + +#[test] +fn query_archetype_nonexistant() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + world.create_entity((A, B, C)); + + let ent_2_id = world.create_entity((A, B, C, D, E)); + let ent_3_id = world.create_entity((A, B, C, E)); + + world.create_entity((A, B, C, G, F)); + + assert_query_finds_ents::<(&A, &E)>(&world, vec![ent_2_id, ent_3_id]); +} + +#[test] +fn query_archetype_nonexistant_and_opt_comp() +{ + setup(); + + let _test_lock = TEST_LOCK.lock(); + + let mut world = World::new(); + + world.create_entity((A, B, C)); + let ent_2_id = world.create_entity((A, B, C, D, E)); + let ent_3_id = world.create_entity((A, B, C, E)); + world.create_entity((A, B, C, G, F)); + + assert_query_finds_ents::<(&A, &E, &Option)>(&world, vec![ent_2_id, ent_3_id]); +} -- cgit v1.2.3-18-g5258