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