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
26extern 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
64pub 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#[doc(hidden)]
130pub mod __macro_exports {
131 pub use crate::query::DebugCheckedUnwrap;
135 pub use alloc::vec::Vec;
136}
137
138#[cfg(feature = "hotpatching")]
142#[derive(Message, Default)]
143pub struct HotPatched;
144
145#[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 world.get_mut::<TableStored>(e).unwrap().0 = "xyz";
237 assert_eq!(world.get::<TableStored>(e).unwrap().0, "xyz");
238
239 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 world.get_mut::<TableStored>(e1).unwrap().0 = "xyz";
280 assert_eq!(world.get::<TableStored>(e1).unwrap().0, "xyz");
281
282 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 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 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 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 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 }
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 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 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 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 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 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 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 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 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 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 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 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 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 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}