bevy_ecs/
lib.rs

1#![expect(
2    unsafe_op_in_unsafe_fn,
3    reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
4)]
5#![doc = include_str!("../README.md")]
6#![cfg_attr(
7    any(docsrs, docsrs_dep),
8    expect(
9        internal_features,
10        reason = "rustdoc_internals is needed for fake_variadic"
11    )
12)]
13#![cfg_attr(any(docsrs, docsrs_dep), feature(doc_cfg, rustdoc_internals))]
14#![expect(unsafe_code, reason = "Unsafe code is used to improve performance.")]
15#![doc(
16    html_logo_url = "https://bevy.org/assets/icon.png",
17    html_favicon_url = "https://bevy.org/assets/icon.png"
18)]
19#![no_std]
20
21#[cfg(feature = "std")]
22extern crate std;
23
24#[cfg(target_pointer_width = "16")]
25compile_error!("bevy_ecs cannot safely compile for a 16-bit platform.");
26
27extern crate alloc;
28
29// Required to make proc macros work in bevy itself.
30extern crate self as bevy_ecs;
31
32pub mod archetype;
33pub mod batching;
34pub mod bundle;
35pub mod change_detection;
36pub mod component;
37pub mod entity;
38pub mod entity_disabling;
39pub mod error;
40pub mod event;
41pub mod hierarchy;
42pub mod intern;
43pub mod label;
44pub mod lifecycle;
45pub mod message;
46pub mod name;
47pub mod never;
48pub mod observer;
49pub mod query;
50#[cfg(feature = "bevy_reflect")]
51pub mod reflect;
52pub mod relationship;
53pub mod resource;
54pub mod schedule;
55pub mod spawn;
56pub mod storage;
57pub mod system;
58pub mod traversal;
59pub mod world;
60
61pub use bevy_ptr as ptr;
62
63#[cfg(feature = "hotpatching")]
64use message::Message;
65
66/// The ECS prelude.
67///
68/// This includes the most common types in this crate, re-exported for your convenience.
69pub mod prelude {
70    #[doc(hidden)]
71    pub use crate::{
72        bundle::Bundle,
73        change_detection::{DetectChanges, DetectChangesMut, Mut, Ref},
74        children,
75        component::Component,
76        entity::{ContainsEntity, Entity, EntityMapper},
77        error::{BevyError, Result},
78        event::{EntityEvent, Event},
79        hierarchy::{ChildOf, ChildSpawner, ChildSpawnerCommands, Children},
80        lifecycle::{Add, Despawn, Insert, Remove, RemovedComponents, Replace},
81        message::{Message, MessageMutator, MessageReader, MessageWriter, Messages},
82        name::{Name, NameOrEntity},
83        observer::{Observer, On},
84        query::{Added, Allow, AnyOf, Changed, Has, Or, QueryBuilder, QueryState, With, Without},
85        related,
86        relationship::RelationshipTarget,
87        resource::Resource,
88        schedule::{
89            common_conditions::*, ApplyDeferred, IntoScheduleConfigs, IntoSystemSet, Schedule,
90            Schedules, SystemCondition, SystemSet,
91        },
92        spawn::{Spawn, SpawnIter, SpawnRelated, SpawnWith, WithOneRelated, WithRelated},
93        system::{
94            Command, Commands, Deferred, EntityCommand, EntityCommands, If, In, InMut, InRef,
95            IntoSystem, Local, NonSend, NonSendMut, ParamSet, Populated, Query, ReadOnlySystem,
96            Res, ResMut, Single, System, SystemIn, SystemInput, SystemParamBuilder,
97            SystemParamFunction,
98        },
99        world::{
100            EntityMut, EntityRef, EntityWorldMut, FilteredResources, FilteredResourcesMut,
101            FromWorld, World,
102        },
103    };
104
105    #[doc(hidden)]
106    #[cfg(feature = "std")]
107    pub use crate::system::ParallelCommands;
108
109    #[doc(hidden)]
110    #[cfg(feature = "bevy_reflect")]
111    pub use crate::reflect::{
112        AppTypeRegistry, ReflectComponent, ReflectEvent, ReflectFromWorld, ReflectResource,
113    };
114
115    #[doc(hidden)]
116    #[cfg(feature = "reflect_functions")]
117    pub use crate::reflect::AppFunctionRegistry;
118}
119
120/// Exports used by macros.
121///
122/// These are not meant to be used directly and are subject to breaking changes.
123#[doc(hidden)]
124pub mod __macro_exports {
125    // Cannot directly use `alloc::vec::Vec` in macros, as a crate may not have
126    // included `extern crate alloc;`. This re-export ensures we have access
127    // to `Vec` in `no_std` and `std` contexts.
128    pub use crate::query::DebugCheckedUnwrap;
129    pub use alloc::vec::Vec;
130}
131
132/// Event sent when a hotpatch happens.
133///
134/// Can be used for causing custom behavior on hot-patch.
135#[cfg(feature = "hotpatching")]
136#[derive(Message, Default)]
137pub struct HotPatched;
138
139/// Resource which "changes" when a hotpatch happens.
140///
141/// Exists solely for change-detection, which allows systems to
142/// know whether a hotpatch happened even if they only run irregularily and would
143/// miss the event.
144///
145/// Used by Executors and other places which run systems
146/// [`System::refresh_hotpatch`](crate::system::System::refresh_hotpatch) only when necessary.
147#[cfg(feature = "hotpatching")]
148#[derive(resource::Resource, Default)]
149pub struct HotPatchChanges;
150
151#[cfg(test)]
152mod tests {
153    use crate::{
154        bundle::Bundle,
155        change_detection::Ref,
156        component::Component,
157        entity::{Entity, EntityMapper, EntityNotSpawnedError},
158        entity_disabling::DefaultQueryFilters,
159        prelude::Or,
160        query::{Added, Changed, FilteredAccess, QueryFilter, With, Without},
161        resource::Resource,
162        world::{error::EntityDespawnError, EntityMut, EntityRef, Mut, World},
163    };
164    use alloc::{string::String, sync::Arc, vec, vec::Vec};
165    use bevy_platform::collections::HashSet;
166    use bevy_tasks::{ComputeTaskPool, TaskPool};
167    use core::{
168        any::TypeId,
169        marker::PhantomData,
170        sync::atomic::{AtomicUsize, Ordering},
171    };
172    use std::sync::Mutex;
173
174    #[derive(Component, Debug, PartialEq, Eq, Hash, Clone, Copy)]
175    struct A(usize);
176    #[derive(Resource, Debug, PartialEq, Eq)]
177    struct ResA(usize);
178    #[derive(Component, Debug, PartialEq, Eq, Hash, Clone, Copy)]
179    struct B(usize);
180    #[derive(Component, Debug, PartialEq, Eq, Clone, Copy)]
181    struct C;
182
183    #[derive(Default)]
184    struct NonSendA(PhantomData<*mut ()>);
185
186    #[derive(Component, Clone, Debug)]
187    struct DropCk(Arc<AtomicUsize>);
188    impl DropCk {
189        fn new_pair() -> (Self, Arc<AtomicUsize>) {
190            let atomic = Arc::new(AtomicUsize::new(0));
191            (DropCk(atomic.clone()), atomic)
192        }
193    }
194
195    impl Drop for DropCk {
196        fn drop(&mut self) {
197            self.0.as_ref().fetch_add(1, Ordering::Relaxed);
198        }
199    }
200
201    #[expect(
202        dead_code,
203        reason = "This struct is used to test how `Drop` behavior works in regards to SparseSet storage, and as such is solely a wrapper around `DropCk` to make it use the SparseSet storage. Because of this, the inner field is intentionally never read."
204    )]
205    #[derive(Component, Clone, Debug)]
206    #[component(storage = "SparseSet")]
207    struct DropCkSparse(DropCk);
208
209    #[derive(Component, Copy, Clone, PartialEq, Eq, Debug)]
210    #[component(storage = "Table")]
211    struct TableStored(&'static str);
212    #[derive(Component, Copy, Clone, PartialEq, Eq, Hash, Debug)]
213    #[component(storage = "SparseSet")]
214    struct SparseStored(u32);
215
216    #[test]
217    fn random_access() {
218        let mut world = World::new();
219
220        let e = world.spawn((TableStored("abc"), SparseStored(123))).id();
221        let f = world
222            .spawn((TableStored("def"), SparseStored(456), A(1)))
223            .id();
224        assert_eq!(world.get::<TableStored>(e).unwrap().0, "abc");
225        assert_eq!(world.get::<SparseStored>(e).unwrap().0, 123);
226        assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
227        assert_eq!(world.get::<SparseStored>(f).unwrap().0, 456);
228
229        // test archetype get_mut()
230        world.get_mut::<TableStored>(e).unwrap().0 = "xyz";
231        assert_eq!(world.get::<TableStored>(e).unwrap().0, "xyz");
232
233        // test sparse set get_mut()
234        world.get_mut::<SparseStored>(f).unwrap().0 = 42;
235        assert_eq!(world.get::<SparseStored>(f).unwrap().0, 42);
236    }
237
238    #[test]
239    fn bundle_derive() {
240        let mut world = World::new();
241
242        #[derive(Bundle, PartialEq, Debug)]
243        struct FooBundle {
244            x: TableStored,
245            y: SparseStored,
246        }
247        let ids: Vec<_> =
248            <FooBundle as Bundle>::component_ids(&mut world.components_registrator()).collect();
249
250        assert_eq!(
251            ids,
252            &[
253                world.register_component::<TableStored>(),
254                world.register_component::<SparseStored>(),
255            ]
256        );
257
258        let e1 = world
259            .spawn(FooBundle {
260                x: TableStored("abc"),
261                y: SparseStored(123),
262            })
263            .id();
264        let e2 = world
265            .spawn((TableStored("def"), SparseStored(456), A(1)))
266            .id();
267        assert_eq!(world.get::<TableStored>(e1).unwrap().0, "abc");
268        assert_eq!(world.get::<SparseStored>(e1).unwrap().0, 123);
269        assert_eq!(world.get::<TableStored>(e2).unwrap().0, "def");
270        assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 456);
271
272        // test archetype get_mut()
273        world.get_mut::<TableStored>(e1).unwrap().0 = "xyz";
274        assert_eq!(world.get::<TableStored>(e1).unwrap().0, "xyz");
275
276        // test sparse set get_mut()
277        world.get_mut::<SparseStored>(e2).unwrap().0 = 42;
278        assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 42);
279
280        assert_eq!(
281            world.entity_mut(e1).take::<FooBundle>().unwrap(),
282            FooBundle {
283                x: TableStored("xyz"),
284                y: SparseStored(123),
285            }
286        );
287
288        #[derive(Bundle, PartialEq, Debug)]
289        struct NestedBundle {
290            a: A,
291            foo: FooBundle,
292            b: B,
293        }
294
295        let ids: Vec<_> =
296            <NestedBundle as Bundle>::component_ids(&mut world.components_registrator()).collect();
297
298        assert_eq!(
299            ids,
300            &[
301                world.register_component::<A>(),
302                world.register_component::<TableStored>(),
303                world.register_component::<SparseStored>(),
304                world.register_component::<B>(),
305            ]
306        );
307
308        let e3 = world
309            .spawn(NestedBundle {
310                a: A(1),
311                foo: FooBundle {
312                    x: TableStored("ghi"),
313                    y: SparseStored(789),
314                },
315                b: B(2),
316            })
317            .id();
318
319        assert_eq!(world.get::<TableStored>(e3).unwrap().0, "ghi");
320        assert_eq!(world.get::<SparseStored>(e3).unwrap().0, 789);
321        assert_eq!(world.get::<A>(e3).unwrap().0, 1);
322        assert_eq!(world.get::<B>(e3).unwrap().0, 2);
323        assert_eq!(
324            world.entity_mut(e3).take::<NestedBundle>().unwrap(),
325            NestedBundle {
326                a: A(1),
327                foo: FooBundle {
328                    x: TableStored("ghi"),
329                    y: SparseStored(789),
330                },
331                b: B(2),
332            }
333        );
334
335        #[derive(Default, Component, PartialEq, Debug)]
336        struct Ignored;
337
338        #[derive(Bundle, PartialEq, Debug)]
339        struct BundleWithIgnored {
340            c: C,
341            #[bundle(ignore)]
342            ignored: Ignored,
343        }
344
345        let ids: Vec<_> =
346            <BundleWithIgnored as Bundle>::component_ids(&mut world.components_registrator())
347                .collect();
348
349        assert_eq!(ids, &[world.register_component::<C>(),]);
350
351        let e4 = world
352            .spawn(BundleWithIgnored {
353                c: C,
354                ignored: Ignored,
355            })
356            .id();
357
358        assert_eq!(world.get::<C>(e4).unwrap(), &C);
359        assert_eq!(world.get::<Ignored>(e4), None);
360
361        assert_eq!(
362            world.entity_mut(e4).take::<BundleWithIgnored>().unwrap(),
363            BundleWithIgnored {
364                c: C,
365                ignored: Ignored,
366            }
367        );
368    }
369
370    #[test]
371    fn spawning_with_manual_entity_allocation() {
372        let mut world = World::new();
373        let e1 = world.entities_allocator_mut().alloc();
374        world.spawn_at(e1, (TableStored("abc"), A(123))).unwrap();
375
376        let e2 = world.entities_allocator_mut().alloc();
377        assert!(matches!(
378            world.try_despawn_no_free(e2),
379            Err(EntityDespawnError(
380                EntityNotSpawnedError::ValidButNotSpawned(_)
381            ))
382        ));
383        assert!(!world.despawn(e2));
384        world.entities_allocator_mut().free(e2);
385
386        let e3 = world.entities_allocator_mut().alloc();
387        let e3 = world
388            .spawn_at(e3, (TableStored("junk"), A(0)))
389            .unwrap()
390            .despawn_no_free();
391        world.spawn_at(e3, (TableStored("def"), A(456))).unwrap();
392
393        assert_eq!(world.entities.count_spawned(), 2);
394        assert!(world.despawn(e1));
395        assert_eq!(world.entities.count_spawned(), 1);
396        assert!(world.get::<TableStored>(e1).is_none());
397        assert!(world.get::<A>(e1).is_none());
398        assert_eq!(world.get::<TableStored>(e3).unwrap().0, "def");
399        assert_eq!(world.get::<A>(e3).unwrap().0, 456);
400    }
401
402    #[test]
403    fn despawn_table_storage() {
404        let mut world = World::new();
405        let e = world.spawn((TableStored("abc"), A(123))).id();
406        let f = world.spawn((TableStored("def"), A(456))).id();
407        assert_eq!(world.query::<&TableStored>().query(&world).count(), 2);
408        assert!(world.despawn(e));
409        assert_eq!(world.query::<&TableStored>().query(&world).count(), 1);
410        assert!(world.get::<TableStored>(e).is_none());
411        assert!(world.get::<A>(e).is_none());
412        assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
413        assert_eq!(world.get::<A>(f).unwrap().0, 456);
414    }
415
416    #[test]
417    fn despawn_mixed_storage() {
418        let mut world = World::new();
419
420        let e = world.spawn((TableStored("abc"), SparseStored(123))).id();
421        let f = world.spawn((TableStored("def"), SparseStored(456))).id();
422        assert_eq!(world.query::<&TableStored>().query(&world).count(), 2);
423        assert!(world.despawn(e));
424        assert_eq!(world.query::<&TableStored>().query(&world).count(), 1);
425        assert!(world.get::<TableStored>(e).is_none());
426        assert!(world.get::<SparseStored>(e).is_none());
427        assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
428        assert_eq!(world.get::<SparseStored>(f).unwrap().0, 456);
429    }
430
431    #[test]
432    fn query_all() {
433        let mut world = World::new();
434        let e = world.spawn((TableStored("abc"), A(123))).id();
435        let f = world.spawn((TableStored("def"), A(456))).id();
436
437        let ents = world
438            .query::<(Entity, &A, &TableStored)>()
439            .iter(&world)
440            .map(|(e, &i, &s)| (e, i, s))
441            .collect::<Vec<_>>();
442        assert_eq!(
443            ents,
444            &[
445                (e, A(123), TableStored("abc")),
446                (f, A(456), TableStored("def"))
447            ]
448        );
449    }
450
451    #[test]
452    fn query_all_for_each() {
453        let mut world = World::new();
454        let e = world.spawn((TableStored("abc"), A(123))).id();
455        let f = world.spawn((TableStored("def"), A(456))).id();
456
457        let mut results = Vec::new();
458        world
459            .query::<(Entity, &A, &TableStored)>()
460            .iter(&world)
461            .for_each(|(e, &i, &s)| results.push((e, i, s)));
462        assert_eq!(
463            results,
464            &[
465                (e, A(123), TableStored("abc")),
466                (f, A(456), TableStored("def"))
467            ]
468        );
469    }
470
471    #[test]
472    fn query_single_component() {
473        let mut world = World::new();
474        let e = world.spawn((TableStored("abc"), A(123))).id();
475        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
476        let ents = world
477            .query::<(Entity, &A)>()
478            .iter(&world)
479            .map(|(e, &i)| (e, i))
480            .collect::<HashSet<_>>();
481        assert!(ents.contains(&(e, A(123))));
482        assert!(ents.contains(&(f, A(456))));
483    }
484
485    #[test]
486    fn stateful_query_handles_new_archetype() {
487        let mut world = World::new();
488        let e = world.spawn((TableStored("abc"), A(123))).id();
489        let mut query = world.query::<(Entity, &A)>();
490
491        let ents = query.iter(&world).map(|(e, &i)| (e, i)).collect::<Vec<_>>();
492        assert_eq!(ents, &[(e, A(123))]);
493
494        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
495        let ents = query.iter(&world).map(|(e, &i)| (e, i)).collect::<Vec<_>>();
496        assert_eq!(ents, &[(e, A(123)), (f, A(456))]);
497    }
498
499    #[test]
500    fn query_single_component_for_each() {
501        let mut world = World::new();
502        let e = world.spawn((TableStored("abc"), A(123))).id();
503        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
504        let mut results = <HashSet<_>>::default();
505        world
506            .query::<(Entity, &A)>()
507            .iter(&world)
508            .for_each(|(e, &i)| {
509                results.insert((e, i));
510            });
511        assert!(results.contains(&(e, A(123))));
512        assert!(results.contains(&(f, A(456))));
513    }
514
515    #[test]
516    fn par_for_each_dense() {
517        ComputeTaskPool::get_or_init(TaskPool::default);
518        let mut world = World::new();
519        let e1 = world.spawn(A(1)).id();
520        let e2 = world.spawn(A(2)).id();
521        let e3 = world.spawn(A(3)).id();
522        let e4 = world.spawn((A(4), B(1))).id();
523        let e5 = world.spawn((A(5), B(1))).id();
524        let results = Arc::new(Mutex::new(Vec::new()));
525        world
526            .query::<(Entity, &A)>()
527            .par_iter(&world)
528            .for_each(|(e, &A(i))| {
529                results.lock().unwrap().push((e, i));
530            });
531        results.lock().unwrap().sort();
532        let mut expected = [(e1, 1), (e2, 2), (e3, 3), (e4, 4), (e5, 5)];
533        expected.sort();
534        assert_eq!(&*results.lock().unwrap(), &expected);
535    }
536
537    #[test]
538    fn par_for_each_sparse() {
539        ComputeTaskPool::get_or_init(TaskPool::default);
540        let mut world = World::new();
541        let e1 = world.spawn(SparseStored(1)).id();
542        let e2 = world.spawn(SparseStored(2)).id();
543        let e3 = world.spawn(SparseStored(3)).id();
544        let e4 = world.spawn((SparseStored(4), A(1))).id();
545        let e5 = world.spawn((SparseStored(5), A(1))).id();
546        let results = Arc::new(Mutex::new(Vec::new()));
547        world
548            .query::<(Entity, &SparseStored)>()
549            .par_iter(&world)
550            .for_each(|(e, &SparseStored(i))| results.lock().unwrap().push((e, i)));
551        results.lock().unwrap().sort();
552        let mut expected = [(e1, 1), (e2, 2), (e3, 3), (e4, 4), (e5, 5)];
553        expected.sort();
554        assert_eq!(&*results.lock().unwrap(), &expected);
555    }
556
557    #[test]
558    fn query_missing_component() {
559        let mut world = World::new();
560        world.spawn((TableStored("abc"), A(123)));
561        world.spawn((TableStored("def"), A(456)));
562        assert!(world.query::<(&B, &A)>().iter(&world).next().is_none());
563    }
564
565    #[test]
566    fn query_sparse_component() {
567        let mut world = World::new();
568        world.spawn((TableStored("abc"), A(123)));
569        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
570        let ents = world
571            .query::<(Entity, &B)>()
572            .iter(&world)
573            .map(|(e, &b)| (e, b))
574            .collect::<Vec<_>>();
575        assert_eq!(ents, &[(f, B(1))]);
576    }
577
578    #[test]
579    fn query_filter_with() {
580        let mut world = World::new();
581        world.spawn((A(123), B(1)));
582        world.spawn(A(456));
583        let result = world
584            .query_filtered::<&A, With<B>>()
585            .iter(&world)
586            .cloned()
587            .collect::<Vec<_>>();
588        assert_eq!(result, vec![A(123)]);
589    }
590
591    #[test]
592    fn query_filter_with_for_each() {
593        let mut world = World::new();
594        world.spawn((A(123), B(1)));
595        world.spawn(A(456));
596
597        let mut results = Vec::new();
598        world
599            .query_filtered::<&A, With<B>>()
600            .iter(&world)
601            .for_each(|i| results.push(*i));
602        assert_eq!(results, vec![A(123)]);
603    }
604
605    #[test]
606    fn query_filter_with_sparse() {
607        let mut world = World::new();
608
609        world.spawn((A(123), SparseStored(321)));
610        world.spawn(A(456));
611        let result = world
612            .query_filtered::<&A, With<SparseStored>>()
613            .iter(&world)
614            .cloned()
615            .collect::<Vec<_>>();
616        assert_eq!(result, vec![A(123)]);
617    }
618
619    #[test]
620    fn query_filter_with_sparse_for_each() {
621        let mut world = World::new();
622
623        world.spawn((A(123), SparseStored(321)));
624        world.spawn(A(456));
625        let mut results = Vec::new();
626        world
627            .query_filtered::<&A, With<SparseStored>>()
628            .iter(&world)
629            .for_each(|i| results.push(*i));
630        assert_eq!(results, vec![A(123)]);
631    }
632
633    #[test]
634    fn query_filter_without() {
635        let mut world = World::new();
636        world.spawn((A(123), B(321)));
637        world.spawn(A(456));
638        let result = world
639            .query_filtered::<&A, Without<B>>()
640            .iter(&world)
641            .cloned()
642            .collect::<Vec<_>>();
643        assert_eq!(result, vec![A(456)]);
644    }
645
646    #[test]
647    fn query_optional_component_table() {
648        let mut world = World::new();
649        let e = world.spawn((TableStored("abc"), A(123))).id();
650        let f = world.spawn((TableStored("def"), A(456), B(1))).id();
651        // this should be skipped
652        world.spawn(TableStored("abc"));
653        let ents = world
654            .query::<(Entity, Option<&B>, &A)>()
655            .iter(&world)
656            .map(|(e, b, &i)| (e, b.copied(), i))
657            .collect::<HashSet<_>>();
658        assert!(ents.contains(&(e, None, A(123))));
659        assert!(ents.contains(&(f, Some(B(1)), A(456))));
660    }
661
662    #[test]
663    fn query_optional_component_sparse() {
664        let mut world = World::new();
665
666        let e = world.spawn((TableStored("abc"), A(123))).id();
667        let f = world
668            .spawn((TableStored("def"), A(456), SparseStored(1)))
669            .id();
670        // this should be skipped
671        // world.spawn(SparseStored(1));
672        let ents = world
673            .query::<(Entity, Option<&SparseStored>, &A)>()
674            .iter(&world)
675            .map(|(e, b, &i)| (e, b.copied(), i))
676            .collect::<HashSet<_>>();
677        assert_eq!(
678            ents,
679            [(e, None, A(123)), (f, Some(SparseStored(1)), A(456))]
680                .into_iter()
681                .collect::<HashSet<_>>()
682        );
683    }
684
685    #[test]
686    fn query_optional_component_sparse_no_match() {
687        let mut world = World::new();
688
689        let e = world.spawn((TableStored("abc"), A(123))).id();
690        let f = world.spawn((TableStored("def"), A(456))).id();
691        // // this should be skipped
692        world.spawn(TableStored("abc"));
693        let ents = world
694            .query::<(Entity, Option<&SparseStored>, &A)>()
695            .iter(&world)
696            .map(|(e, b, &i)| (e, b.copied(), i))
697            .collect::<Vec<_>>();
698        assert_eq!(ents, &[(e, None, A(123)), (f, None, A(456))]);
699    }
700
701    #[test]
702    fn add_remove_components() {
703        let mut world = World::new();
704        let e1 = world.spawn((A(1), B(3), TableStored("abc"))).id();
705        let e2 = world.spawn((A(2), B(4), TableStored("xyz"))).id();
706
707        assert_eq!(
708            world
709                .query::<(Entity, &A, &B)>()
710                .iter(&world)
711                .map(|(e, &i, &b)| (e, i, b))
712                .collect::<HashSet<_>>(),
713            [(e1, A(1), B(3)), (e2, A(2), B(4))]
714                .into_iter()
715                .collect::<HashSet<_>>()
716        );
717        assert_eq!(world.entity_mut(e1).take::<A>(), Some(A(1)));
718        assert_eq!(
719            world
720                .query::<(Entity, &A, &B)>()
721                .iter(&world)
722                .map(|(e, &i, &b)| (e, i, b))
723                .collect::<Vec<_>>(),
724            &[(e2, A(2), B(4))]
725        );
726        assert_eq!(
727            world
728                .query::<(Entity, &B, &TableStored)>()
729                .iter(&world)
730                .map(|(e, &B(b), &TableStored(s))| (e, b, s))
731                .collect::<HashSet<_>>(),
732            [(e2, 4, "xyz"), (e1, 3, "abc")]
733                .into_iter()
734                .collect::<HashSet<_>>()
735        );
736        world.entity_mut(e1).insert(A(43));
737        assert_eq!(
738            world
739                .query::<(Entity, &A, &B)>()
740                .iter(&world)
741                .map(|(e, &i, &b)| (e, i, b))
742                .collect::<HashSet<_>>(),
743            [(e2, A(2), B(4)), (e1, A(43), B(3))]
744                .into_iter()
745                .collect::<HashSet<_>>()
746        );
747        world.entity_mut(e1).insert(C);
748        assert_eq!(
749            world
750                .query::<(Entity, &C)>()
751                .iter(&world)
752                .map(|(e, &f)| (e, f))
753                .collect::<Vec<_>>(),
754            &[(e1, C)]
755        );
756    }
757
758    #[test]
759    fn table_add_remove_many() {
760        let mut world = World::default();
761        #[cfg(miri)]
762        let (mut entities, to) = {
763            let to = 10;
764            (Vec::with_capacity(to), to)
765        };
766        #[cfg(not(miri))]
767        let (mut entities, to) = {
768            let to = 10_000;
769            (Vec::with_capacity(to), to)
770        };
771
772        for _ in 0..to {
773            entities.push(world.spawn(B(0)).id());
774        }
775
776        for (i, entity) in entities.iter().cloned().enumerate() {
777            world.entity_mut(entity).insert(A(i));
778        }
779
780        for (i, entity) in entities.iter().cloned().enumerate() {
781            assert_eq!(world.entity_mut(entity).take::<A>(), Some(A(i)));
782        }
783    }
784
785    #[test]
786    fn sparse_set_add_remove_many() {
787        let mut world = World::default();
788
789        let mut entities = Vec::with_capacity(1000);
790        for _ in 0..4 {
791            entities.push(world.spawn(A(2)).id());
792        }
793
794        for (i, entity) in entities.iter().cloned().enumerate() {
795            world.entity_mut(entity).insert(SparseStored(i as u32));
796        }
797
798        for (i, entity) in entities.iter().cloned().enumerate() {
799            assert_eq!(
800                world.entity_mut(entity).take::<SparseStored>(),
801                Some(SparseStored(i as u32))
802            );
803        }
804    }
805
806    #[test]
807    fn remove_missing() {
808        let mut world = World::new();
809        let e = world.spawn((TableStored("abc"), A(123))).id();
810        assert!(world.entity_mut(e).take::<B>().is_none());
811    }
812
813    #[test]
814    fn spawn_batch() {
815        let mut world = World::new();
816        world.spawn_batch((0..100).map(|x| (A(x), TableStored("abc"))));
817        let values = world
818            .query::<&A>()
819            .iter(&world)
820            .map(|v| v.0)
821            .collect::<Vec<_>>();
822        let expected = (0..100).collect::<Vec<_>>();
823        assert_eq!(values, expected);
824    }
825
826    #[test]
827    fn query_get() {
828        let mut world = World::new();
829        let a = world.spawn((TableStored("abc"), A(123))).id();
830        let b = world.spawn((TableStored("def"), A(456))).id();
831        let c = world.spawn((TableStored("ghi"), A(789), B(1))).id();
832
833        let mut i32_query = world.query::<&A>();
834        assert_eq!(i32_query.get(&world, a).unwrap().0, 123);
835        assert_eq!(i32_query.get(&world, b).unwrap().0, 456);
836
837        let mut i32_bool_query = world.query::<(&A, &B)>();
838        assert!(i32_bool_query.get(&world, a).is_err());
839        assert_eq!(i32_bool_query.get(&world, c).unwrap(), (&A(789), &B(1)));
840        assert!(world.despawn(a));
841        assert!(i32_query.get(&world, a).is_err());
842    }
843
844    #[test]
845    fn query_get_works_across_sparse_removal() {
846        // Regression test for: https://github.com/bevyengine/bevy/issues/6623
847        let mut world = World::new();
848        let a = world.spawn((TableStored("abc"), SparseStored(123))).id();
849        let b = world.spawn((TableStored("def"), SparseStored(456))).id();
850        let c = world
851            .spawn((TableStored("ghi"), SparseStored(789), B(1)))
852            .id();
853
854        let mut query = world.query::<&TableStored>();
855        assert_eq!(query.get(&world, a).unwrap(), &TableStored("abc"));
856        assert_eq!(query.get(&world, b).unwrap(), &TableStored("def"));
857        assert_eq!(query.get(&world, c).unwrap(), &TableStored("ghi"));
858
859        world.entity_mut(b).remove::<SparseStored>();
860        world.entity_mut(c).remove::<SparseStored>();
861
862        assert_eq!(query.get(&world, a).unwrap(), &TableStored("abc"));
863        assert_eq!(query.get(&world, b).unwrap(), &TableStored("def"));
864        assert_eq!(query.get(&world, c).unwrap(), &TableStored("ghi"));
865    }
866
867    #[test]
868    fn remove_tracking() {
869        let mut world = World::new();
870
871        let a = world.spawn((SparseStored(0), A(123))).id();
872        let b = world.spawn((SparseStored(1), A(123))).id();
873
874        world.entity_mut(a).despawn();
875        assert_eq!(
876            world.removed::<A>().collect::<Vec<_>>(),
877            &[a],
878            "despawning results in 'removed component' state for table components"
879        );
880        assert_eq!(
881            world.removed::<SparseStored>().collect::<Vec<_>>(),
882            &[a],
883            "despawning results in 'removed component' state for sparse set components"
884        );
885
886        world.entity_mut(b).insert(B(1));
887        assert_eq!(
888            world.removed::<A>().collect::<Vec<_>>(),
889            &[a],
890            "archetype moves does not result in 'removed component' state"
891        );
892
893        world.entity_mut(b).remove::<A>();
894        assert_eq!(
895            world.removed::<A>().collect::<Vec<_>>(),
896            &[a, b],
897            "removing a component results in a 'removed component' state"
898        );
899
900        world.clear_trackers();
901        assert_eq!(
902            world.removed::<A>().collect::<Vec<_>>(),
903            &[],
904            "clearing trackers clears removals"
905        );
906        assert_eq!(
907            world.removed::<SparseStored>().collect::<Vec<_>>(),
908            &[],
909            "clearing trackers clears removals"
910        );
911        assert_eq!(
912            world.removed::<B>().collect::<Vec<_>>(),
913            &[],
914            "clearing trackers clears removals"
915        );
916
917        // TODO: uncomment when world.clear() is implemented
918        // let c = world.spawn(("abc", 123)).id();
919        // let d = world.spawn(("abc", 123)).id();
920        // world.clear();
921        // assert_eq!(
922        //     world.removed::<i32>(),
923        //     &[c, d],
924        //     "world clears result in 'removed component' states"
925        // );
926        // assert_eq!(
927        //     world.removed::<&'static str>(),
928        //     &[c, d, b],
929        //     "world clears result in 'removed component' states"
930        // );
931        // assert_eq!(
932        //     world.removed::<f64>(),
933        //     &[b],
934        //     "world clears result in 'removed component' states"
935        // );
936    }
937
938    #[test]
939    fn added_tracking() {
940        let mut world = World::new();
941        let a = world.spawn(A(123)).id();
942
943        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
944        assert_eq!(
945            world.query_filtered::<(), Added<A>>().iter(&world).count(),
946            1
947        );
948        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
949        assert_eq!(
950            world.query_filtered::<(), Added<A>>().iter(&world).count(),
951            1
952        );
953        assert!(world.query::<&A>().get(&world, a).is_ok());
954        assert!(world
955            .query_filtered::<(), Added<A>>()
956            .get(&world, a)
957            .is_ok());
958        assert!(world.query::<&A>().get(&world, a).is_ok());
959        assert!(world
960            .query_filtered::<(), Added<A>>()
961            .get(&world, a)
962            .is_ok());
963
964        world.clear_trackers();
965
966        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
967        assert_eq!(
968            world.query_filtered::<(), Added<A>>().iter(&world).count(),
969            0
970        );
971        assert_eq!(world.query::<&A>().iter(&world).count(), 1);
972        assert_eq!(
973            world.query_filtered::<(), Added<A>>().iter(&world).count(),
974            0
975        );
976        assert!(world.query::<&A>().get(&world, a).is_ok());
977        assert!(world
978            .query_filtered::<(), Added<A>>()
979            .get(&world, a)
980            .is_err());
981        assert!(world.query::<&A>().get(&world, a).is_ok());
982        assert!(world
983            .query_filtered::<(), Added<A>>()
984            .get(&world, a)
985            .is_err());
986    }
987
988    #[test]
989    fn added_queries() {
990        let mut world = World::default();
991        let e1 = world.spawn(A(0)).id();
992
993        fn get_added<Com: Component>(world: &mut World) -> Vec<Entity> {
994            world
995                .query_filtered::<Entity, Added<Com>>()
996                .iter(world)
997                .collect::<Vec<Entity>>()
998        }
999
1000        assert_eq!(get_added::<A>(&mut world), vec![e1]);
1001        world.entity_mut(e1).insert(B(0));
1002        assert_eq!(get_added::<A>(&mut world), vec![e1]);
1003        assert_eq!(get_added::<B>(&mut world), vec![e1]);
1004
1005        world.clear_trackers();
1006        assert!(get_added::<A>(&mut world).is_empty());
1007        let e2 = world.spawn((A(1), B(1))).id();
1008        assert_eq!(get_added::<A>(&mut world), vec![e2]);
1009        assert_eq!(get_added::<B>(&mut world), vec![e2]);
1010
1011        let added = world
1012            .query_filtered::<Entity, (Added<A>, Added<B>)>()
1013            .iter(&world)
1014            .collect::<Vec<Entity>>();
1015        assert_eq!(added, vec![e2]);
1016    }
1017
1018    #[test]
1019    fn changed_trackers() {
1020        let mut world = World::default();
1021        let e1 = world.spawn((A(0), B(0))).id();
1022        let e2 = world.spawn((A(0), B(0))).id();
1023        let e3 = world.spawn((A(0), B(0))).id();
1024        world.spawn((A(0), B(0)));
1025
1026        world.clear_trackers();
1027
1028        for (i, mut a) in world.query::<&mut A>().iter_mut(&mut world).enumerate() {
1029            if i % 2 == 0 {
1030                a.0 += 1;
1031            }
1032        }
1033
1034        fn get_filtered<F: QueryFilter>(world: &mut World) -> HashSet<Entity> {
1035            world
1036                .query_filtered::<Entity, F>()
1037                .iter(world)
1038                .collect::<HashSet<Entity>>()
1039        }
1040
1041        assert_eq!(
1042            get_filtered::<Changed<A>>(&mut world),
1043            [e1, e3].into_iter().collect::<HashSet<_>>()
1044        );
1045
1046        // ensure changing an entity's archetypes also moves its changed state
1047        world.entity_mut(e1).insert(C);
1048
1049        assert_eq!(
1050            get_filtered::<Changed<A>>(&mut world),
1051            [e3, e1].into_iter().collect::<HashSet<_>>(),
1052            "changed entities list should not change"
1053        );
1054
1055        // spawning a new A entity should not change existing changed state
1056        world.entity_mut(e1).insert((A(0), B(0)));
1057
1058        assert_eq!(
1059            get_filtered::<Changed<A>>(&mut world),
1060            [e3, e1].into_iter().collect::<HashSet<_>>(),
1061            "changed entities list should not change"
1062        );
1063
1064        // removing an unchanged entity should not change changed state
1065        assert!(world.despawn(e2));
1066        assert_eq!(
1067            get_filtered::<Changed<A>>(&mut world),
1068            [e3, e1].into_iter().collect::<HashSet<_>>(),
1069            "changed entities list should not change"
1070        );
1071
1072        // removing a changed entity should remove it from enumeration
1073        assert!(world.despawn(e1));
1074        assert_eq!(
1075            get_filtered::<Changed<A>>(&mut world),
1076            [e3].into_iter().collect::<HashSet<_>>(),
1077            "e1 should no longer be returned"
1078        );
1079
1080        world.clear_trackers();
1081
1082        assert!(get_filtered::<Changed<A>>(&mut world).is_empty());
1083
1084        let e4 = world.spawn_empty().id();
1085
1086        world.entity_mut(e4).insert(A(0));
1087        assert_eq!(
1088            get_filtered::<Changed<A>>(&mut world),
1089            [e4].into_iter().collect::<HashSet<_>>()
1090        );
1091        assert_eq!(
1092            get_filtered::<Added<A>>(&mut world),
1093            [e4].into_iter().collect::<HashSet<_>>()
1094        );
1095
1096        world.entity_mut(e4).insert(A(1));
1097        assert_eq!(
1098            get_filtered::<Changed<A>>(&mut world),
1099            [e4].into_iter().collect::<HashSet<_>>()
1100        );
1101
1102        world.clear_trackers();
1103
1104        // ensure inserting multiple components set changed state for all components and set added
1105        // state for non existing components even when changing archetype.
1106        world.entity_mut(e4).insert((A(0), B(0)));
1107
1108        assert!(get_filtered::<Added<A>>(&mut world).is_empty());
1109        assert_eq!(
1110            get_filtered::<Changed<A>>(&mut world),
1111            [e4].into_iter().collect::<HashSet<_>>()
1112        );
1113        assert_eq!(
1114            get_filtered::<Added<B>>(&mut world),
1115            [e4].into_iter().collect::<HashSet<_>>()
1116        );
1117        assert_eq!(
1118            get_filtered::<Changed<B>>(&mut world),
1119            [e4].into_iter().collect::<HashSet<_>>()
1120        );
1121    }
1122
1123    #[test]
1124    fn changed_trackers_sparse() {
1125        let mut world = World::default();
1126        let e1 = world.spawn(SparseStored(0)).id();
1127        let e2 = world.spawn(SparseStored(0)).id();
1128        let e3 = world.spawn(SparseStored(0)).id();
1129        world.spawn(SparseStored(0));
1130
1131        world.clear_trackers();
1132
1133        for (i, mut a) in world
1134            .query::<&mut SparseStored>()
1135            .iter_mut(&mut world)
1136            .enumerate()
1137        {
1138            if i % 2 == 0 {
1139                a.0 += 1;
1140            }
1141        }
1142
1143        fn get_filtered<F: QueryFilter>(world: &mut World) -> HashSet<Entity> {
1144            world
1145                .query_filtered::<Entity, F>()
1146                .iter(world)
1147                .collect::<HashSet<Entity>>()
1148        }
1149
1150        assert_eq!(
1151            get_filtered::<Changed<SparseStored>>(&mut world),
1152            [e1, e3].into_iter().collect::<HashSet<_>>()
1153        );
1154
1155        // ensure changing an entity's archetypes also moves its changed state
1156        world.entity_mut(e1).insert(C);
1157
1158        assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), [e3, e1].into_iter().collect::<HashSet<_>>(), "changed entities list should not change (although the order will due to archetype moves)");
1159
1160        // spawning a new SparseStored entity should not change existing changed state
1161        world.entity_mut(e1).insert(SparseStored(0));
1162        assert_eq!(
1163            get_filtered::<Changed<SparseStored>>(&mut world),
1164            [e3, e1].into_iter().collect::<HashSet<_>>(),
1165            "changed entities list should not change"
1166        );
1167
1168        // removing an unchanged entity should not change changed state
1169        assert!(world.despawn(e2));
1170        assert_eq!(
1171            get_filtered::<Changed<SparseStored>>(&mut world),
1172            [e3, e1].into_iter().collect::<HashSet<_>>(),
1173            "changed entities list should not change"
1174        );
1175
1176        // removing a changed entity should remove it from enumeration
1177        assert!(world.despawn(e1));
1178        assert_eq!(
1179            get_filtered::<Changed<SparseStored>>(&mut world),
1180            [e3].into_iter().collect::<HashSet<_>>(),
1181            "e1 should no longer be returned"
1182        );
1183
1184        world.clear_trackers();
1185
1186        assert!(get_filtered::<Changed<SparseStored>>(&mut world).is_empty());
1187
1188        let e4 = world.spawn_empty().id();
1189
1190        world.entity_mut(e4).insert(SparseStored(0));
1191        assert_eq!(
1192            get_filtered::<Changed<SparseStored>>(&mut world),
1193            [e4].into_iter().collect::<HashSet<_>>()
1194        );
1195        assert_eq!(
1196            get_filtered::<Added<SparseStored>>(&mut world),
1197            [e4].into_iter().collect::<HashSet<_>>()
1198        );
1199
1200        world.entity_mut(e4).insert(A(1));
1201        assert_eq!(
1202            get_filtered::<Changed<SparseStored>>(&mut world),
1203            [e4].into_iter().collect::<HashSet<_>>()
1204        );
1205
1206        world.clear_trackers();
1207
1208        // ensure inserting multiple components set changed state for all components and set added
1209        // state for non existing components even when changing archetype.
1210        world.entity_mut(e4).insert(SparseStored(0));
1211
1212        assert!(get_filtered::<Added<SparseStored>>(&mut world).is_empty());
1213        assert_eq!(
1214            get_filtered::<Changed<SparseStored>>(&mut world),
1215            [e4].into_iter().collect::<HashSet<_>>()
1216        );
1217    }
1218
1219    #[test]
1220    fn empty_spawn() {
1221        let mut world = World::default();
1222        let e = world.spawn_empty().id();
1223        let mut e_mut = world.entity_mut(e);
1224        e_mut.insert(A(0));
1225        assert_eq!(e_mut.get::<A>().unwrap(), &A(0));
1226    }
1227
1228    #[test]
1229    fn changed_query() {
1230        let mut world = World::default();
1231        let e1 = world.spawn((A(0), B(0))).id();
1232
1233        fn get_changed(world: &mut World) -> Vec<Entity> {
1234            world
1235                .query_filtered::<Entity, Changed<A>>()
1236                .iter(world)
1237                .collect::<Vec<Entity>>()
1238        }
1239        assert_eq!(get_changed(&mut world), vec![e1]);
1240        world.clear_trackers();
1241        assert_eq!(get_changed(&mut world), vec![]);
1242        *world.get_mut(e1).unwrap() = A(1);
1243        assert_eq!(get_changed(&mut world), vec![e1]);
1244    }
1245
1246    #[test]
1247    fn resource() {
1248        use crate::resource::Resource;
1249
1250        #[derive(Resource, PartialEq, Debug)]
1251        struct Num(i32);
1252
1253        #[derive(Resource, PartialEq, Debug)]
1254        struct BigNum(u64);
1255
1256        let mut world = World::default();
1257        assert!(world.get_resource::<Num>().is_none());
1258        assert!(!world.contains_resource::<Num>());
1259        assert!(!world.is_resource_added::<Num>());
1260        assert!(!world.is_resource_changed::<Num>());
1261
1262        world.insert_resource(Num(123));
1263        let resource_id = world
1264            .components()
1265            .get_resource_id(TypeId::of::<Num>())
1266            .unwrap();
1267
1268        assert_eq!(world.resource::<Num>().0, 123);
1269        assert!(world.contains_resource::<Num>());
1270        assert!(world.is_resource_added::<Num>());
1271        assert!(world.is_resource_changed::<Num>());
1272
1273        world.insert_resource(BigNum(456));
1274        assert_eq!(world.resource::<BigNum>().0, 456u64);
1275
1276        world.insert_resource(BigNum(789));
1277        assert_eq!(world.resource::<BigNum>().0, 789);
1278
1279        {
1280            let mut value = world.resource_mut::<BigNum>();
1281            assert_eq!(value.0, 789);
1282            value.0 = 10;
1283        }
1284
1285        assert_eq!(
1286            world.resource::<BigNum>().0,
1287            10,
1288            "resource changes are preserved"
1289        );
1290
1291        assert_eq!(
1292            world.remove_resource::<BigNum>(),
1293            Some(BigNum(10)),
1294            "removed resource has the correct value"
1295        );
1296        assert_eq!(
1297            world.get_resource::<BigNum>(),
1298            None,
1299            "removed resource no longer exists"
1300        );
1301        assert_eq!(
1302            world.remove_resource::<BigNum>(),
1303            None,
1304            "double remove returns nothing"
1305        );
1306
1307        world.insert_resource(BigNum(1));
1308        assert_eq!(
1309            world.get_resource::<BigNum>(),
1310            Some(&BigNum(1)),
1311            "re-inserting resources works"
1312        );
1313
1314        assert_eq!(
1315            world.get_resource::<Num>(),
1316            Some(&Num(123)),
1317            "other resources are unaffected"
1318        );
1319
1320        let current_resource_id = world
1321            .components()
1322            .get_resource_id(TypeId::of::<Num>())
1323            .unwrap();
1324        assert_eq!(
1325            resource_id, current_resource_id,
1326            "resource id does not change after removing / re-adding"
1327        );
1328    }
1329
1330    #[test]
1331    fn remove() {
1332        let mut world = World::default();
1333        let e1 = world.spawn((A(1), B(1), TableStored("a"))).id();
1334
1335        let mut e = world.entity_mut(e1);
1336        assert_eq!(e.get::<TableStored>(), Some(&TableStored("a")));
1337        assert_eq!(e.get::<A>(), Some(&A(1)));
1338        assert_eq!(e.get::<B>(), Some(&B(1)));
1339        assert_eq!(
1340            e.get::<C>(),
1341            None,
1342            "C is not in the entity, so it should not exist"
1343        );
1344
1345        e.remove::<(A, B, C)>();
1346        assert_eq!(
1347            e.get::<TableStored>(),
1348            Some(&TableStored("a")),
1349            "TableStored is not in the removed bundle, so it should exist"
1350        );
1351        assert_eq!(
1352            e.get::<A>(),
1353            None,
1354            "Num is in the removed bundle, so it should not exist"
1355        );
1356        assert_eq!(
1357            e.get::<B>(),
1358            None,
1359            "f64 is in the removed bundle, so it should not exist"
1360        );
1361        assert_eq!(
1362            e.get::<C>(),
1363            None,
1364            "usize is in the removed bundle, so it should not exist"
1365        );
1366    }
1367
1368    #[test]
1369    fn take() {
1370        let mut world = World::default();
1371        world.spawn((A(1), B(1), TableStored("1")));
1372        let e2 = world.spawn((A(2), B(2), TableStored("2"))).id();
1373        world.spawn((A(3), B(3), TableStored("3")));
1374
1375        let mut query = world.query::<(&B, &TableStored)>();
1376        let results = query
1377            .iter(&world)
1378            .map(|(a, b)| (a.0, b.0))
1379            .collect::<HashSet<_>>();
1380        assert_eq!(
1381            results,
1382            [(1, "1"), (2, "2"), (3, "3"),]
1383                .into_iter()
1384                .collect::<HashSet<_>>()
1385        );
1386
1387        let removed_bundle = world.entity_mut(e2).take::<(B, TableStored)>().unwrap();
1388        assert_eq!(removed_bundle, (B(2), TableStored("2")));
1389
1390        let results = query
1391            .iter(&world)
1392            .map(|(a, b)| (a.0, b.0))
1393            .collect::<HashSet<_>>();
1394        assert_eq!(
1395            results,
1396            [(1, "1"), (3, "3"),].into_iter().collect::<HashSet<_>>()
1397        );
1398
1399        let mut a_query = world.query::<&A>();
1400        let results = a_query.iter(&world).map(|a| a.0).collect::<HashSet<_>>();
1401        assert_eq!(results, [1, 3, 2].into_iter().collect::<HashSet<_>>());
1402
1403        let entity_ref = world.entity(e2);
1404        assert_eq!(
1405            entity_ref.get::<A>(),
1406            Some(&A(2)),
1407            "A is not in the removed bundle, so it should exist"
1408        );
1409        assert_eq!(
1410            entity_ref.get::<B>(),
1411            None,
1412            "B is in the removed bundle, so it should not exist"
1413        );
1414        assert_eq!(
1415            entity_ref.get::<TableStored>(),
1416            None,
1417            "TableStored is in the removed bundle, so it should not exist"
1418        );
1419    }
1420
1421    #[test]
1422    fn non_send_resource() {
1423        let mut world = World::default();
1424        world.insert_non_send_resource(123i32);
1425        world.insert_non_send_resource(456i64);
1426        assert_eq!(*world.non_send_resource::<i32>(), 123);
1427        assert_eq!(*world.non_send_resource_mut::<i64>(), 456);
1428    }
1429
1430    #[test]
1431    fn non_send_resource_points_to_distinct_data() {
1432        let mut world = World::default();
1433        world.insert_resource(ResA(123));
1434        world.insert_non_send_resource(ResA(456));
1435        assert_eq!(*world.resource::<ResA>(), ResA(123));
1436        assert_eq!(*world.non_send_resource::<ResA>(), ResA(456));
1437    }
1438
1439    #[test]
1440    #[should_panic]
1441    fn non_send_resource_panic() {
1442        let mut world = World::default();
1443        world.insert_non_send_resource(0i32);
1444        std::thread::spawn(move || {
1445            let _ = world.non_send_resource_mut::<i32>();
1446        })
1447        .join()
1448        .unwrap();
1449    }
1450
1451    #[test]
1452    fn exact_size_query() {
1453        let mut world = World::default();
1454        world.spawn((A(0), B(0)));
1455        world.spawn((A(0), B(0)));
1456        world.spawn((A(0), B(0), C));
1457        world.spawn(C);
1458
1459        let mut query = world.query::<(&A, &B)>();
1460        assert_eq!(query.iter(&world).len(), 3);
1461    }
1462
1463    #[test]
1464    #[should_panic]
1465    fn duplicate_components_panic() {
1466        let mut world = World::new();
1467        world.spawn((A(1), A(2)));
1468    }
1469
1470    #[test]
1471    #[should_panic]
1472    fn ref_and_mut_query_panic() {
1473        let mut world = World::new();
1474        world.query::<(&A, &mut A)>();
1475    }
1476
1477    #[test]
1478    #[should_panic]
1479    fn entity_ref_and_mut_query_panic() {
1480        let mut world = World::new();
1481        world.query::<(EntityRef, &mut A)>();
1482    }
1483
1484    #[test]
1485    #[should_panic]
1486    fn mut_and_ref_query_panic() {
1487        let mut world = World::new();
1488        world.query::<(&mut A, &A)>();
1489    }
1490
1491    #[test]
1492    #[should_panic]
1493    fn mut_and_entity_ref_query_panic() {
1494        let mut world = World::new();
1495        world.query::<(&mut A, EntityRef)>();
1496    }
1497
1498    #[test]
1499    #[should_panic]
1500    fn entity_ref_and_entity_mut_query_panic() {
1501        let mut world = World::new();
1502        world.query::<(EntityRef, EntityMut)>();
1503    }
1504
1505    #[test]
1506    #[should_panic]
1507    fn entity_mut_and_entity_mut_query_panic() {
1508        let mut world = World::new();
1509        world.query::<(EntityMut, EntityMut)>();
1510    }
1511
1512    #[test]
1513    fn entity_ref_and_entity_ref_query_no_panic() {
1514        let mut world = World::new();
1515        world.query::<(EntityRef, EntityRef)>();
1516    }
1517
1518    #[test]
1519    #[should_panic]
1520    fn mut_and_mut_query_panic() {
1521        let mut world = World::new();
1522        world.query::<(&mut A, &mut A)>();
1523    }
1524
1525    #[test]
1526    #[should_panic]
1527    fn multiple_worlds_same_query_iter() {
1528        let mut world_a = World::new();
1529        let world_b = World::new();
1530        let mut query = world_a.query::<&A>();
1531        query.iter(&world_a);
1532        query.iter(&world_b);
1533    }
1534
1535    #[test]
1536    fn query_filters_dont_collide_with_fetches() {
1537        let mut world = World::new();
1538        world.query_filtered::<&mut A, Changed<A>>();
1539    }
1540
1541    #[test]
1542    fn filtered_query_access() {
1543        let mut world = World::new();
1544        // We remove entity disabling so it doesn't affect our query filters
1545        world.remove_resource::<DefaultQueryFilters>();
1546        let query = world.query_filtered::<&mut A, Changed<B>>();
1547
1548        let mut expected = FilteredAccess::default();
1549        let a_id = world.components.get_id(TypeId::of::<A>()).unwrap();
1550        let b_id = world.components.get_id(TypeId::of::<B>()).unwrap();
1551        expected.add_component_write(a_id);
1552        expected.add_component_read(b_id);
1553        assert!(
1554            query.component_access.eq(&expected),
1555            "ComponentId access from query fetch and query filter should be combined"
1556        );
1557    }
1558
1559    #[test]
1560    #[should_panic]
1561    fn multiple_worlds_same_query_get() {
1562        let mut world_a = World::new();
1563        let world_b = World::new();
1564        let mut query = world_a.query::<&A>();
1565        let _ = query.get(&world_a, Entity::from_raw_u32(0).unwrap());
1566        let _ = query.get(&world_b, Entity::from_raw_u32(0).unwrap());
1567    }
1568
1569    #[test]
1570    #[should_panic]
1571    fn multiple_worlds_same_query_for_each() {
1572        let mut world_a = World::new();
1573        let world_b = World::new();
1574        let mut query = world_a.query::<&A>();
1575        query.iter(&world_a).for_each(|_| {});
1576        query.iter(&world_b).for_each(|_| {});
1577    }
1578
1579    #[test]
1580    fn resource_scope() {
1581        let mut world = World::default();
1582        assert!(world.try_resource_scope::<ResA, _>(|_, _| {}).is_none());
1583        world.insert_resource(ResA(0));
1584        world.resource_scope(|world: &mut World, mut value: Mut<ResA>| {
1585            value.0 += 1;
1586            assert!(!world.contains_resource::<ResA>());
1587        });
1588        assert_eq!(world.resource::<ResA>().0, 1);
1589    }
1590
1591    #[cfg(feature = "std")]
1592    #[test]
1593    fn resource_scope_unwind() {
1594        #[derive(Debug, PartialEq)]
1595        struct Panic;
1596
1597        let mut world = World::default();
1598        assert!(world.try_resource_scope::<ResA, _>(|_, _| {}).is_none());
1599        world.insert_resource(ResA(0));
1600        let panic = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
1601            world.resource_scope(|world: &mut World, _value: Mut<ResA>| {
1602                assert!(!world.contains_resource::<ResA>());
1603                std::panic::panic_any(Panic);
1604            });
1605            unreachable!();
1606        }));
1607        assert_eq!(panic.unwrap_err().downcast_ref::<Panic>(), Some(&Panic));
1608        assert!(world.contains_resource::<ResA>());
1609    }
1610
1611    // NOTE: this test is meant to validate the current behavior of `{try_}resource_scope` when resource metadata is cleared
1612    // within the scope. future contributors who wish to change this behavior should feel free to delete this test.
1613    #[test]
1614    fn resource_scope_resources_cleared() {
1615        let mut world = World::default();
1616        assert!(world.try_resource_scope::<ResA, _>(|_, _| {}).is_none());
1617        world.insert_resource(ResA(0));
1618        let r = world.try_resource_scope(|world: &mut World, _value: Mut<ResA>| {
1619            assert!(!world.contains_resource::<ResA>());
1620            world.clear_resources();
1621        });
1622        assert_eq!(r, None);
1623        assert!(!world.contains_resource::<ResA>());
1624    }
1625
1626    #[test]
1627    #[should_panic]
1628    fn non_send_resource_drop_from_different_thread() {
1629        let mut world = World::default();
1630        world.insert_non_send_resource(NonSendA::default());
1631
1632        let thread = std::thread::spawn(move || {
1633            // Dropping the non-send resource on a different thread
1634            // Should result in a panic
1635            drop(world);
1636        });
1637
1638        if let Err(err) = thread.join() {
1639            std::panic::resume_unwind(err);
1640        }
1641    }
1642
1643    #[test]
1644    fn non_send_resource_drop_from_same_thread() {
1645        let mut world = World::default();
1646        world.insert_non_send_resource(NonSendA::default());
1647        drop(world);
1648    }
1649
1650    #[test]
1651    fn insert_overwrite_drop() {
1652        let (dropck1, dropped1) = DropCk::new_pair();
1653        let (dropck2, dropped2) = DropCk::new_pair();
1654        let mut world = World::default();
1655        world.spawn(dropck1).insert(dropck2);
1656        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1657        assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1658        drop(world);
1659        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1660        assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1661    }
1662
1663    #[test]
1664    fn insert_overwrite_drop_sparse() {
1665        let (dropck1, dropped1) = DropCk::new_pair();
1666        let (dropck2, dropped2) = DropCk::new_pair();
1667        let mut world = World::default();
1668
1669        world
1670            .spawn(DropCkSparse(dropck1))
1671            .insert(DropCkSparse(dropck2));
1672        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1673        assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1674        drop(world);
1675        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1676        assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1677    }
1678
1679    #[test]
1680    fn clear_entities() {
1681        let mut world = World::default();
1682
1683        world.insert_resource(ResA(0));
1684        world.spawn(A(1));
1685        world.spawn(SparseStored(1));
1686
1687        let mut q1 = world.query::<&A>();
1688        let mut q2 = world.query::<&SparseStored>();
1689
1690        assert_eq!(q1.query(&world).count(), 1);
1691        assert_eq!(q2.query(&world).count(), 1);
1692
1693        world.clear_entities();
1694
1695        assert_eq!(
1696            q1.query(&world).count(),
1697            0,
1698            "world should not contain table components"
1699        );
1700        assert_eq!(
1701            q2.query(&world).count(),
1702            0,
1703            "world should not contain sparse set components"
1704        );
1705        assert_eq!(
1706            world.resource::<ResA>().0,
1707            0,
1708            "world should still contain resources"
1709        );
1710    }
1711
1712    #[test]
1713    fn test_is_archetypal_size_hints() {
1714        let mut world = World::default();
1715        macro_rules! query_min_size {
1716            ($query:ty, $filter:ty) => {
1717                world
1718                    .query_filtered::<$query, $filter>()
1719                    .iter(&world)
1720                    .size_hint()
1721                    .0
1722            };
1723        }
1724
1725        world.spawn((A(1), B(1), C));
1726        world.spawn((A(1), C));
1727        world.spawn((A(1), B(1)));
1728        world.spawn((B(1), C));
1729        world.spawn(A(1));
1730        world.spawn(C);
1731        assert_eq!(2, query_min_size![(), (With<A>, Without<B>)]);
1732        assert_eq!(3, query_min_size![&B, Or<(With<A>, With<C>)>]);
1733        assert_eq!(1, query_min_size![&B, (With<A>, With<C>)]);
1734        assert_eq!(1, query_min_size![(&A, &B), With<C>]);
1735        assert_eq!(4, query_min_size![&A, ()], "Simple Archetypal");
1736        assert_eq!(4, query_min_size![Ref<A>, ()]);
1737        // All the following should set minimum size to 0, as it's impossible to predict
1738        // how many entities the filters will trim.
1739        assert_eq!(0, query_min_size![(), Added<A>], "Simple Added");
1740        assert_eq!(0, query_min_size![(), Changed<A>], "Simple Changed");
1741        assert_eq!(0, query_min_size![(&A, &B), Changed<A>]);
1742        assert_eq!(0, query_min_size![&A, (Changed<A>, With<B>)]);
1743        assert_eq!(0, query_min_size![(&A, &B), Or<(Changed<A>, Changed<B>)>]);
1744    }
1745
1746    #[test]
1747    fn insert_batch() {
1748        let mut world = World::default();
1749        let e0 = world.spawn(A(0)).id();
1750        let e1 = world.spawn(B(0)).id();
1751
1752        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1753
1754        world.insert_batch(values);
1755
1756        assert_eq!(
1757            world.get::<A>(e0),
1758            Some(&A(1)),
1759            "first entity's A component should have been replaced"
1760        );
1761        assert_eq!(
1762            world.get::<B>(e0),
1763            Some(&B(0)),
1764            "first entity should have received B component"
1765        );
1766        assert_eq!(
1767            world.get::<A>(e1),
1768            Some(&A(0)),
1769            "second entity should have received A component"
1770        );
1771        assert_eq!(
1772            world.get::<B>(e1),
1773            Some(&B(1)),
1774            "second entity's B component should have been replaced"
1775        );
1776    }
1777
1778    #[test]
1779    fn insert_batch_same_archetype() {
1780        let mut world = World::default();
1781        let e0 = world.spawn((A(0), B(0))).id();
1782        let e1 = world.spawn((A(0), B(0))).id();
1783        let e2 = world.spawn(B(0)).id();
1784
1785        let values = vec![(e0, (B(1), C)), (e1, (B(2), C)), (e2, (B(3), C))];
1786
1787        world.insert_batch(values);
1788        let mut query = world.query::<(Option<&A>, &B, &C)>();
1789        let component_values = query.get_many(&world, [e0, e1, e2]).unwrap();
1790
1791        assert_eq!(
1792            component_values,
1793            [(Some(&A(0)), &B(1), &C), (Some(&A(0)), &B(2), &C), (None, &B(3), &C)],
1794            "all entities should have had their B component replaced, received C component, and had their A component (or lack thereof) unchanged"
1795        );
1796    }
1797
1798    #[test]
1799    fn insert_batch_if_new() {
1800        let mut world = World::default();
1801        let e0 = world.spawn(A(0)).id();
1802        let e1 = world.spawn(B(0)).id();
1803
1804        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1805
1806        world.insert_batch_if_new(values);
1807
1808        assert_eq!(
1809            world.get::<A>(e0),
1810            Some(&A(0)),
1811            "first entity's A component should not have been replaced"
1812        );
1813        assert_eq!(
1814            world.get::<B>(e0),
1815            Some(&B(0)),
1816            "first entity should have received B component"
1817        );
1818        assert_eq!(
1819            world.get::<A>(e1),
1820            Some(&A(0)),
1821            "second entity should have received A component"
1822        );
1823        assert_eq!(
1824            world.get::<B>(e1),
1825            Some(&B(0)),
1826            "second entity's B component should not have been replaced"
1827        );
1828    }
1829
1830    #[test]
1831    fn try_insert_batch() {
1832        let mut world = World::default();
1833        let e0 = world.spawn(A(0)).id();
1834        let e1 = Entity::from_raw_u32(10_000).unwrap();
1835
1836        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1837
1838        let error = world.try_insert_batch(values).unwrap_err();
1839
1840        assert_eq!(e1, error.entities[0]);
1841
1842        assert_eq!(
1843            world.get::<A>(e0),
1844            Some(&A(1)),
1845            "first entity's A component should have been replaced"
1846        );
1847        assert_eq!(
1848            world.get::<B>(e0),
1849            Some(&B(0)),
1850            "first entity should have received B component"
1851        );
1852    }
1853
1854    #[test]
1855    fn try_insert_batch_if_new() {
1856        let mut world = World::default();
1857        let e0 = world.spawn(A(0)).id();
1858        let e1 = Entity::from_raw_u32(10_000).unwrap();
1859
1860        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1861
1862        let error = world.try_insert_batch_if_new(values).unwrap_err();
1863
1864        assert_eq!(e1, error.entities[0]);
1865
1866        assert_eq!(
1867            world.get::<A>(e0),
1868            Some(&A(0)),
1869            "first entity's A component should not have been replaced"
1870        );
1871        assert_eq!(
1872            world.get::<B>(e0),
1873            Some(&B(0)),
1874            "first entity should have received B component"
1875        );
1876    }
1877
1878    #[derive(Default)]
1879    struct CaptureMapper(Vec<Entity>);
1880    impl EntityMapper for CaptureMapper {
1881        fn get_mapped(&mut self, source: Entity) -> Entity {
1882            self.0.push(source);
1883            source
1884        }
1885
1886        fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
1887    }
1888
1889    #[test]
1890    fn map_struct_entities() {
1891        #[derive(Component)]
1892        #[expect(
1893            unused,
1894            reason = "extra fields are used to ensure the derive works properly"
1895        )]
1896        struct Foo(usize, #[entities] Entity);
1897
1898        #[derive(Component)]
1899        #[expect(
1900            unused,
1901            reason = "extra fields are used to ensure the derive works properly"
1902        )]
1903        struct Bar {
1904            #[entities]
1905            a: Entity,
1906            b: usize,
1907            #[entities]
1908            c: Vec<Entity>,
1909        }
1910
1911        let mut world = World::new();
1912        let e1 = world.spawn_empty().id();
1913        let e2 = world.spawn_empty().id();
1914        let e3 = world.spawn_empty().id();
1915
1916        let mut foo = Foo(1, e1);
1917        let mut mapper = CaptureMapper::default();
1918        Component::map_entities(&mut foo, &mut mapper);
1919        assert_eq!(&mapper.0, &[e1]);
1920
1921        let mut bar = Bar {
1922            a: e1,
1923            b: 1,
1924            c: vec![e2, e3],
1925        };
1926        let mut mapper = CaptureMapper::default();
1927        Component::map_entities(&mut bar, &mut mapper);
1928        assert_eq!(&mapper.0, &[e1, e2, e3]);
1929    }
1930
1931    #[test]
1932    fn map_enum_entities() {
1933        #[derive(Component)]
1934        #[expect(
1935            unused,
1936            reason = "extra fields are used to ensure the derive works properly"
1937        )]
1938        enum Foo {
1939            Bar(usize, #[entities] Entity),
1940            Baz {
1941                #[entities]
1942                a: Entity,
1943                b: usize,
1944                #[entities]
1945                c: Vec<Entity>,
1946            },
1947        }
1948
1949        let mut world = World::new();
1950        let e1 = world.spawn_empty().id();
1951        let e2 = world.spawn_empty().id();
1952        let e3 = world.spawn_empty().id();
1953
1954        let mut foo = Foo::Bar(1, e1);
1955        let mut mapper = CaptureMapper::default();
1956        Component::map_entities(&mut foo, &mut mapper);
1957        assert_eq!(&mapper.0, &[e1]);
1958
1959        let mut foo = Foo::Baz {
1960            a: e1,
1961            b: 1,
1962            c: vec![e2, e3],
1963        };
1964        let mut mapper = CaptureMapper::default();
1965        Component::map_entities(&mut foo, &mut mapper);
1966        assert_eq!(&mapper.0, &[e1, e2, e3]);
1967    }
1968
1969    #[expect(
1970        dead_code,
1971        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1972    )]
1973    #[derive(Component)]
1974    struct ComponentA(u32);
1975
1976    #[expect(
1977        dead_code,
1978        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1979    )]
1980    #[derive(Component)]
1981    struct ComponentB(u32);
1982
1983    #[derive(Bundle)]
1984    struct Simple(ComponentA);
1985
1986    #[expect(
1987        dead_code,
1988        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1989    )]
1990    #[derive(Bundle)]
1991    struct Tuple(Simple, ComponentB);
1992
1993    #[expect(
1994        dead_code,
1995        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1996    )]
1997    #[derive(Bundle)]
1998    struct Record {
1999        field0: Simple,
2000        field1: ComponentB,
2001    }
2002
2003    #[expect(
2004        dead_code,
2005        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
2006    )]
2007    #[derive(Component)]
2008    struct MyEntities {
2009        #[entities]
2010        entities: Vec<Entity>,
2011        #[entities]
2012        another_one: Entity,
2013        #[entities]
2014        maybe_entity: Option<Entity>,
2015        something_else: String,
2016    }
2017
2018    #[expect(
2019        dead_code,
2020        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
2021    )]
2022    #[derive(Component)]
2023    struct MyEntitiesTuple(#[entities] Vec<Entity>, #[entities] Entity, usize);
2024
2025    #[test]
2026    fn clone_entities() {
2027        use crate::entity::{ComponentCloneCtx, SourceComponent};
2028
2029        #[expect(
2030            dead_code,
2031            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2032        )]
2033        #[derive(Component)]
2034        #[component(clone_behavior = Ignore)]
2035        struct IgnoreClone;
2036
2037        #[expect(
2038            dead_code,
2039            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2040        )]
2041        #[derive(Component)]
2042        #[component(clone_behavior = Default)]
2043        struct DefaultClone;
2044
2045        #[expect(
2046            dead_code,
2047            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2048        )]
2049        #[derive(Component)]
2050        #[component(clone_behavior = Custom(custom_clone))]
2051        struct CustomClone;
2052
2053        #[expect(
2054            dead_code,
2055            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2056        )]
2057        #[derive(Component, Clone)]
2058        #[component(clone_behavior = clone::<Self>())]
2059        struct CloneFunction;
2060
2061        #[expect(
2062            dead_code,
2063            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2064        )]
2065        fn custom_clone(_source: &SourceComponent, _ctx: &mut ComponentCloneCtx) {}
2066    }
2067
2068    #[test]
2069    fn queue_register_component_toctou() {
2070        for _ in 0..1000 {
2071            let w = World::new();
2072
2073            std::thread::scope(|s| {
2074                let c1 = s.spawn(|| w.components_queue().queue_register_component::<A>());
2075                let c2 = s.spawn(|| w.components_queue().queue_register_component::<A>());
2076                assert_eq!(c1.join().unwrap(), c2.join().unwrap());
2077            });
2078        }
2079    }
2080}