1#![allow(unsafe_op_in_unsafe_fn)]
3#![doc = include_str!("../README.md")]
4#![cfg_attr(docsrs, feature(doc_auto_cfg))]
5#![allow(unsafe_code)]
6#![doc(
7 html_logo_url = "https://bevyengine.org/assets/icon.png",
8 html_favicon_url = "https://bevyengine.org/assets/icon.png"
9)]
10
11#[cfg(target_pointer_width = "16")]
12compile_error!("bevy_ecs cannot safely compile for a 16-bit platform.");
13
14pub mod archetype;
15pub mod batching;
16pub mod bundle;
17pub mod change_detection;
18pub mod component;
19pub mod entity;
20pub mod event;
21pub mod identifier;
22pub mod intern;
23pub mod label;
24pub mod observer;
25pub mod query;
26#[cfg(feature = "bevy_reflect")]
27pub mod reflect;
28pub mod removal_detection;
29pub mod schedule;
30pub mod storage;
31pub mod system;
32pub mod world;
33
34pub use bevy_ptr as ptr;
35
36pub mod prelude {
38 #[doc(hidden)]
39 #[cfg(feature = "bevy_reflect")]
40 pub use crate::reflect::{
41 AppTypeRegistry, ReflectComponent, ReflectFromWorld, ReflectResource,
42 };
43 #[doc(hidden)]
44 pub use crate::{
45 bundle::Bundle,
46 change_detection::{DetectChanges, DetectChangesMut, Mut, Ref},
47 component::Component,
48 entity::{Entity, EntityMapper},
49 event::{Event, EventReader, EventWriter, Events, ShouldUpdateEvents},
50 observer::{Observer, Trigger},
51 query::{Added, AnyOf, Changed, Has, Or, QueryBuilder, QueryState, With, Without},
52 removal_detection::RemovedComponents,
53 schedule::{
54 apply_deferred, common_conditions::*, Condition, IntoSystemConfigs, IntoSystemSet,
55 IntoSystemSetConfigs, Schedule, Schedules, SystemSet,
56 },
57 system::{
58 Commands, Deferred, In, IntoSystem, Local, NonSend, NonSendMut, ParallelCommands,
59 ParamSet, Query, ReadOnlySystem, Res, ResMut, Resource, System, SystemBuilder,
60 SystemParamFunction,
61 },
62 world::{
63 EntityMut, EntityRef, EntityWorldMut, FromWorld, OnAdd, OnInsert, OnRemove, World,
64 },
65 };
66}
67
68#[cfg(test)]
69mod tests {
70 use crate as bevy_ecs;
71 use crate::prelude::Or;
72 use crate::{
73 bundle::Bundle,
74 change_detection::Ref,
75 component::{Component, ComponentId},
76 entity::Entity,
77 query::{Added, Changed, FilteredAccess, QueryFilter, With, Without},
78 system::Resource,
79 world::{EntityRef, Mut, World},
80 };
81 use bevy_tasks::{ComputeTaskPool, TaskPool};
82 use std::num::NonZeroU32;
83 use std::{
84 any::TypeId,
85 marker::PhantomData,
86 sync::{
87 atomic::{AtomicUsize, Ordering},
88 Arc, Mutex,
89 },
90 };
91
92 #[derive(Component, Resource, Debug, PartialEq, Eq, Clone, Copy)]
93 struct A(usize);
94 #[derive(Component, Debug, PartialEq, Eq, Clone, Copy)]
95 struct B(usize);
96 #[derive(Component, Debug, PartialEq, Eq, Clone, Copy)]
97 struct C;
98
99 #[allow(dead_code)]
100 #[derive(Default)]
101 struct NonSendA(usize, PhantomData<*mut ()>);
102
103 #[derive(Component, Clone, Debug)]
104 struct DropCk(Arc<AtomicUsize>);
105 impl DropCk {
106 fn new_pair() -> (Self, Arc<AtomicUsize>) {
107 let atomic = Arc::new(AtomicUsize::new(0));
108 (DropCk(atomic.clone()), atomic)
109 }
110 }
111
112 impl Drop for DropCk {
113 fn drop(&mut self) {
114 self.0.as_ref().fetch_add(1, Ordering::Relaxed);
115 }
116 }
117
118 #[allow(dead_code)]
120 #[derive(Component, Clone, Debug)]
121 #[component(storage = "SparseSet")]
122 struct DropCkSparse(DropCk);
123
124 #[derive(Component, Copy, Clone, PartialEq, Eq, Debug)]
125 #[component(storage = "Table")]
126 struct TableStored(&'static str);
127 #[derive(Component, Copy, Clone, PartialEq, Eq, Debug)]
128 #[component(storage = "SparseSet")]
129 struct SparseStored(u32);
130
131 #[test]
132 fn random_access() {
133 let mut world = World::new();
134
135 let e = world.spawn((TableStored("abc"), SparseStored(123))).id();
136 let f = world
137 .spawn((TableStored("def"), SparseStored(456), A(1)))
138 .id();
139 assert_eq!(world.get::<TableStored>(e).unwrap().0, "abc");
140 assert_eq!(world.get::<SparseStored>(e).unwrap().0, 123);
141 assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
142 assert_eq!(world.get::<SparseStored>(f).unwrap().0, 456);
143
144 world.get_mut::<TableStored>(e).unwrap().0 = "xyz";
146 assert_eq!(world.get::<TableStored>(e).unwrap().0, "xyz");
147
148 world.get_mut::<SparseStored>(f).unwrap().0 = 42;
150 assert_eq!(world.get::<SparseStored>(f).unwrap().0, 42);
151 }
152
153 #[test]
154 fn bundle_derive() {
155 let mut world = World::new();
156
157 #[derive(Bundle, PartialEq, Debug)]
158 struct FooBundle {
159 x: TableStored,
160 y: SparseStored,
161 }
162 let mut ids = Vec::new();
163 <FooBundle as Bundle>::component_ids(
164 &mut world.components,
165 &mut world.storages,
166 &mut |id| {
167 ids.push(id);
168 },
169 );
170
171 assert_eq!(
172 ids,
173 &[
174 world.init_component::<TableStored>(),
175 world.init_component::<SparseStored>(),
176 ]
177 );
178
179 let e1 = world
180 .spawn(FooBundle {
181 x: TableStored("abc"),
182 y: SparseStored(123),
183 })
184 .id();
185 let e2 = world
186 .spawn((TableStored("def"), SparseStored(456), A(1)))
187 .id();
188 assert_eq!(world.get::<TableStored>(e1).unwrap().0, "abc");
189 assert_eq!(world.get::<SparseStored>(e1).unwrap().0, 123);
190 assert_eq!(world.get::<TableStored>(e2).unwrap().0, "def");
191 assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 456);
192
193 world.get_mut::<TableStored>(e1).unwrap().0 = "xyz";
195 assert_eq!(world.get::<TableStored>(e1).unwrap().0, "xyz");
196
197 world.get_mut::<SparseStored>(e2).unwrap().0 = 42;
199 assert_eq!(world.get::<SparseStored>(e2).unwrap().0, 42);
200
201 assert_eq!(
202 world.entity_mut(e1).take::<FooBundle>().unwrap(),
203 FooBundle {
204 x: TableStored("xyz"),
205 y: SparseStored(123),
206 }
207 );
208
209 #[derive(Bundle, PartialEq, Debug)]
210 struct NestedBundle {
211 a: A,
212 foo: FooBundle,
213 b: B,
214 }
215
216 let mut ids = Vec::new();
217 <NestedBundle as Bundle>::component_ids(
218 &mut world.components,
219 &mut world.storages,
220 &mut |id| {
221 ids.push(id);
222 },
223 );
224
225 assert_eq!(
226 ids,
227 &[
228 world.init_component::<A>(),
229 world.init_component::<TableStored>(),
230 world.init_component::<SparseStored>(),
231 world.init_component::<B>(),
232 ]
233 );
234
235 let e3 = world
236 .spawn(NestedBundle {
237 a: A(1),
238 foo: FooBundle {
239 x: TableStored("ghi"),
240 y: SparseStored(789),
241 },
242 b: B(2),
243 })
244 .id();
245
246 assert_eq!(world.get::<TableStored>(e3).unwrap().0, "ghi");
247 assert_eq!(world.get::<SparseStored>(e3).unwrap().0, 789);
248 assert_eq!(world.get::<A>(e3).unwrap().0, 1);
249 assert_eq!(world.get::<B>(e3).unwrap().0, 2);
250 assert_eq!(
251 world.entity_mut(e3).take::<NestedBundle>().unwrap(),
252 NestedBundle {
253 a: A(1),
254 foo: FooBundle {
255 x: TableStored("ghi"),
256 y: SparseStored(789),
257 },
258 b: B(2),
259 }
260 );
261
262 #[derive(Default, Component, PartialEq, Debug)]
263 struct Ignored;
264
265 #[derive(Bundle, PartialEq, Debug)]
266 struct BundleWithIgnored {
267 c: C,
268 #[bundle(ignore)]
269 ignored: Ignored,
270 }
271
272 let mut ids = Vec::new();
273 <BundleWithIgnored as Bundle>::component_ids(
274 &mut world.components,
275 &mut world.storages,
276 &mut |id| {
277 ids.push(id);
278 },
279 );
280
281 assert_eq!(ids, &[world.init_component::<C>(),]);
282
283 let e4 = world
284 .spawn(BundleWithIgnored {
285 c: C,
286 ignored: Ignored,
287 })
288 .id();
289
290 assert_eq!(world.get::<C>(e4).unwrap(), &C);
291 assert_eq!(world.get::<Ignored>(e4), None);
292
293 assert_eq!(
294 world.entity_mut(e4).take::<BundleWithIgnored>().unwrap(),
295 BundleWithIgnored {
296 c: C,
297 ignored: Ignored,
298 }
299 );
300 }
301
302 #[test]
303 fn despawn_table_storage() {
304 let mut world = World::new();
305 let e = world.spawn((TableStored("abc"), A(123))).id();
306 let f = world.spawn((TableStored("def"), A(456))).id();
307 assert_eq!(world.entities.len(), 2);
308 assert!(world.despawn(e));
309 assert_eq!(world.entities.len(), 1);
310 assert!(world.get::<TableStored>(e).is_none());
311 assert!(world.get::<A>(e).is_none());
312 assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
313 assert_eq!(world.get::<A>(f).unwrap().0, 456);
314 }
315
316 #[test]
317 fn despawn_mixed_storage() {
318 let mut world = World::new();
319
320 let e = world.spawn((TableStored("abc"), SparseStored(123))).id();
321 let f = world.spawn((TableStored("def"), SparseStored(456))).id();
322 assert_eq!(world.entities.len(), 2);
323 assert!(world.despawn(e));
324 assert_eq!(world.entities.len(), 1);
325 assert!(world.get::<TableStored>(e).is_none());
326 assert!(world.get::<SparseStored>(e).is_none());
327 assert_eq!(world.get::<TableStored>(f).unwrap().0, "def");
328 assert_eq!(world.get::<SparseStored>(f).unwrap().0, 456);
329 }
330
331 #[test]
332 fn query_all() {
333 let mut world = World::new();
334 let e = world.spawn((TableStored("abc"), A(123))).id();
335 let f = world.spawn((TableStored("def"), A(456))).id();
336
337 let ents = world
338 .query::<(Entity, &A, &TableStored)>()
339 .iter(&world)
340 .map(|(e, &i, &s)| (e, i, s))
341 .collect::<Vec<_>>();
342 assert_eq!(
343 ents,
344 &[
345 (e, A(123), TableStored("abc")),
346 (f, A(456), TableStored("def"))
347 ]
348 );
349 }
350
351 #[test]
352 fn query_all_for_each() {
353 let mut world = World::new();
354 let e = world.spawn((TableStored("abc"), A(123))).id();
355 let f = world.spawn((TableStored("def"), A(456))).id();
356
357 let mut results = Vec::new();
358 world
359 .query::<(Entity, &A, &TableStored)>()
360 .iter(&world)
361 .for_each(|(e, &i, &s)| results.push((e, i, s)));
362 assert_eq!(
363 results,
364 &[
365 (e, A(123), TableStored("abc")),
366 (f, A(456), TableStored("def"))
367 ]
368 );
369 }
370
371 #[test]
372 fn query_single_component() {
373 let mut world = World::new();
374 let e = world.spawn((TableStored("abc"), A(123))).id();
375 let f = world.spawn((TableStored("def"), A(456), B(1))).id();
376 let ents = world
377 .query::<(Entity, &A)>()
378 .iter(&world)
379 .map(|(e, &i)| (e, i))
380 .collect::<Vec<_>>();
381 assert_eq!(ents, &[(e, A(123)), (f, A(456))]);
382 }
383
384 #[test]
385 fn stateful_query_handles_new_archetype() {
386 let mut world = World::new();
387 let e = world.spawn((TableStored("abc"), A(123))).id();
388 let mut query = world.query::<(Entity, &A)>();
389
390 let ents = query.iter(&world).map(|(e, &i)| (e, i)).collect::<Vec<_>>();
391 assert_eq!(ents, &[(e, A(123))]);
392
393 let f = world.spawn((TableStored("def"), A(456), B(1))).id();
394 let ents = query.iter(&world).map(|(e, &i)| (e, i)).collect::<Vec<_>>();
395 assert_eq!(ents, &[(e, A(123)), (f, A(456))]);
396 }
397
398 #[test]
399 fn query_single_component_for_each() {
400 let mut world = World::new();
401 let e = world.spawn((TableStored("abc"), A(123))).id();
402 let f = world.spawn((TableStored("def"), A(456), B(1))).id();
403 let mut results = Vec::new();
404 world
405 .query::<(Entity, &A)>()
406 .iter(&world)
407 .for_each(|(e, &i)| results.push((e, i)));
408 assert_eq!(results, &[(e, A(123)), (f, A(456))]);
409 }
410
411 #[test]
412 fn par_for_each_dense() {
413 ComputeTaskPool::get_or_init(TaskPool::default);
414 let mut world = World::new();
415 let e1 = world.spawn(A(1)).id();
416 let e2 = world.spawn(A(2)).id();
417 let e3 = world.spawn(A(3)).id();
418 let e4 = world.spawn((A(4), B(1))).id();
419 let e5 = world.spawn((A(5), B(1))).id();
420 let results = Arc::new(Mutex::new(Vec::new()));
421 world
422 .query::<(Entity, &A)>()
423 .par_iter(&world)
424 .for_each(|(e, &A(i))| {
425 results.lock().unwrap().push((e, i));
426 });
427 results.lock().unwrap().sort();
428 assert_eq!(
429 &*results.lock().unwrap(),
430 &[(e1, 1), (e2, 2), (e3, 3), (e4, 4), (e5, 5)]
431 );
432 }
433
434 #[test]
435 fn par_for_each_sparse() {
436 ComputeTaskPool::get_or_init(TaskPool::default);
437 let mut world = World::new();
438 let e1 = world.spawn(SparseStored(1)).id();
439 let e2 = world.spawn(SparseStored(2)).id();
440 let e3 = world.spawn(SparseStored(3)).id();
441 let e4 = world.spawn((SparseStored(4), A(1))).id();
442 let e5 = world.spawn((SparseStored(5), A(1))).id();
443 let results = Arc::new(Mutex::new(Vec::new()));
444 world
445 .query::<(Entity, &SparseStored)>()
446 .par_iter(&world)
447 .for_each(|(e, &SparseStored(i))| results.lock().unwrap().push((e, i)));
448 results.lock().unwrap().sort();
449 assert_eq!(
450 &*results.lock().unwrap(),
451 &[(e1, 1), (e2, 2), (e3, 3), (e4, 4), (e5, 5)]
452 );
453 }
454
455 #[test]
456 fn query_missing_component() {
457 let mut world = World::new();
458 world.spawn((TableStored("abc"), A(123)));
459 world.spawn((TableStored("def"), A(456)));
460 assert!(world.query::<(&B, &A)>().iter(&world).next().is_none());
461 }
462
463 #[test]
464 fn query_sparse_component() {
465 let mut world = World::new();
466 world.spawn((TableStored("abc"), A(123)));
467 let f = world.spawn((TableStored("def"), A(456), B(1))).id();
468 let ents = world
469 .query::<(Entity, &B)>()
470 .iter(&world)
471 .map(|(e, &b)| (e, b))
472 .collect::<Vec<_>>();
473 assert_eq!(ents, &[(f, B(1))]);
474 }
475
476 #[test]
477 fn query_filter_with() {
478 let mut world = World::new();
479 world.spawn((A(123), B(1)));
480 world.spawn(A(456));
481 let result = world
482 .query_filtered::<&A, With<B>>()
483 .iter(&world)
484 .cloned()
485 .collect::<Vec<_>>();
486 assert_eq!(result, vec![A(123)]);
487 }
488
489 #[test]
490 fn query_filter_with_for_each() {
491 let mut world = World::new();
492 world.spawn((A(123), B(1)));
493 world.spawn(A(456));
494
495 let mut results = Vec::new();
496 world
497 .query_filtered::<&A, With<B>>()
498 .iter(&world)
499 .for_each(|i| results.push(*i));
500 assert_eq!(results, vec![A(123)]);
501 }
502
503 #[test]
504 fn query_filter_with_sparse() {
505 let mut world = World::new();
506
507 world.spawn((A(123), SparseStored(321)));
508 world.spawn(A(456));
509 let result = world
510 .query_filtered::<&A, With<SparseStored>>()
511 .iter(&world)
512 .cloned()
513 .collect::<Vec<_>>();
514 assert_eq!(result, vec![A(123)]);
515 }
516
517 #[test]
518 fn query_filter_with_sparse_for_each() {
519 let mut world = World::new();
520
521 world.spawn((A(123), SparseStored(321)));
522 world.spawn(A(456));
523 let mut results = Vec::new();
524 world
525 .query_filtered::<&A, With<SparseStored>>()
526 .iter(&world)
527 .for_each(|i| results.push(*i));
528 assert_eq!(results, vec![A(123)]);
529 }
530
531 #[test]
532 fn query_filter_without() {
533 let mut world = World::new();
534 world.spawn((A(123), B(321)));
535 world.spawn(A(456));
536 let result = world
537 .query_filtered::<&A, Without<B>>()
538 .iter(&world)
539 .cloned()
540 .collect::<Vec<_>>();
541 assert_eq!(result, vec![A(456)]);
542 }
543
544 #[test]
545 fn query_optional_component_table() {
546 let mut world = World::new();
547 let e = world.spawn((TableStored("abc"), A(123))).id();
548 let f = world.spawn((TableStored("def"), A(456), B(1))).id();
549 world.spawn(TableStored("abc"));
551 let ents = world
552 .query::<(Entity, Option<&B>, &A)>()
553 .iter(&world)
554 .map(|(e, b, &i)| (e, b.copied(), i))
555 .collect::<Vec<_>>();
556 assert_eq!(ents, &[(e, None, A(123)), (f, Some(B(1)), A(456))]);
557 }
558
559 #[test]
560 fn query_optional_component_sparse() {
561 let mut world = World::new();
562
563 let e = world.spawn((TableStored("abc"), A(123))).id();
564 let f = world
565 .spawn((TableStored("def"), A(456), SparseStored(1)))
566 .id();
567 let ents = world
570 .query::<(Entity, Option<&SparseStored>, &A)>()
571 .iter(&world)
572 .map(|(e, b, &i)| (e, b.copied(), i))
573 .collect::<Vec<_>>();
574 assert_eq!(
575 ents,
576 &[(e, None, A(123)), (f, Some(SparseStored(1)), A(456))]
577 );
578 }
579
580 #[test]
581 fn query_optional_component_sparse_no_match() {
582 let mut world = World::new();
583
584 let e = world.spawn((TableStored("abc"), A(123))).id();
585 let f = world.spawn((TableStored("def"), A(456))).id();
586 world.spawn(TableStored("abc"));
588 let ents = world
589 .query::<(Entity, Option<&SparseStored>, &A)>()
590 .iter(&world)
591 .map(|(e, b, &i)| (e, b.copied(), i))
592 .collect::<Vec<_>>();
593 assert_eq!(ents, &[(e, None, A(123)), (f, None, A(456))]);
594 }
595
596 #[test]
597 fn add_remove_components() {
598 let mut world = World::new();
599 let e1 = world.spawn((A(1), B(3), TableStored("abc"))).id();
600 let e2 = world.spawn((A(2), B(4), TableStored("xyz"))).id();
601
602 assert_eq!(
603 world
604 .query::<(Entity, &A, &B)>()
605 .iter(&world)
606 .map(|(e, &i, &b)| (e, i, b))
607 .collect::<Vec<_>>(),
608 &[(e1, A(1), B(3)), (e2, A(2), B(4))]
609 );
610
611 assert_eq!(world.entity_mut(e1).take::<A>(), Some(A(1)));
612 assert_eq!(
613 world
614 .query::<(Entity, &A, &B)>()
615 .iter(&world)
616 .map(|(e, &i, &b)| (e, i, b))
617 .collect::<Vec<_>>(),
618 &[(e2, A(2), B(4))]
619 );
620 assert_eq!(
621 world
622 .query::<(Entity, &B, &TableStored)>()
623 .iter(&world)
624 .map(|(e, &B(b), &TableStored(s))| (e, b, s))
625 .collect::<Vec<_>>(),
626 &[(e2, 4, "xyz"), (e1, 3, "abc")]
627 );
628 world.entity_mut(e1).insert(A(43));
629 assert_eq!(
630 world
631 .query::<(Entity, &A, &B)>()
632 .iter(&world)
633 .map(|(e, &i, &b)| (e, i, b))
634 .collect::<Vec<_>>(),
635 &[(e2, A(2), B(4)), (e1, A(43), B(3))]
636 );
637 world.entity_mut(e1).insert(C);
638 assert_eq!(
639 world
640 .query::<(Entity, &C)>()
641 .iter(&world)
642 .map(|(e, &f)| (e, f))
643 .collect::<Vec<_>>(),
644 &[(e1, C)]
645 );
646 }
647
648 #[test]
649 fn table_add_remove_many() {
650 let mut world = World::default();
651 #[cfg(miri)]
652 let (mut entities, to) = {
653 let to = 10;
654 (Vec::with_capacity(to), to)
655 };
656 #[cfg(not(miri))]
657 let (mut entities, to) = {
658 let to = 10_000;
659 (Vec::with_capacity(to), to)
660 };
661
662 for _ in 0..to {
663 entities.push(world.spawn(B(0)).id());
664 }
665
666 for (i, entity) in entities.iter().cloned().enumerate() {
667 world.entity_mut(entity).insert(A(i));
668 }
669
670 for (i, entity) in entities.iter().cloned().enumerate() {
671 assert_eq!(world.entity_mut(entity).take::<A>(), Some(A(i)));
672 }
673 }
674
675 #[test]
676 fn sparse_set_add_remove_many() {
677 let mut world = World::default();
678
679 let mut entities = Vec::with_capacity(1000);
680 for _ in 0..4 {
681 entities.push(world.spawn(A(2)).id());
682 }
683
684 for (i, entity) in entities.iter().cloned().enumerate() {
685 world.entity_mut(entity).insert(SparseStored(i as u32));
686 }
687
688 for (i, entity) in entities.iter().cloned().enumerate() {
689 assert_eq!(
690 world.entity_mut(entity).take::<SparseStored>(),
691 Some(SparseStored(i as u32))
692 );
693 }
694 }
695
696 #[test]
697 fn remove_missing() {
698 let mut world = World::new();
699 let e = world.spawn((TableStored("abc"), A(123))).id();
700 assert!(world.entity_mut(e).take::<B>().is_none());
701 }
702
703 #[test]
704 fn spawn_batch() {
705 let mut world = World::new();
706 world.spawn_batch((0..100).map(|x| (A(x), TableStored("abc"))));
707 let values = world
708 .query::<&A>()
709 .iter(&world)
710 .map(|v| v.0)
711 .collect::<Vec<_>>();
712 let expected = (0..100).collect::<Vec<_>>();
713 assert_eq!(values, expected);
714 }
715
716 #[test]
717 fn query_get() {
718 let mut world = World::new();
719 let a = world.spawn((TableStored("abc"), A(123))).id();
720 let b = world.spawn((TableStored("def"), A(456))).id();
721 let c = world.spawn((TableStored("ghi"), A(789), B(1))).id();
722
723 let mut i32_query = world.query::<&A>();
724 assert_eq!(i32_query.get(&world, a).unwrap().0, 123);
725 assert_eq!(i32_query.get(&world, b).unwrap().0, 456);
726
727 let mut i32_bool_query = world.query::<(&A, &B)>();
728 assert!(i32_bool_query.get(&world, a).is_err());
729 assert_eq!(i32_bool_query.get(&world, c).unwrap(), (&A(789), &B(1)));
730 assert!(world.despawn(a));
731 assert!(i32_query.get(&world, a).is_err());
732 }
733
734 #[test]
735 fn query_get_works_across_sparse_removal() {
736 let mut world = World::new();
738 let a = world.spawn((TableStored("abc"), SparseStored(123))).id();
739 let b = world.spawn((TableStored("def"), SparseStored(456))).id();
740 let c = world
741 .spawn((TableStored("ghi"), SparseStored(789), B(1)))
742 .id();
743
744 let mut query = world.query::<&TableStored>();
745 assert_eq!(query.get(&world, a).unwrap(), &TableStored("abc"));
746 assert_eq!(query.get(&world, b).unwrap(), &TableStored("def"));
747 assert_eq!(query.get(&world, c).unwrap(), &TableStored("ghi"));
748
749 world.entity_mut(b).remove::<SparseStored>();
750 world.entity_mut(c).remove::<SparseStored>();
751
752 assert_eq!(query.get(&world, a).unwrap(), &TableStored("abc"));
753 assert_eq!(query.get(&world, b).unwrap(), &TableStored("def"));
754 assert_eq!(query.get(&world, c).unwrap(), &TableStored("ghi"));
755 }
756
757 #[test]
758 fn remove_tracking() {
759 let mut world = World::new();
760
761 let a = world.spawn((SparseStored(0), A(123))).id();
762 let b = world.spawn((SparseStored(1), A(123))).id();
763
764 world.entity_mut(a).despawn();
765 assert_eq!(
766 world.removed::<A>().collect::<Vec<_>>(),
767 &[a],
768 "despawning results in 'removed component' state for table components"
769 );
770 assert_eq!(
771 world.removed::<SparseStored>().collect::<Vec<_>>(),
772 &[a],
773 "despawning results in 'removed component' state for sparse set components"
774 );
775
776 world.entity_mut(b).insert(B(1));
777 assert_eq!(
778 world.removed::<A>().collect::<Vec<_>>(),
779 &[a],
780 "archetype moves does not result in 'removed component' state"
781 );
782
783 world.entity_mut(b).remove::<A>();
784 assert_eq!(
785 world.removed::<A>().collect::<Vec<_>>(),
786 &[a, b],
787 "removing a component results in a 'removed component' state"
788 );
789
790 world.clear_trackers();
791 assert_eq!(
792 world.removed::<A>().collect::<Vec<_>>(),
793 &[],
794 "clearing trackers clears removals"
795 );
796 assert_eq!(
797 world.removed::<SparseStored>().collect::<Vec<_>>(),
798 &[],
799 "clearing trackers clears removals"
800 );
801 assert_eq!(
802 world.removed::<B>().collect::<Vec<_>>(),
803 &[],
804 "clearing trackers clears removals"
805 );
806
807 }
827
828 #[test]
829 fn added_tracking() {
830 let mut world = World::new();
831 let a = world.spawn(A(123)).id();
832
833 assert_eq!(world.query::<&A>().iter(&world).count(), 1);
834 assert_eq!(
835 world.query_filtered::<(), Added<A>>().iter(&world).count(),
836 1
837 );
838 assert_eq!(world.query::<&A>().iter(&world).count(), 1);
839 assert_eq!(
840 world.query_filtered::<(), Added<A>>().iter(&world).count(),
841 1
842 );
843 assert!(world.query::<&A>().get(&world, a).is_ok());
844 assert!(world
845 .query_filtered::<(), Added<A>>()
846 .get(&world, a)
847 .is_ok());
848 assert!(world.query::<&A>().get(&world, a).is_ok());
849 assert!(world
850 .query_filtered::<(), Added<A>>()
851 .get(&world, a)
852 .is_ok());
853
854 world.clear_trackers();
855
856 assert_eq!(world.query::<&A>().iter(&world).count(), 1);
857 assert_eq!(
858 world.query_filtered::<(), Added<A>>().iter(&world).count(),
859 0
860 );
861 assert_eq!(world.query::<&A>().iter(&world).count(), 1);
862 assert_eq!(
863 world.query_filtered::<(), Added<A>>().iter(&world).count(),
864 0
865 );
866 assert!(world.query::<&A>().get(&world, a).is_ok());
867 assert!(world
868 .query_filtered::<(), Added<A>>()
869 .get(&world, a)
870 .is_err());
871 assert!(world.query::<&A>().get(&world, a).is_ok());
872 assert!(world
873 .query_filtered::<(), Added<A>>()
874 .get(&world, a)
875 .is_err());
876 }
877
878 #[test]
879 fn added_queries() {
880 let mut world = World::default();
881 let e1 = world.spawn(A(0)).id();
882
883 fn get_added<Com: Component>(world: &mut World) -> Vec<Entity> {
884 world
885 .query_filtered::<Entity, Added<Com>>()
886 .iter(world)
887 .collect::<Vec<Entity>>()
888 }
889
890 assert_eq!(get_added::<A>(&mut world), vec![e1]);
891 world.entity_mut(e1).insert(B(0));
892 assert_eq!(get_added::<A>(&mut world), vec![e1]);
893 assert_eq!(get_added::<B>(&mut world), vec![e1]);
894
895 world.clear_trackers();
896 assert!(get_added::<A>(&mut world).is_empty());
897 let e2 = world.spawn((A(1), B(1))).id();
898 assert_eq!(get_added::<A>(&mut world), vec![e2]);
899 assert_eq!(get_added::<B>(&mut world), vec![e2]);
900
901 let added = world
902 .query_filtered::<Entity, (Added<A>, Added<B>)>()
903 .iter(&world)
904 .collect::<Vec<Entity>>();
905 assert_eq!(added, vec![e2]);
906 }
907
908 #[test]
909 fn changed_trackers() {
910 let mut world = World::default();
911 let e1 = world.spawn((A(0), B(0))).id();
912 let e2 = world.spawn((A(0), B(0))).id();
913 let e3 = world.spawn((A(0), B(0))).id();
914 world.spawn((A(0), B(0)));
915
916 world.clear_trackers();
917
918 for (i, mut a) in world.query::<&mut A>().iter_mut(&mut world).enumerate() {
919 if i % 2 == 0 {
920 a.0 += 1;
921 }
922 }
923
924 fn get_filtered<F: QueryFilter>(world: &mut World) -> Vec<Entity> {
925 world
926 .query_filtered::<Entity, F>()
927 .iter(world)
928 .collect::<Vec<Entity>>()
929 }
930
931 assert_eq!(get_filtered::<Changed<A>>(&mut world), vec![e1, e3]);
932
933 world.entity_mut(e1).insert(C);
935
936 assert_eq!(get_filtered::<Changed<A>>(&mut world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
937
938 world.entity_mut(e1).insert((A(0), B(0)));
940 assert_eq!(
941 get_filtered::<Changed<A>>(&mut world),
942 vec![e3, e1],
943 "changed entities list should not change"
944 );
945
946 assert!(world.despawn(e2));
948 assert_eq!(
949 get_filtered::<Changed<A>>(&mut world),
950 vec![e3, e1],
951 "changed entities list should not change"
952 );
953
954 assert!(world.despawn(e1));
956 assert_eq!(
957 get_filtered::<Changed<A>>(&mut world),
958 vec![e3],
959 "e1 should no longer be returned"
960 );
961
962 world.clear_trackers();
963
964 assert!(get_filtered::<Changed<A>>(&mut world).is_empty());
965
966 let e4 = world.spawn_empty().id();
967
968 world.entity_mut(e4).insert(A(0));
969 assert_eq!(get_filtered::<Changed<A>>(&mut world), vec![e4]);
970 assert_eq!(get_filtered::<Added<A>>(&mut world), vec![e4]);
971
972 world.entity_mut(e4).insert(A(1));
973 assert_eq!(get_filtered::<Changed<A>>(&mut world), vec![e4]);
974
975 world.clear_trackers();
976
977 world.entity_mut(e4).insert((A(0), B(0)));
980
981 assert!(get_filtered::<Added<A>>(&mut world).is_empty());
982 assert_eq!(get_filtered::<Changed<A>>(&mut world), vec![e4]);
983 assert_eq!(get_filtered::<Added<B>>(&mut world), vec![e4]);
984 assert_eq!(get_filtered::<Changed<B>>(&mut world), vec![e4]);
985 }
986
987 #[test]
988 fn changed_trackers_sparse() {
989 let mut world = World::default();
990 let e1 = world.spawn(SparseStored(0)).id();
991 let e2 = world.spawn(SparseStored(0)).id();
992 let e3 = world.spawn(SparseStored(0)).id();
993 world.spawn(SparseStored(0));
994
995 world.clear_trackers();
996
997 for (i, mut a) in world
998 .query::<&mut SparseStored>()
999 .iter_mut(&mut world)
1000 .enumerate()
1001 {
1002 if i % 2 == 0 {
1003 a.0 += 1;
1004 }
1005 }
1006
1007 fn get_filtered<F: QueryFilter>(world: &mut World) -> Vec<Entity> {
1008 world
1009 .query_filtered::<Entity, F>()
1010 .iter(world)
1011 .collect::<Vec<Entity>>()
1012 }
1013
1014 assert_eq!(
1015 get_filtered::<Changed<SparseStored>>(&mut world),
1016 vec![e1, e3]
1017 );
1018
1019 world.entity_mut(e1).insert(C);
1021
1022 assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
1023
1024 world.entity_mut(e1).insert(SparseStored(0));
1026 assert_eq!(
1027 get_filtered::<Changed<SparseStored>>(&mut world),
1028 vec![e3, e1],
1029 "changed entities list should not change"
1030 );
1031
1032 assert!(world.despawn(e2));
1034 assert_eq!(
1035 get_filtered::<Changed<SparseStored>>(&mut world),
1036 vec![e3, e1],
1037 "changed entities list should not change"
1038 );
1039
1040 assert!(world.despawn(e1));
1042 assert_eq!(
1043 get_filtered::<Changed<SparseStored>>(&mut world),
1044 vec![e3],
1045 "e1 should no longer be returned"
1046 );
1047
1048 world.clear_trackers();
1049
1050 assert!(get_filtered::<Changed<SparseStored>>(&mut world).is_empty());
1051
1052 let e4 = world.spawn_empty().id();
1053
1054 world.entity_mut(e4).insert(SparseStored(0));
1055 assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e4]);
1056 assert_eq!(get_filtered::<Added<SparseStored>>(&mut world), vec![e4]);
1057
1058 world.entity_mut(e4).insert(A(1));
1059 assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e4]);
1060
1061 world.clear_trackers();
1062
1063 world.entity_mut(e4).insert(SparseStored(0));
1066
1067 assert!(get_filtered::<Added<SparseStored>>(&mut world).is_empty());
1068 assert_eq!(get_filtered::<Changed<SparseStored>>(&mut world), vec![e4]);
1069 }
1070
1071 #[test]
1072 fn empty_spawn() {
1073 let mut world = World::default();
1074 let e = world.spawn_empty().id();
1075 let mut e_mut = world.entity_mut(e);
1076 e_mut.insert(A(0));
1077 assert_eq!(e_mut.get::<A>().unwrap(), &A(0));
1078 }
1079
1080 #[test]
1081 fn reserve_and_spawn() {
1082 let mut world = World::default();
1083 let e = world.entities().reserve_entity();
1084 world.flush_entities();
1085 let mut e_mut = world.entity_mut(e);
1086 e_mut.insert(A(0));
1087 assert_eq!(e_mut.get::<A>().unwrap(), &A(0));
1088 }
1089
1090 #[test]
1091 fn changed_query() {
1092 let mut world = World::default();
1093 let e1 = world.spawn((A(0), B(0))).id();
1094
1095 fn get_changed(world: &mut World) -> Vec<Entity> {
1096 world
1097 .query_filtered::<Entity, Changed<A>>()
1098 .iter(world)
1099 .collect::<Vec<Entity>>()
1100 }
1101 assert_eq!(get_changed(&mut world), vec![e1]);
1102 world.clear_trackers();
1103 assert_eq!(get_changed(&mut world), vec![]);
1104 *world.get_mut(e1).unwrap() = A(1);
1105 assert_eq!(get_changed(&mut world), vec![e1]);
1106 }
1107
1108 #[test]
1109 fn resource() {
1110 use crate::system::Resource;
1111
1112 #[derive(Resource, PartialEq, Debug)]
1113 struct Num(i32);
1114
1115 #[derive(Resource, PartialEq, Debug)]
1116 struct BigNum(u64);
1117
1118 let mut world = World::default();
1119 assert!(world.get_resource::<Num>().is_none());
1120 assert!(!world.contains_resource::<Num>());
1121 assert!(!world.is_resource_added::<Num>());
1122 assert!(!world.is_resource_changed::<Num>());
1123
1124 world.insert_resource(Num(123));
1125 let resource_id = world
1126 .components()
1127 .get_resource_id(TypeId::of::<Num>())
1128 .unwrap();
1129 let archetype_component_id = world.storages().resources.get(resource_id).unwrap().id();
1130
1131 assert_eq!(world.resource::<Num>().0, 123);
1132 assert!(world.contains_resource::<Num>());
1133 assert!(world.is_resource_added::<Num>());
1134 assert!(world.is_resource_changed::<Num>());
1135
1136 world.insert_resource(BigNum(456));
1137 assert_eq!(world.resource::<BigNum>().0, 456u64);
1138
1139 world.insert_resource(BigNum(789));
1140 assert_eq!(world.resource::<BigNum>().0, 789);
1141
1142 {
1143 let mut value = world.resource_mut::<BigNum>();
1144 assert_eq!(value.0, 789);
1145 value.0 = 10;
1146 }
1147
1148 assert_eq!(
1149 world.resource::<BigNum>().0,
1150 10,
1151 "resource changes are preserved"
1152 );
1153
1154 assert_eq!(
1155 world.remove_resource::<BigNum>(),
1156 Some(BigNum(10)),
1157 "removed resource has the correct value"
1158 );
1159 assert_eq!(
1160 world.get_resource::<BigNum>(),
1161 None,
1162 "removed resource no longer exists"
1163 );
1164 assert_eq!(
1165 world.remove_resource::<BigNum>(),
1166 None,
1167 "double remove returns nothing"
1168 );
1169
1170 world.insert_resource(BigNum(1));
1171 assert_eq!(
1172 world.get_resource::<BigNum>(),
1173 Some(&BigNum(1)),
1174 "re-inserting resources works"
1175 );
1176
1177 assert_eq!(
1178 world.get_resource::<Num>(),
1179 Some(&Num(123)),
1180 "other resources are unaffected"
1181 );
1182
1183 let current_resource_id = world
1184 .components()
1185 .get_resource_id(TypeId::of::<Num>())
1186 .unwrap();
1187 assert_eq!(
1188 resource_id, current_resource_id,
1189 "resource id does not change after removing / re-adding"
1190 );
1191
1192 let current_archetype_component_id =
1193 world.storages().resources.get(resource_id).unwrap().id();
1194
1195 assert_eq!(
1196 archetype_component_id, current_archetype_component_id,
1197 "resource archetype component id does not change after removing / re-adding"
1198 );
1199 }
1200
1201 #[test]
1202 fn remove() {
1203 let mut world = World::default();
1204 let e1 = world.spawn((A(1), B(1), TableStored("a"))).id();
1205
1206 let mut e = world.entity_mut(e1);
1207 assert_eq!(e.get::<TableStored>(), Some(&TableStored("a")));
1208 assert_eq!(e.get::<A>(), Some(&A(1)));
1209 assert_eq!(e.get::<B>(), Some(&B(1)));
1210 assert_eq!(
1211 e.get::<C>(),
1212 None,
1213 "C is not in the entity, so it should not exist"
1214 );
1215
1216 e.remove::<(A, B, C)>();
1217 assert_eq!(
1218 e.get::<TableStored>(),
1219 Some(&TableStored("a")),
1220 "TableStored is not in the removed bundle, so it should exist"
1221 );
1222 assert_eq!(
1223 e.get::<A>(),
1224 None,
1225 "Num is in the removed bundle, so it should not exist"
1226 );
1227 assert_eq!(
1228 e.get::<B>(),
1229 None,
1230 "f64 is in the removed bundle, so it should not exist"
1231 );
1232 assert_eq!(
1233 e.get::<C>(),
1234 None,
1235 "usize is in the removed bundle, so it should not exist"
1236 );
1237 }
1238
1239 #[test]
1240 fn take() {
1241 let mut world = World::default();
1242 world.spawn((A(1), B(1), TableStored("1")));
1243 let e2 = world.spawn((A(2), B(2), TableStored("2"))).id();
1244 world.spawn((A(3), B(3), TableStored("3")));
1245
1246 let mut query = world.query::<(&B, &TableStored)>();
1247 let results = query
1248 .iter(&world)
1249 .map(|(a, b)| (a.0, b.0))
1250 .collect::<Vec<_>>();
1251 assert_eq!(results, vec![(1, "1"), (2, "2"), (3, "3"),]);
1252
1253 let removed_bundle = world.entity_mut(e2).take::<(B, TableStored)>().unwrap();
1254 assert_eq!(removed_bundle, (B(2), TableStored("2")));
1255
1256 let results = query
1257 .iter(&world)
1258 .map(|(a, b)| (a.0, b.0))
1259 .collect::<Vec<_>>();
1260 assert_eq!(results, vec![(1, "1"), (3, "3"),]);
1261
1262 let mut a_query = world.query::<&A>();
1263 let results = a_query.iter(&world).map(|a| a.0).collect::<Vec<_>>();
1264 assert_eq!(results, vec![1, 3, 2]);
1265
1266 let entity_ref = world.entity(e2);
1267 assert_eq!(
1268 entity_ref.get::<A>(),
1269 Some(&A(2)),
1270 "A is not in the removed bundle, so it should exist"
1271 );
1272 assert_eq!(
1273 entity_ref.get::<B>(),
1274 None,
1275 "B is in the removed bundle, so it should not exist"
1276 );
1277 assert_eq!(
1278 entity_ref.get::<TableStored>(),
1279 None,
1280 "TableStored is in the removed bundle, so it should not exist"
1281 );
1282 }
1283
1284 #[test]
1285 fn non_send_resource() {
1286 let mut world = World::default();
1287 world.insert_non_send_resource(123i32);
1288 world.insert_non_send_resource(456i64);
1289 assert_eq!(*world.non_send_resource::<i32>(), 123);
1290 assert_eq!(*world.non_send_resource_mut::<i64>(), 456);
1291 }
1292
1293 #[test]
1294 fn non_send_resource_points_to_distinct_data() {
1295 let mut world = World::default();
1296 world.insert_resource(A(123));
1297 world.insert_non_send_resource(A(456));
1298 assert_eq!(*world.resource::<A>(), A(123));
1299 assert_eq!(*world.non_send_resource::<A>(), A(456));
1300 }
1301
1302 #[test]
1303 #[should_panic]
1304 fn non_send_resource_panic() {
1305 let mut world = World::default();
1306 world.insert_non_send_resource(0i32);
1307 std::thread::spawn(move || {
1308 let _ = world.non_send_resource_mut::<i32>();
1309 })
1310 .join()
1311 .unwrap();
1312 }
1313
1314 #[test]
1315 fn exact_size_query() {
1316 let mut world = World::default();
1317 world.spawn((A(0), B(0)));
1318 world.spawn((A(0), B(0)));
1319 world.spawn((A(0), B(0), C));
1320 world.spawn(C);
1321
1322 let mut query = world.query::<(&A, &B)>();
1323 assert_eq!(query.iter(&world).len(), 3);
1324 }
1325
1326 #[test]
1327 #[should_panic]
1328 fn duplicate_components_panic() {
1329 let mut world = World::new();
1330 world.spawn((A(1), A(2)));
1331 }
1332
1333 #[test]
1334 #[should_panic]
1335 fn ref_and_mut_query_panic() {
1336 let mut world = World::new();
1337 world.query::<(&A, &mut A)>();
1338 }
1339
1340 #[test]
1341 #[should_panic]
1342 fn entity_ref_and_mut_query_panic() {
1343 let mut world = World::new();
1344 world.query::<(EntityRef, &mut A)>();
1345 }
1346
1347 #[test]
1348 #[should_panic]
1349 fn mut_and_ref_query_panic() {
1350 let mut world = World::new();
1351 world.query::<(&mut A, &A)>();
1352 }
1353
1354 #[test]
1355 #[should_panic]
1356 fn mut_and_entity_ref_query_panic() {
1357 let mut world = World::new();
1358 world.query::<(&mut A, EntityRef)>();
1359 }
1360
1361 #[test]
1362 #[should_panic]
1363 fn mut_and_mut_query_panic() {
1364 let mut world = World::new();
1365 world.query::<(&mut A, &mut A)>();
1366 }
1367
1368 #[test]
1369 #[should_panic]
1370 fn multiple_worlds_same_query_iter() {
1371 let mut world_a = World::new();
1372 let world_b = World::new();
1373 let mut query = world_a.query::<&A>();
1374 query.iter(&world_a);
1375 query.iter(&world_b);
1376 }
1377
1378 #[test]
1379 fn query_filters_dont_collide_with_fetches() {
1380 let mut world = World::new();
1381 world.query_filtered::<&mut A, Changed<A>>();
1382 }
1383
1384 #[test]
1385 fn filtered_query_access() {
1386 let mut world = World::new();
1387 let query = world.query_filtered::<&mut A, Changed<B>>();
1388
1389 let mut expected = FilteredAccess::<ComponentId>::default();
1390 let a_id = world.components.get_id(TypeId::of::<A>()).unwrap();
1391 let b_id = world.components.get_id(TypeId::of::<B>()).unwrap();
1392 expected.add_write(a_id);
1393 expected.add_read(b_id);
1394 assert!(
1395 query.component_access.eq(&expected),
1396 "ComponentId access from query fetch and query filter should be combined"
1397 );
1398 }
1399
1400 #[test]
1401 #[should_panic]
1402 fn multiple_worlds_same_query_get() {
1403 let mut world_a = World::new();
1404 let world_b = World::new();
1405 let mut query = world_a.query::<&A>();
1406 let _ = query.get(&world_a, Entity::from_raw(0));
1407 let _ = query.get(&world_b, Entity::from_raw(0));
1408 }
1409
1410 #[test]
1411 #[should_panic]
1412 fn multiple_worlds_same_query_for_each() {
1413 let mut world_a = World::new();
1414 let world_b = World::new();
1415 let mut query = world_a.query::<&A>();
1416 query.iter(&world_a).for_each(|_| {});
1417 query.iter(&world_b).for_each(|_| {});
1418 }
1419
1420 #[test]
1421 fn resource_scope() {
1422 let mut world = World::default();
1423 world.insert_resource(A(0));
1424 world.resource_scope(|world: &mut World, mut value: Mut<A>| {
1425 value.0 += 1;
1426 assert!(!world.contains_resource::<A>());
1427 });
1428 assert_eq!(world.resource::<A>().0, 1);
1429 }
1430
1431 #[test]
1432 #[should_panic(
1433 expected = "Attempted to access or drop non-send resource bevy_ecs::tests::NonSendA from thread"
1434 )]
1435 fn non_send_resource_drop_from_different_thread() {
1436 let mut world = World::default();
1437 world.insert_non_send_resource(NonSendA::default());
1438
1439 let thread = std::thread::spawn(move || {
1440 drop(world);
1443 });
1444
1445 if let Err(err) = thread.join() {
1446 std::panic::resume_unwind(err);
1447 }
1448 }
1449
1450 #[test]
1451 fn non_send_resource_drop_from_same_thread() {
1452 let mut world = World::default();
1453 world.insert_non_send_resource(NonSendA::default());
1454 drop(world);
1455 }
1456
1457 #[test]
1458 fn insert_overwrite_drop() {
1459 let (dropck1, dropped1) = DropCk::new_pair();
1460 let (dropck2, dropped2) = DropCk::new_pair();
1461 let mut world = World::default();
1462 world.spawn(dropck1).insert(dropck2);
1463 assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1464 assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1465 drop(world);
1466 assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1467 assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1468 }
1469
1470 #[test]
1471 fn insert_overwrite_drop_sparse() {
1472 let (dropck1, dropped1) = DropCk::new_pair();
1473 let (dropck2, dropped2) = DropCk::new_pair();
1474 let mut world = World::default();
1475
1476 world
1477 .spawn(DropCkSparse(dropck1))
1478 .insert(DropCkSparse(dropck2));
1479 assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1480 assert_eq!(dropped2.load(Ordering::Relaxed), 0);
1481 drop(world);
1482 assert_eq!(dropped1.load(Ordering::Relaxed), 1);
1483 assert_eq!(dropped2.load(Ordering::Relaxed), 1);
1484 }
1485
1486 #[test]
1487 fn clear_entities() {
1488 let mut world = World::default();
1489
1490 world.insert_resource(A(0));
1491 world.spawn(A(1));
1492 world.spawn(SparseStored(1));
1493
1494 let mut q1 = world.query::<&A>();
1495 let mut q2 = world.query::<&SparseStored>();
1496
1497 assert_eq!(q1.iter(&world).len(), 1);
1498 assert_eq!(q2.iter(&world).len(), 1);
1499 assert_eq!(world.entities().len(), 2);
1500
1501 world.clear_entities();
1502
1503 assert_eq!(
1504 q1.iter(&world).len(),
1505 0,
1506 "world should not contain table components"
1507 );
1508 assert_eq!(
1509 q2.iter(&world).len(),
1510 0,
1511 "world should not contain sparse set components"
1512 );
1513 assert_eq!(
1514 world.entities().len(),
1515 0,
1516 "world should not have any entities"
1517 );
1518 assert_eq!(
1519 world.resource::<A>().0,
1520 0,
1521 "world should still contain resources"
1522 );
1523 }
1524
1525 #[test]
1526 fn test_is_archetypal_size_hints() {
1527 let mut world = World::default();
1528 macro_rules! query_min_size {
1529 ($query:ty, $filter:ty) => {
1530 world
1531 .query_filtered::<$query, $filter>()
1532 .iter(&world)
1533 .size_hint()
1534 .0
1535 };
1536 }
1537
1538 world.spawn((A(1), B(1), C));
1539 world.spawn((A(1), C));
1540 world.spawn((A(1), B(1)));
1541 world.spawn((B(1), C));
1542 world.spawn(A(1));
1543 world.spawn(C);
1544 assert_eq!(2, query_min_size![(), (With<A>, Without<B>)]);
1545 assert_eq!(3, query_min_size![&B, Or<(With<A>, With<C>)>]);
1546 assert_eq!(1, query_min_size![&B, (With<A>, With<C>)]);
1547 assert_eq!(1, query_min_size![(&A, &B), With<C>]);
1548 assert_eq!(4, query_min_size![&A, ()], "Simple Archetypal");
1549 assert_eq!(4, query_min_size![Ref<A>, ()]);
1550 assert_eq!(0, query_min_size![(), Added<A>], "Simple Added");
1553 assert_eq!(0, query_min_size![(), Changed<A>], "Simple Changed");
1554 assert_eq!(0, query_min_size![(&A, &B), Changed<A>]);
1555 assert_eq!(0, query_min_size![&A, (Changed<A>, With<B>)]);
1556 assert_eq!(0, query_min_size![(&A, &B), Or<(Changed<A>, Changed<B>)>]);
1557 }
1558
1559 #[test]
1560 fn reserve_entities_across_worlds() {
1561 let mut world_a = World::default();
1562 let mut world_b = World::default();
1563
1564 let e1 = world_a.spawn(A(1)).id();
1565 let e2 = world_a.spawn(A(2)).id();
1566 let e3 = world_a.entities().reserve_entity();
1567 world_a.flush_entities();
1568
1569 let world_a_max_entities = world_a.entities().len();
1570 world_b.entities.reserve_entities(world_a_max_entities);
1571 world_b.entities.flush_as_invalid();
1572
1573 let e4 = world_b.spawn(A(4)).id();
1574 assert_eq!(
1575 e4,
1576 Entity::from_raw(3),
1577 "new entity is created immediately after world_a's max entity"
1578 );
1579 assert!(world_b.get::<A>(e1).is_none());
1580 assert!(world_b.get_entity(e1).is_none());
1581
1582 assert!(world_b.get::<A>(e2).is_none());
1583 assert!(world_b.get_entity(e2).is_none());
1584
1585 assert!(world_b.get::<A>(e3).is_none());
1586 assert!(world_b.get_entity(e3).is_none());
1587
1588 world_b.get_or_spawn(e1).unwrap().insert(B(1));
1589 assert_eq!(
1590 world_b.get::<B>(e1),
1591 Some(&B(1)),
1592 "spawning into 'world_a' entities works"
1593 );
1594
1595 world_b.get_or_spawn(e4).unwrap().insert(B(4));
1596 assert_eq!(
1597 world_b.get::<B>(e4),
1598 Some(&B(4)),
1599 "spawning into existing `world_b` entities works"
1600 );
1601 assert_eq!(
1602 world_b.get::<A>(e4),
1603 Some(&A(4)),
1604 "spawning into existing `world_b` entities works"
1605 );
1606
1607 let e4_mismatched_generation =
1608 Entity::from_raw_and_generation(3, NonZeroU32::new(2).unwrap());
1609 assert!(
1610 world_b.get_or_spawn(e4_mismatched_generation).is_none(),
1611 "attempting to spawn on top of an entity with a mismatched entity generation fails"
1612 );
1613 assert_eq!(
1614 world_b.get::<B>(e4),
1615 Some(&B(4)),
1616 "failed mismatched spawn doesn't change existing entity"
1617 );
1618 assert_eq!(
1619 world_b.get::<A>(e4),
1620 Some(&A(4)),
1621 "failed mismatched spawn doesn't change existing entity"
1622 );
1623
1624 let high_non_existent_entity = Entity::from_raw(6);
1625 world_b
1626 .get_or_spawn(high_non_existent_entity)
1627 .unwrap()
1628 .insert(B(10));
1629 assert_eq!(
1630 world_b.get::<B>(high_non_existent_entity),
1631 Some(&B(10)),
1632 "inserting into newly allocated high / non-continuous entity id works"
1633 );
1634
1635 let high_non_existent_but_reserved_entity = Entity::from_raw(5);
1636 assert!(
1637 world_b.get_entity(high_non_existent_but_reserved_entity).is_none(),
1638 "entities between high-newly allocated entity and continuous block of existing entities don't exist"
1639 );
1640
1641 let reserved_entities = vec![
1642 world_b.entities().reserve_entity(),
1643 world_b.entities().reserve_entity(),
1644 world_b.entities().reserve_entity(),
1645 world_b.entities().reserve_entity(),
1646 ];
1647
1648 assert_eq!(
1649 reserved_entities,
1650 vec![
1651 Entity::from_raw(5),
1652 Entity::from_raw(4),
1653 Entity::from_raw(7),
1654 Entity::from_raw(8),
1655 ],
1656 "space between original entities and high entities is used for new entity ids"
1657 );
1658 }
1659
1660 #[test]
1661 fn insert_or_spawn_batch() {
1662 let mut world = World::default();
1663 let e0 = world.spawn(A(0)).id();
1664 let e1 = Entity::from_raw(1);
1665
1666 let values = vec![(e0, (B(0), C)), (e1, (B(1), C))];
1667
1668 world.insert_or_spawn_batch(values).unwrap();
1669
1670 assert_eq!(
1671 world.get::<A>(e0),
1672 Some(&A(0)),
1673 "existing component was preserved"
1674 );
1675 assert_eq!(
1676 world.get::<B>(e0),
1677 Some(&B(0)),
1678 "pre-existing entity received correct B component"
1679 );
1680 assert_eq!(
1681 world.get::<B>(e1),
1682 Some(&B(1)),
1683 "new entity was spawned and received correct B component"
1684 );
1685 assert_eq!(
1686 world.get::<C>(e0),
1687 Some(&C),
1688 "pre-existing entity received C component"
1689 );
1690 assert_eq!(
1691 world.get::<C>(e1),
1692 Some(&C),
1693 "new entity was spawned and received C component"
1694 );
1695 }
1696
1697 #[test]
1698 fn insert_or_spawn_batch_invalid() {
1699 let mut world = World::default();
1700 let e0 = world.spawn(A(0)).id();
1701 let e1 = Entity::from_raw(1);
1702 let e2 = world.spawn_empty().id();
1703 let invalid_e2 = Entity::from_raw_and_generation(e2.index(), NonZeroU32::new(2).unwrap());
1704
1705 let values = vec![(e0, (B(0), C)), (e1, (B(1), C)), (invalid_e2, (B(2), C))];
1706
1707 let result = world.insert_or_spawn_batch(values);
1708
1709 assert_eq!(
1710 result,
1711 Err(vec![invalid_e2]),
1712 "e2 failed to be spawned or inserted into"
1713 );
1714
1715 assert_eq!(
1716 world.get::<A>(e0),
1717 Some(&A(0)),
1718 "existing component was preserved"
1719 );
1720 assert_eq!(
1721 world.get::<B>(e0),
1722 Some(&B(0)),
1723 "pre-existing entity received correct B component"
1724 );
1725 assert_eq!(
1726 world.get::<B>(e1),
1727 Some(&B(1)),
1728 "new entity was spawned and received correct B component"
1729 );
1730 assert_eq!(
1731 world.get::<C>(e0),
1732 Some(&C),
1733 "pre-existing entity received C component"
1734 );
1735 assert_eq!(
1736 world.get::<C>(e1),
1737 Some(&C),
1738 "new entity was spawned and received C component"
1739 );
1740 }
1741
1742 #[allow(dead_code)]
1744 #[derive(Component)]
1745 struct ComponentA(u32);
1746
1747 #[allow(dead_code)]
1748 #[derive(Component)]
1749 struct ComponentB(u32);
1750
1751 #[derive(Bundle)]
1752 struct Simple(ComponentA);
1753
1754 #[derive(Bundle)]
1755 struct Tuple(Simple, ComponentB);
1756
1757 #[derive(Bundle)]
1758 struct Record {
1759 field0: Simple,
1760 field1: ComponentB,
1761 }
1762}