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