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