Extract bundle tests
This commit is contained in:
parent
1ed72c508b
commit
048263eeb5
@ -3,6 +3,8 @@
|
||||
//! This module contains the [`Bundle`] trait and some other helper types.
|
||||
|
||||
mod impls;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Derive the [`Bundle`] trait
|
||||
///
|
||||
@ -1925,294 +1927,3 @@ fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
archetype::ArchetypeCreated, lifecycle::HookContext, prelude::*, world::DeferredWorld,
|
||||
};
|
||||
use alloc::vec;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A;
|
||||
|
||||
#[derive(Component)]
|
||||
#[component(on_add = a_on_add, on_insert = a_on_insert, on_replace = a_on_replace, on_remove = a_on_remove)]
|
||||
struct AMacroHooks;
|
||||
|
||||
fn a_on_add(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(0);
|
||||
}
|
||||
|
||||
fn a_on_insert(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(1);
|
||||
}
|
||||
|
||||
fn a_on_replace(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(2);
|
||||
}
|
||||
|
||||
fn a_on_remove(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(3);
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct B;
|
||||
|
||||
#[derive(Component)]
|
||||
struct C;
|
||||
|
||||
#[derive(Component)]
|
||||
struct D;
|
||||
|
||||
#[derive(Component, Eq, PartialEq, Debug)]
|
||||
struct V(&'static str); // component with a value
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
struct R(usize);
|
||||
|
||||
impl R {
|
||||
#[track_caller]
|
||||
fn assert_order(&mut self, count: usize) {
|
||||
assert_eq!(count, self.0);
|
||||
self.0 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
#[bundle(ignore_from_components)]
|
||||
struct BundleNoExtract {
|
||||
b: B,
|
||||
no_from_comp: crate::spawn::SpawnRelatedBundle<ChildOf, Spawn<C>>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_spawn_bundle_without_extract() {
|
||||
let mut world = World::new();
|
||||
let id = world
|
||||
.spawn(BundleNoExtract {
|
||||
b: B,
|
||||
no_from_comp: Children::spawn(Spawn(C)),
|
||||
})
|
||||
.id();
|
||||
|
||||
assert!(world.entity(id).get::<Children>().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_spawn_despawn() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
|
||||
.on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
|
||||
.on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
|
||||
.on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
|
||||
|
||||
let entity = world.spawn(A).id();
|
||||
world.despawn(entity);
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_spawn_despawn_with_macro_hooks() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
|
||||
let entity = world.spawn(AMacroHooks).id();
|
||||
world.despawn(entity);
|
||||
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_insert_remove() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
|
||||
.on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
|
||||
.on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
|
||||
.on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
|
||||
|
||||
let mut entity = world.spawn_empty();
|
||||
entity.insert(A);
|
||||
entity.remove::<A>();
|
||||
entity.flush();
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_replace() {
|
||||
let mut world = World::new();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_replace(|mut world, _| world.resource_mut::<R>().assert_order(0))
|
||||
.on_insert(|mut world, _| {
|
||||
if let Some(mut r) = world.get_resource_mut::<R>() {
|
||||
r.assert_order(1);
|
||||
}
|
||||
});
|
||||
|
||||
let entity = world.spawn(A).id();
|
||||
world.init_resource::<R>();
|
||||
let mut entity = world.entity_mut(entity);
|
||||
entity.insert(A);
|
||||
entity.insert_if_new(A); // this will not trigger on_replace or on_insert
|
||||
entity.flush();
|
||||
assert_eq!(2, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_recursive() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(0);
|
||||
world.commands().entity(context.entity).insert(B);
|
||||
})
|
||||
.on_remove(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(2);
|
||||
world.commands().entity(context.entity).remove::<B>();
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<B>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(1);
|
||||
world.commands().entity(context.entity).remove::<A>();
|
||||
})
|
||||
.on_remove(|mut world, _| {
|
||||
world.resource_mut::<R>().assert_order(3);
|
||||
});
|
||||
|
||||
let entity = world.spawn(A).flush();
|
||||
let entity = world.get_entity(entity).unwrap();
|
||||
assert!(!entity.contains::<A>());
|
||||
assert!(!entity.contains::<B>());
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_recursive_multiple() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(0);
|
||||
world.commands().entity(context.entity).insert(B).insert(C);
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<B>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(1);
|
||||
world.commands().entity(context.entity).insert(D);
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<C>()
|
||||
.on_add(|mut world, _| {
|
||||
world.resource_mut::<R>().assert_order(3);
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<D>()
|
||||
.on_add(|mut world, _| {
|
||||
world.resource_mut::<R>().assert_order(2);
|
||||
});
|
||||
|
||||
world.spawn(A).flush();
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_if_new() {
|
||||
let mut world = World::new();
|
||||
let id = world.spawn(V("one")).id();
|
||||
let mut entity = world.entity_mut(id);
|
||||
entity.insert_if_new(V("two"));
|
||||
entity.insert_if_new((A, V("three")));
|
||||
entity.flush();
|
||||
// should still contain "one"
|
||||
let entity = world.entity(id);
|
||||
assert!(entity.contains::<A>());
|
||||
assert_eq!(entity.get(), Some(&V("one")));
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Eq, PartialEq)]
|
||||
#[component(storage = "SparseSet")]
|
||||
pub struct SparseV(&'static str);
|
||||
|
||||
#[derive(Component, Debug, Eq, PartialEq)]
|
||||
#[component(storage = "SparseSet")]
|
||||
pub struct SparseA;
|
||||
|
||||
#[test]
|
||||
fn sparse_set_insert_if_new() {
|
||||
let mut world = World::new();
|
||||
let id = world.spawn(SparseV("one")).id();
|
||||
let mut entity = world.entity_mut(id);
|
||||
entity.insert_if_new(SparseV("two"));
|
||||
entity.insert_if_new((SparseA, SparseV("three")));
|
||||
entity.flush();
|
||||
// should still contain "one"
|
||||
let entity = world.entity(id);
|
||||
assert!(entity.contains::<SparseA>());
|
||||
assert_eq!(entity.get(), Some(&SparseV("one")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sorted_remove() {
|
||||
let mut a = vec![1, 2, 3, 4, 5, 6, 7];
|
||||
let b = vec![1, 2, 3, 5, 7];
|
||||
super::sorted_remove(&mut a, &b);
|
||||
|
||||
assert_eq!(a, vec![4, 6]);
|
||||
|
||||
let mut a = vec![1];
|
||||
let b = vec![1];
|
||||
super::sorted_remove(&mut a, &b);
|
||||
|
||||
assert_eq!(a, vec![]);
|
||||
|
||||
let mut a = vec![1];
|
||||
let b = vec![2];
|
||||
super::sorted_remove(&mut a, &b);
|
||||
|
||||
assert_eq!(a, vec![1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_archetype_created() {
|
||||
let mut world = World::new();
|
||||
#[derive(Resource, Default)]
|
||||
struct Count(u32);
|
||||
world.init_resource::<Count>();
|
||||
world.add_observer(|_t: On<ArchetypeCreated>, mut count: ResMut<Count>| {
|
||||
count.0 += 1;
|
||||
});
|
||||
|
||||
let mut e = world.spawn((A, B));
|
||||
e.insert(C);
|
||||
e.remove::<A>();
|
||||
e.insert(A);
|
||||
e.insert(A);
|
||||
|
||||
assert_eq!(world.resource::<Count>().0, 3);
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
#[expect(unused, reason = "tests the output of the derive macro is valid")]
|
||||
struct Ignore {
|
||||
#[bundle(ignore)]
|
||||
foo: i32,
|
||||
#[bundle(ignore)]
|
||||
bar: i32,
|
||||
}
|
||||
}
|
||||
|
287
crates/bevy_ecs/src/bundle/tests.rs
Normal file
287
crates/bevy_ecs/src/bundle/tests.rs
Normal file
@ -0,0 +1,287 @@
|
||||
use crate::{
|
||||
archetype::ArchetypeCreated, lifecycle::HookContext, prelude::*, world::DeferredWorld,
|
||||
};
|
||||
use alloc::vec;
|
||||
|
||||
#[derive(Component)]
|
||||
struct A;
|
||||
|
||||
#[derive(Component)]
|
||||
#[component(on_add = a_on_add, on_insert = a_on_insert, on_replace = a_on_replace, on_remove = a_on_remove)]
|
||||
struct AMacroHooks;
|
||||
|
||||
fn a_on_add(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(0);
|
||||
}
|
||||
|
||||
fn a_on_insert(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(1);
|
||||
}
|
||||
|
||||
fn a_on_replace(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(2);
|
||||
}
|
||||
|
||||
fn a_on_remove(mut world: DeferredWorld, _: HookContext) {
|
||||
world.resource_mut::<R>().assert_order(3);
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct B;
|
||||
|
||||
#[derive(Component)]
|
||||
struct C;
|
||||
|
||||
#[derive(Component)]
|
||||
struct D;
|
||||
|
||||
#[derive(Component, Eq, PartialEq, Debug)]
|
||||
struct V(&'static str); // component with a value
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
struct R(usize);
|
||||
|
||||
impl R {
|
||||
#[track_caller]
|
||||
fn assert_order(&mut self, count: usize) {
|
||||
assert_eq!(count, self.0);
|
||||
self.0 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
#[bundle(ignore_from_components)]
|
||||
struct BundleNoExtract {
|
||||
b: B,
|
||||
no_from_comp: crate::spawn::SpawnRelatedBundle<ChildOf, Spawn<C>>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_spawn_bundle_without_extract() {
|
||||
let mut world = World::new();
|
||||
let id = world
|
||||
.spawn(BundleNoExtract {
|
||||
b: B,
|
||||
no_from_comp: Children::spawn(Spawn(C)),
|
||||
})
|
||||
.id();
|
||||
|
||||
assert!(world.entity(id).get::<Children>().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_spawn_despawn() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
|
||||
.on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
|
||||
.on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
|
||||
.on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
|
||||
|
||||
let entity = world.spawn(A).id();
|
||||
world.despawn(entity);
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_spawn_despawn_with_macro_hooks() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
|
||||
let entity = world.spawn(AMacroHooks).id();
|
||||
world.despawn(entity);
|
||||
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_insert_remove() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, _| world.resource_mut::<R>().assert_order(0))
|
||||
.on_insert(|mut world, _| world.resource_mut::<R>().assert_order(1))
|
||||
.on_replace(|mut world, _| world.resource_mut::<R>().assert_order(2))
|
||||
.on_remove(|mut world, _| world.resource_mut::<R>().assert_order(3));
|
||||
|
||||
let mut entity = world.spawn_empty();
|
||||
entity.insert(A);
|
||||
entity.remove::<A>();
|
||||
entity.flush();
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_replace() {
|
||||
let mut world = World::new();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_replace(|mut world, _| world.resource_mut::<R>().assert_order(0))
|
||||
.on_insert(|mut world, _| {
|
||||
if let Some(mut r) = world.get_resource_mut::<R>() {
|
||||
r.assert_order(1);
|
||||
}
|
||||
});
|
||||
|
||||
let entity = world.spawn(A).id();
|
||||
world.init_resource::<R>();
|
||||
let mut entity = world.entity_mut(entity);
|
||||
entity.insert(A);
|
||||
entity.insert_if_new(A); // this will not trigger on_replace or on_insert
|
||||
entity.flush();
|
||||
assert_eq!(2, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_recursive() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(0);
|
||||
world.commands().entity(context.entity).insert(B);
|
||||
})
|
||||
.on_remove(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(2);
|
||||
world.commands().entity(context.entity).remove::<B>();
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<B>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(1);
|
||||
world.commands().entity(context.entity).remove::<A>();
|
||||
})
|
||||
.on_remove(|mut world, _| {
|
||||
world.resource_mut::<R>().assert_order(3);
|
||||
});
|
||||
|
||||
let entity = world.spawn(A).flush();
|
||||
let entity = world.get_entity(entity).unwrap();
|
||||
assert!(!entity.contains::<A>());
|
||||
assert!(!entity.contains::<B>());
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn component_hook_order_recursive_multiple() {
|
||||
let mut world = World::new();
|
||||
world.init_resource::<R>();
|
||||
world
|
||||
.register_component_hooks::<A>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(0);
|
||||
world.commands().entity(context.entity).insert(B).insert(C);
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<B>()
|
||||
.on_add(|mut world, context| {
|
||||
world.resource_mut::<R>().assert_order(1);
|
||||
world.commands().entity(context.entity).insert(D);
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<C>()
|
||||
.on_add(|mut world, _| {
|
||||
world.resource_mut::<R>().assert_order(3);
|
||||
});
|
||||
|
||||
world
|
||||
.register_component_hooks::<D>()
|
||||
.on_add(|mut world, _| {
|
||||
world.resource_mut::<R>().assert_order(2);
|
||||
});
|
||||
|
||||
world.spawn(A).flush();
|
||||
assert_eq!(4, world.resource::<R>().0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_if_new() {
|
||||
let mut world = World::new();
|
||||
let id = world.spawn(V("one")).id();
|
||||
let mut entity = world.entity_mut(id);
|
||||
entity.insert_if_new(V("two"));
|
||||
entity.insert_if_new((A, V("three")));
|
||||
entity.flush();
|
||||
// should still contain "one"
|
||||
let entity = world.entity(id);
|
||||
assert!(entity.contains::<A>());
|
||||
assert_eq!(entity.get(), Some(&V("one")));
|
||||
}
|
||||
|
||||
#[derive(Component, Debug, Eq, PartialEq)]
|
||||
#[component(storage = "SparseSet")]
|
||||
pub struct SparseV(&'static str);
|
||||
|
||||
#[derive(Component, Debug, Eq, PartialEq)]
|
||||
#[component(storage = "SparseSet")]
|
||||
pub struct SparseA;
|
||||
|
||||
#[test]
|
||||
fn sparse_set_insert_if_new() {
|
||||
let mut world = World::new();
|
||||
let id = world.spawn(SparseV("one")).id();
|
||||
let mut entity = world.entity_mut(id);
|
||||
entity.insert_if_new(SparseV("two"));
|
||||
entity.insert_if_new((SparseA, SparseV("three")));
|
||||
entity.flush();
|
||||
// should still contain "one"
|
||||
let entity = world.entity(id);
|
||||
assert!(entity.contains::<SparseA>());
|
||||
assert_eq!(entity.get(), Some(&SparseV("one")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sorted_remove() {
|
||||
let mut a = vec![1, 2, 3, 4, 5, 6, 7];
|
||||
let b = vec![1, 2, 3, 5, 7];
|
||||
super::sorted_remove(&mut a, &b);
|
||||
|
||||
assert_eq!(a, vec![4, 6]);
|
||||
|
||||
let mut a = vec![1];
|
||||
let b = vec![1];
|
||||
super::sorted_remove(&mut a, &b);
|
||||
|
||||
assert_eq!(a, vec![]);
|
||||
|
||||
let mut a = vec![1];
|
||||
let b = vec![2];
|
||||
super::sorted_remove(&mut a, &b);
|
||||
|
||||
assert_eq!(a, vec![1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn new_archetype_created() {
|
||||
let mut world = World::new();
|
||||
#[derive(Resource, Default)]
|
||||
struct Count(u32);
|
||||
world.init_resource::<Count>();
|
||||
world.add_observer(|_t: On<ArchetypeCreated>, mut count: ResMut<Count>| {
|
||||
count.0 += 1;
|
||||
});
|
||||
|
||||
let mut e = world.spawn((A, B));
|
||||
e.insert(C);
|
||||
e.remove::<A>();
|
||||
e.insert(A);
|
||||
e.insert(A);
|
||||
|
||||
assert_eq!(world.resource::<Count>().0, 3);
|
||||
}
|
||||
|
||||
#[derive(Bundle)]
|
||||
#[expect(unused, reason = "tests the output of the derive macro is valid")]
|
||||
struct Ignore {
|
||||
#[bundle(ignore)]
|
||||
foo: i32,
|
||||
#[bundle(ignore)]
|
||||
bar: i32,
|
||||
}
|
Loading…
Reference in New Issue
Block a user