Skip to main content

bevy_ecs/
lib.rs

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