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    #[test]
1592    #[should_panic]
1593    fn non_send_resource_drop_from_different_thread() {
1594        let mut world = World::default();
1595        world.insert_non_send_resource(NonSendA::default());
1596
1597        let thread = std::thread::spawn(move || {
1598            // Dropping the non-send resource on a different thread
1599            // Should result in a panic
1600            drop(world);
1601        });
1602
1603        if let Err(err) = thread.join() {
1604            std::panic::resume_unwind(err);
1605        }
1606    }
1607
1608    #[test]
1609    fn non_send_resource_drop_from_same_thread() {
1610        let mut world = World::default();
1611        world.insert_non_send_resource(NonSendA::default());
1612        drop(world);
1613    }
1614
1615    #[test]
1616    fn insert_overwrite_drop() {
1617        let (dropck1, dropped1) = DropCk::new_pair();
1618        let (dropck2, dropped2) = DropCk::new_pair();
1619        let mut world = World::default();
1620        world.spawn(dropck1).insert(dropck2);
1621        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1622        assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1623        drop(world);
1624        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1625        assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1626    }
1627
1628    #[test]
1629    fn insert_overwrite_drop_sparse() {
1630        let (dropck1, dropped1) = DropCk::new_pair();
1631        let (dropck2, dropped2) = DropCk::new_pair();
1632        let mut world = World::default();
1633
1634        world
1635            .spawn(DropCkSparse(dropck1))
1636            .insert(DropCkSparse(dropck2));
1637        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1638        assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1639        drop(world);
1640        assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1641        assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1642    }
1643
1644    #[test]
1645    fn clear_entities() {
1646        let mut world = World::default();
1647
1648        world.insert_resource(ResA(0));
1649        world.spawn(A(1));
1650        world.spawn(SparseStored(1));
1651
1652        let mut q1 = world.query::<&A>();
1653        let mut q2 = world.query::<&SparseStored>();
1654
1655        assert_eq!(q1.query(&world).count(), 1);
1656        assert_eq!(q2.query(&world).count(), 1);
1657
1658        world.clear_entities();
1659
1660        assert_eq!(
1661            q1.query(&world).count(),
1662            0,
1663            "world should not contain table components"
1664        );
1665        assert_eq!(
1666            q2.query(&world).count(),
1667            0,
1668            "world should not contain sparse set components"
1669        );
1670        assert_eq!(
1671            world.resource::<ResA>().0,
1672            0,
1673            "world should still contain resources"
1674        );
1675    }
1676
1677    #[test]
1678    fn test_is_archetypal_size_hints() {
1679        let mut world = World::default();
1680        macro_rules! query_min_size {
1681            ($query:ty, $filter:ty) => {
1682                world
1683                    .query_filtered::<$query, $filter>()
1684                    .iter(&world)
1685                    .size_hint()
1686                    .0
1687            };
1688        }
1689
1690        world.spawn((A(1), B(1), C));
1691        world.spawn((A(1), C));
1692        world.spawn((A(1), B(1)));
1693        world.spawn((B(1), C));
1694        world.spawn(A(1));
1695        world.spawn(C);
1696        assert_eq!(2, query_min_size![(), (With<A>, Without<B>)]);
1697        assert_eq!(3, query_min_size![&B, Or<(With<A>, With<C>)>]);
1698        assert_eq!(1, query_min_size![&B, (With<A>, With<C>)]);
1699        assert_eq!(1, query_min_size![(&A, &B), With<C>]);
1700        assert_eq!(4, query_min_size![&A, ()], "Simple Archetypal");
1701        assert_eq!(4, query_min_size![Ref<A>, ()]);
1702        // All the following should set minimum size to 0, as it's impossible to predict
1703        // how many entities the filters will trim.
1704        assert_eq!(0, query_min_size![(), Added<A>], "Simple Added");
1705        assert_eq!(0, query_min_size![(), Changed<A>], "Simple Changed");
1706        assert_eq!(0, query_min_size![(&A, &B), Changed<A>]);
1707        assert_eq!(0, query_min_size![&A, (Changed<A>, With<B>)]);
1708        assert_eq!(0, query_min_size![(&A, &B), Or<(Changed<A>, Changed<B>)>]);
1709    }
1710
1711    #[test]
1712    fn insert_batch() {
1713        let mut world = World::default();
1714        let e0 = world.spawn(A(0)).id();
1715        let e1 = world.spawn(B(0)).id();
1716
1717        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1718
1719        world.insert_batch(values);
1720
1721        assert_eq!(
1722            world.get::<A>(e0),
1723            Some(&A(1)),
1724            "first entity's A component should have been replaced"
1725        );
1726        assert_eq!(
1727            world.get::<B>(e0),
1728            Some(&B(0)),
1729            "first entity should have received B component"
1730        );
1731        assert_eq!(
1732            world.get::<A>(e1),
1733            Some(&A(0)),
1734            "second entity should have received A component"
1735        );
1736        assert_eq!(
1737            world.get::<B>(e1),
1738            Some(&B(1)),
1739            "second entity's B component should have been replaced"
1740        );
1741    }
1742
1743    #[test]
1744    fn insert_batch_same_archetype() {
1745        let mut world = World::default();
1746        let e0 = world.spawn((A(0), B(0))).id();
1747        let e1 = world.spawn((A(0), B(0))).id();
1748        let e2 = world.spawn(B(0)).id();
1749
1750        let values = vec![(e0, (B(1), C)), (e1, (B(2), C)), (e2, (B(3), C))];
1751
1752        world.insert_batch(values);
1753        let mut query = world.query::<(Option<&A>, &B, &C)>();
1754        let component_values = query.get_many(&world, [e0, e1, e2]).unwrap();
1755
1756        assert_eq!(
1757            component_values,
1758            [(Some(&A(0)), &B(1), &C), (Some(&A(0)), &B(2), &C), (None, &B(3), &C)],
1759            "all entities should have had their B component replaced, received C component, and had their A component (or lack thereof) unchanged"
1760        );
1761    }
1762
1763    #[test]
1764    fn insert_batch_if_new() {
1765        let mut world = World::default();
1766        let e0 = world.spawn(A(0)).id();
1767        let e1 = world.spawn(B(0)).id();
1768
1769        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1770
1771        world.insert_batch_if_new(values);
1772
1773        assert_eq!(
1774            world.get::<A>(e0),
1775            Some(&A(0)),
1776            "first entity's A component should not have been replaced"
1777        );
1778        assert_eq!(
1779            world.get::<B>(e0),
1780            Some(&B(0)),
1781            "first entity should have received B component"
1782        );
1783        assert_eq!(
1784            world.get::<A>(e1),
1785            Some(&A(0)),
1786            "second entity should have received A component"
1787        );
1788        assert_eq!(
1789            world.get::<B>(e1),
1790            Some(&B(0)),
1791            "second entity's B component should not have been replaced"
1792        );
1793    }
1794
1795    #[test]
1796    fn try_insert_batch() {
1797        let mut world = World::default();
1798        let e0 = world.spawn(A(0)).id();
1799        let e1 = Entity::from_raw_u32(10_000).unwrap();
1800
1801        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1802
1803        let error = world.try_insert_batch(values).unwrap_err();
1804
1805        assert_eq!(e1, error.entities[0]);
1806
1807        assert_eq!(
1808            world.get::<A>(e0),
1809            Some(&A(1)),
1810            "first entity's A component should have been replaced"
1811        );
1812        assert_eq!(
1813            world.get::<B>(e0),
1814            Some(&B(0)),
1815            "first entity should have received B component"
1816        );
1817    }
1818
1819    #[test]
1820    fn try_insert_batch_if_new() {
1821        let mut world = World::default();
1822        let e0 = world.spawn(A(0)).id();
1823        let e1 = Entity::from_raw_u32(10_000).unwrap();
1824
1825        let values = vec![(e0, (A(1), B(0))), (e1, (A(0), B(1)))];
1826
1827        let error = world.try_insert_batch_if_new(values).unwrap_err();
1828
1829        assert_eq!(e1, error.entities[0]);
1830
1831        assert_eq!(
1832            world.get::<A>(e0),
1833            Some(&A(0)),
1834            "first entity's A component should not have been replaced"
1835        );
1836        assert_eq!(
1837            world.get::<B>(e0),
1838            Some(&B(0)),
1839            "first entity should have received B component"
1840        );
1841    }
1842
1843    #[derive(Default)]
1844    struct CaptureMapper(Vec<Entity>);
1845    impl EntityMapper for CaptureMapper {
1846        fn get_mapped(&mut self, source: Entity) -> Entity {
1847            self.0.push(source);
1848            source
1849        }
1850
1851        fn set_mapped(&mut self, _source: Entity, _target: Entity) {}
1852    }
1853
1854    #[test]
1855    fn map_struct_entities() {
1856        #[derive(Component)]
1857        #[expect(
1858            unused,
1859            reason = "extra fields are used to ensure the derive works properly"
1860        )]
1861        struct Foo(usize, #[entities] Entity);
1862
1863        #[derive(Component)]
1864        #[expect(
1865            unused,
1866            reason = "extra fields are used to ensure the derive works properly"
1867        )]
1868        struct Bar {
1869            #[entities]
1870            a: Entity,
1871            b: usize,
1872            #[entities]
1873            c: Vec<Entity>,
1874        }
1875
1876        let mut world = World::new();
1877        let e1 = world.spawn_empty().id();
1878        let e2 = world.spawn_empty().id();
1879        let e3 = world.spawn_empty().id();
1880
1881        let mut foo = Foo(1, e1);
1882        let mut mapper = CaptureMapper::default();
1883        Component::map_entities(&mut foo, &mut mapper);
1884        assert_eq!(&mapper.0, &[e1]);
1885
1886        let mut bar = Bar {
1887            a: e1,
1888            b: 1,
1889            c: vec![e2, e3],
1890        };
1891        let mut mapper = CaptureMapper::default();
1892        Component::map_entities(&mut bar, &mut mapper);
1893        assert_eq!(&mapper.0, &[e1, e2, e3]);
1894    }
1895
1896    #[test]
1897    fn map_enum_entities() {
1898        #[derive(Component)]
1899        #[expect(
1900            unused,
1901            reason = "extra fields are used to ensure the derive works properly"
1902        )]
1903        enum Foo {
1904            Bar(usize, #[entities] Entity),
1905            Baz {
1906                #[entities]
1907                a: Entity,
1908                b: usize,
1909                #[entities]
1910                c: Vec<Entity>,
1911            },
1912        }
1913
1914        let mut world = World::new();
1915        let e1 = world.spawn_empty().id();
1916        let e2 = world.spawn_empty().id();
1917        let e3 = world.spawn_empty().id();
1918
1919        let mut foo = Foo::Bar(1, e1);
1920        let mut mapper = CaptureMapper::default();
1921        Component::map_entities(&mut foo, &mut mapper);
1922        assert_eq!(&mapper.0, &[e1]);
1923
1924        let mut foo = Foo::Baz {
1925            a: e1,
1926            b: 1,
1927            c: vec![e2, e3],
1928        };
1929        let mut mapper = CaptureMapper::default();
1930        Component::map_entities(&mut foo, &mut mapper);
1931        assert_eq!(&mapper.0, &[e1, e2, e3]);
1932    }
1933
1934    #[expect(
1935        dead_code,
1936        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1937    )]
1938    #[derive(Component)]
1939    struct ComponentA(u32);
1940
1941    #[expect(
1942        dead_code,
1943        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1944    )]
1945    #[derive(Component)]
1946    struct ComponentB(u32);
1947
1948    #[derive(Bundle)]
1949    struct Simple(ComponentA);
1950
1951    #[expect(
1952        dead_code,
1953        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1954    )]
1955    #[derive(Bundle)]
1956    struct Tuple(Simple, ComponentB);
1957
1958    #[expect(
1959        dead_code,
1960        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1961    )]
1962    #[derive(Bundle)]
1963    struct Record {
1964        field0: Simple,
1965        field1: ComponentB,
1966    }
1967
1968    #[expect(
1969        dead_code,
1970        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1971    )]
1972    #[derive(Component)]
1973    struct MyEntities {
1974        #[entities]
1975        entities: Vec<Entity>,
1976        #[entities]
1977        another_one: Entity,
1978        #[entities]
1979        maybe_entity: Option<Entity>,
1980        something_else: String,
1981    }
1982
1983    #[expect(
1984        dead_code,
1985        reason = "This struct is used as a compilation test to test the derive macros, and as such is intentionally never constructed."
1986    )]
1987    #[derive(Component)]
1988    struct MyEntitiesTuple(#[entities] Vec<Entity>, #[entities] Entity, usize);
1989
1990    #[test]
1991    fn clone_entities() {
1992        use crate::entity::{ComponentCloneCtx, SourceComponent};
1993
1994        #[expect(
1995            dead_code,
1996            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
1997        )]
1998        #[derive(Component)]
1999        #[component(clone_behavior = Ignore)]
2000        struct IgnoreClone;
2001
2002        #[expect(
2003            dead_code,
2004            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2005        )]
2006        #[derive(Component)]
2007        #[component(clone_behavior = Default)]
2008        struct DefaultClone;
2009
2010        #[expect(
2011            dead_code,
2012            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2013        )]
2014        #[derive(Component)]
2015        #[component(clone_behavior = Custom(custom_clone))]
2016        struct CustomClone;
2017
2018        #[expect(
2019            dead_code,
2020            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2021        )]
2022        #[derive(Component, Clone)]
2023        #[component(clone_behavior = clone::<Self>())]
2024        struct CloneFunction;
2025
2026        #[expect(
2027            dead_code,
2028            reason = "This struct is used as a compilation test to test the derive macros, and as such this field is intentionally never used."
2029        )]
2030        fn custom_clone(_source: &SourceComponent, _ctx: &mut ComponentCloneCtx) {}
2031    }
2032
2033    #[test]
2034    fn queue_register_component_toctou() {
2035        for _ in 0..1000 {
2036            let w = World::new();
2037
2038            std::thread::scope(|s| {
2039                let c1 = s.spawn(|| w.components_queue().queue_register_component::<A>());
2040                let c2 = s.spawn(|| w.components_queue().queue_register_component::<A>());
2041                assert_eq!(c1.join().unwrap(), c2.join().unwrap());
2042            });
2043        }
2044    }
2045}