1mod adapter_system;
123mod builder;
124mod combinator;
125mod commands;
126mod exclusive_function_system;
127mod exclusive_system_param;
128mod function_system;
129mod input;
130mod observer_system;
131mod query;
132mod schedule_system;
133mod system;
134mod system_name;
135mod system_param;
136mod system_registry;
137
138use core::any::TypeId;
139
140pub use adapter_system::*;
141pub use builder::*;
142pub use combinator::*;
143pub use commands::*;
144pub use exclusive_function_system::*;
145pub use exclusive_system_param::*;
146pub use function_system::*;
147pub use input::*;
148pub use observer_system::*;
149pub use query::*;
150pub use schedule_system::*;
151pub use system::*;
152pub use system_name::*;
153pub use system_param::*;
154pub use system_registry::*;
155
156use crate::world::{FromWorld, World};
157
158#[diagnostic::on_unimplemented(
182 message = "`{Self}` is not a valid system with input `{In}` and output `{Out}`",
183 label = "invalid system"
184)]
185pub trait IntoSystem<In: SystemInput, Out, Marker>: Sized {
186 type System: System<In = In, Out = Out>;
188
189 fn into_system(this: Self) -> Self::System;
191
192 fn pipe<B, BIn, BOut, MarkerB>(self, system: B) -> IntoPipeSystem<Self, B>
197 where
198 Out: 'static,
199 B: IntoSystem<BIn, BOut, MarkerB>,
200 for<'a> BIn: SystemInput<Inner<'a> = Out>,
201 {
202 IntoPipeSystem::new(self, system)
203 }
204
205 fn map<T, F>(self, f: F) -> IntoAdapterSystem<F, Self>
225 where
226 F: Send + Sync + 'static + FnMut(Out) -> T,
227 {
228 IntoAdapterSystem::new(f, self)
229 }
230
231 fn with_input<T>(self, value: T) -> WithInputWrapper<Self::System, T>
254 where
255 for<'i> In: SystemInput<Inner<'i> = &'i mut T>,
256 T: Send + Sync + 'static,
257 {
258 WithInputWrapper::new(self, value)
259 }
260
261 fn with_input_from<T>(self) -> WithInputFromWrapper<Self::System, T>
295 where
296 for<'i> In: SystemInput<Inner<'i> = &'i mut T>,
297 T: FromWorld + Send + Sync + 'static,
298 {
299 WithInputFromWrapper::new(self)
300 }
301
302 #[inline]
304 fn system_type_id(&self) -> TypeId {
305 TypeId::of::<Self::System>()
306 }
307}
308
309impl<T: System> IntoSystem<T::In, T::Out, ()> for T {
311 type System = T;
312 fn into_system(this: Self) -> Self {
313 this
314 }
315}
316
317pub fn assert_is_system<In: SystemInput, Out: 'static, Marker>(
342 system: impl IntoSystem<In, Out, Marker>,
343) {
344 let mut system = IntoSystem::into_system(system);
345
346 let mut world = World::new();
348 system.initialize(&mut world);
349}
350
351pub fn assert_is_read_only_system<In, Out, Marker, S>(system: S)
375where
376 In: SystemInput,
377 Out: 'static,
378 S: IntoSystem<In, Out, Marker>,
379 S::System: ReadOnlySystem,
380{
381 assert_is_system(system);
382}
383
384pub fn assert_system_does_not_conflict<Out, Params, S: IntoSystem<(), Out, Params>>(sys: S) {
390 let mut world = World::new();
391 let mut system = IntoSystem::into_system(sys);
392 system.initialize(&mut world);
393 system.run((), &mut world).unwrap();
394}
395
396#[cfg(test)]
397#[expect(clippy::print_stdout, reason = "Allowed in tests.")]
398mod tests {
399 use alloc::{vec, vec::Vec};
400 use bevy_utils::default;
401 use core::any::TypeId;
402 use std::println;
403
404 use crate::{
405 archetype::Archetypes,
406 bundle::Bundles,
407 change_detection::DetectChanges,
408 component::{Component, Components},
409 entity::{Entities, Entity},
410 error::Result,
411 lifecycle::RemovedComponents,
412 name::Name,
413 prelude::{Add, AnyOf, EntityRef, On},
414 query::{Added, Changed, Or, SpawnDetails, Spawned, With, Without},
415 resource::Resource,
416 schedule::{
417 common_conditions::resource_exists, ApplyDeferred, IntoScheduleConfigs, Schedule,
418 SystemCondition,
419 },
420 system::{
421 Commands, In, InMut, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query, Res,
422 ResMut, Single, StaticSystemParam, System, SystemState,
423 },
424 world::{DeferredWorld, EntityMut, FromWorld, World},
425 };
426
427 use super::ScheduleSystem;
428
429 #[derive(Resource, PartialEq, Debug)]
430 enum SystemRan {
431 Yes,
432 No,
433 }
434
435 #[derive(Component, Resource, Debug, Eq, PartialEq, Default)]
436 struct A;
437 #[derive(Component, Resource)]
438 struct B;
439 #[derive(Component, Resource)]
440 struct C;
441 #[derive(Component, Resource)]
442 struct D;
443 #[derive(Component, Resource)]
444 struct E;
445 #[derive(Component, Resource)]
446 struct F;
447
448 #[derive(Component, Debug)]
449 struct W<T>(T);
450
451 #[test]
452 fn simple_system() {
453 fn sys(query: Query<&A>) {
454 for a in &query {
455 println!("{a:?}");
456 }
457 }
458
459 let mut system = IntoSystem::into_system(sys);
460 let mut world = World::new();
461 world.spawn(A);
462
463 system.initialize(&mut world);
464 system.run((), &mut world).unwrap();
465 }
466
467 fn run_system<Marker, S: IntoScheduleConfigs<ScheduleSystem, Marker>>(
468 world: &mut World,
469 system: S,
470 ) {
471 let mut schedule = Schedule::default();
472 schedule.add_systems(system);
473 schedule.run(world);
474 }
475
476 #[test]
477 fn get_many_is_ordered() {
478 use crate::resource::Resource;
479 const ENTITIES_COUNT: usize = 1000;
480
481 #[derive(Resource)]
482 struct EntitiesArray(Vec<Entity>);
483
484 fn query_system(
485 mut ran: ResMut<SystemRan>,
486 entities_array: Res<EntitiesArray>,
487 q: Query<&W<usize>>,
488 ) {
489 let entities_array: [Entity; ENTITIES_COUNT] =
490 entities_array.0.clone().try_into().unwrap();
491
492 for (i, w) in (0..ENTITIES_COUNT).zip(q.get_many(entities_array).unwrap()) {
493 assert_eq!(i, w.0);
494 }
495
496 *ran = SystemRan::Yes;
497 }
498
499 fn query_system_mut(
500 mut ran: ResMut<SystemRan>,
501 entities_array: Res<EntitiesArray>,
502 mut q: Query<&mut W<usize>>,
503 ) {
504 let entities_array: [Entity; ENTITIES_COUNT] =
505 entities_array.0.clone().try_into().unwrap();
506
507 for (i, w) in (0..ENTITIES_COUNT).zip(q.get_many_mut(entities_array).unwrap()) {
508 assert_eq!(i, w.0);
509 }
510
511 *ran = SystemRan::Yes;
512 }
513
514 let mut world = World::default();
515 world.insert_resource(SystemRan::No);
516 let entity_ids = (0..ENTITIES_COUNT)
517 .map(|i| world.spawn(W(i)).id())
518 .collect();
519 world.insert_resource(EntitiesArray(entity_ids));
520
521 run_system(&mut world, query_system);
522 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
523
524 world.insert_resource(SystemRan::No);
525 run_system(&mut world, query_system_mut);
526 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
527 }
528
529 #[test]
530 fn or_param_set_system() {
531 fn query_system(
533 mut ran: ResMut<SystemRan>,
534 mut set: ParamSet<(
535 Query<(), Or<(Changed<A>, Changed<B>)>>,
536 Query<(), Or<(Added<A>, Added<B>)>>,
537 )>,
538 ) {
539 let changed = set.p0().iter().count();
540 let added = set.p1().iter().count();
541
542 assert_eq!(changed, 1);
543 assert_eq!(added, 1);
544
545 *ran = SystemRan::Yes;
546 }
547
548 let mut world = World::default();
549 world.insert_resource(SystemRan::No);
550 world.spawn((A, B));
551
552 run_system(&mut world, query_system);
553
554 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
555 }
556
557 #[test]
558 fn changed_resource_system() {
559 use crate::resource::Resource;
560
561 #[derive(Resource)]
562 struct Flipper(bool);
563
564 #[derive(Resource)]
565 struct Added(usize);
566
567 #[derive(Resource)]
568 struct Changed(usize);
569
570 fn incr_e_on_flip(
571 value: Res<Flipper>,
572 mut changed: ResMut<Changed>,
573 mut added: ResMut<Added>,
574 ) {
575 if value.is_added() {
576 added.0 += 1;
577 }
578
579 if value.is_changed() {
580 changed.0 += 1;
581 }
582 }
583
584 let mut world = World::default();
585 world.insert_resource(Flipper(false));
586 world.insert_resource(Added(0));
587 world.insert_resource(Changed(0));
588
589 let mut schedule = Schedule::default();
590
591 schedule.add_systems((incr_e_on_flip, ApplyDeferred, World::clear_trackers).chain());
592
593 schedule.run(&mut world);
594 assert_eq!(world.resource::<Added>().0, 1);
595 assert_eq!(world.resource::<Changed>().0, 1);
596
597 schedule.run(&mut world);
598 assert_eq!(world.resource::<Added>().0, 1);
599 assert_eq!(world.resource::<Changed>().0, 1);
600
601 world.resource_mut::<Flipper>().0 = true;
602 schedule.run(&mut world);
603 assert_eq!(world.resource::<Added>().0, 1);
604 assert_eq!(world.resource::<Changed>().0, 2);
605 }
606
607 #[test]
608 #[should_panic = "error[B0001]"]
609 fn option_has_no_filter_with() {
610 fn sys(_: Query<(Option<&A>, &mut B)>, _: Query<&mut B, Without<A>>) {}
611 let mut world = World::default();
612 run_system(&mut world, sys);
613 }
614
615 #[test]
616 fn option_doesnt_remove_unrelated_filter_with() {
617 fn sys(_: Query<(Option<&A>, &mut B, &A)>, _: Query<&mut B, Without<A>>) {}
618 let mut world = World::default();
619 run_system(&mut world, sys);
620 }
621
622 #[test]
623 fn any_of_working() {
624 fn sys(_: Query<AnyOf<(&mut A, &B)>>) {}
625 let mut world = World::default();
626 run_system(&mut world, sys);
627 }
628
629 #[test]
630 fn any_of_with_and_without_common() {
631 fn sys(_: Query<(&mut D, &C, AnyOf<(&A, &B)>)>, _: Query<&mut D, Without<C>>) {}
632 let mut world = World::default();
633 run_system(&mut world, sys);
634 }
635
636 #[test]
637 #[should_panic]
638 fn any_of_with_mut_and_ref() {
639 fn sys(_: Query<AnyOf<(&mut A, &A)>>) {}
640 let mut world = World::default();
641 run_system(&mut world, sys);
642 }
643
644 #[test]
645 #[should_panic]
646 fn any_of_with_ref_and_mut() {
647 fn sys(_: Query<AnyOf<(&A, &mut A)>>) {}
648 let mut world = World::default();
649 run_system(&mut world, sys);
650 }
651
652 #[test]
653 #[should_panic]
654 fn any_of_with_mut_and_option() {
655 fn sys(_: Query<AnyOf<(&mut A, Option<&A>)>>) {}
656 let mut world = World::default();
657 run_system(&mut world, sys);
658 }
659
660 #[test]
661 fn any_of_with_entity_and_mut() {
662 fn sys(_: Query<AnyOf<(Entity, &mut A)>>) {}
663 let mut world = World::default();
664 run_system(&mut world, sys);
665 }
666
667 #[test]
668 fn any_of_with_empty_and_mut() {
669 fn sys(_: Query<AnyOf<((), &mut A)>>) {}
670 let mut world = World::default();
671 run_system(&mut world, sys);
672 }
673
674 #[test]
675 #[should_panic = "error[B0001]"]
676 fn any_of_has_no_filter_with() {
677 fn sys(_: Query<(AnyOf<(&A, ())>, &mut B)>, _: Query<&mut B, Without<A>>) {}
678 let mut world = World::default();
679 run_system(&mut world, sys);
680 }
681
682 #[test]
683 #[should_panic]
684 fn any_of_with_conflicting() {
685 fn sys(_: Query<AnyOf<(&mut A, &mut A)>>) {}
686 let mut world = World::default();
687 run_system(&mut world, sys);
688 }
689
690 #[test]
691 fn any_of_has_filter_with_when_both_have_it() {
692 fn sys(_: Query<(AnyOf<(&A, &A)>, &mut B)>, _: Query<&mut B, Without<A>>) {}
693 let mut world = World::default();
694 run_system(&mut world, sys);
695 }
696
697 #[test]
698 fn any_of_doesnt_remove_unrelated_filter_with() {
699 fn sys(_: Query<(AnyOf<(&A, ())>, &mut B, &A)>, _: Query<&mut B, Without<A>>) {}
700 let mut world = World::default();
701 run_system(&mut world, sys);
702 }
703
704 #[test]
705 fn any_of_and_without() {
706 fn sys(_: Query<(AnyOf<(&A, &B)>, &mut C)>, _: Query<&mut C, (Without<A>, Without<B>)>) {}
707 let mut world = World::default();
708 run_system(&mut world, sys);
709 }
710
711 #[test]
712 #[should_panic = "error[B0001]"]
713 fn or_has_no_filter_with() {
714 fn sys(_: Query<&mut B, Or<(With<A>, With<B>)>>, _: Query<&mut B, Without<A>>) {}
715 let mut world = World::default();
716 run_system(&mut world, sys);
717 }
718
719 #[test]
720 fn or_has_filter_with_when_both_have_it() {
721 fn sys(_: Query<&mut B, Or<(With<A>, With<A>)>>, _: Query<&mut B, Without<A>>) {}
722 let mut world = World::default();
723 run_system(&mut world, sys);
724 }
725
726 #[test]
727 fn or_has_filter_with() {
728 fn sys(
729 _: Query<&mut C, Or<(With<A>, With<B>)>>,
730 _: Query<&mut C, (Without<A>, Without<B>)>,
731 ) {
732 }
733 let mut world = World::default();
734 run_system(&mut world, sys);
735 }
736
737 #[test]
738 fn or_expanded_with_and_without_common() {
739 fn sys(_: Query<&mut D, (With<A>, Or<(With<B>, With<C>)>)>, _: Query<&mut D, Without<A>>) {}
740 let mut world = World::default();
741 run_system(&mut world, sys);
742 }
743
744 #[test]
745 fn or_expanded_nested_with_and_without_common() {
746 fn sys(
747 _: Query<&mut E, (Or<((With<B>, With<C>), (With<C>, With<D>))>, With<A>)>,
748 _: Query<&mut E, (Without<B>, Without<D>)>,
749 ) {
750 }
751 let mut world = World::default();
752 run_system(&mut world, sys);
753 }
754
755 #[test]
756 #[should_panic = "error[B0001]"]
757 fn or_expanded_nested_with_and_disjoint_without() {
758 fn sys(
759 _: Query<&mut E, (Or<((With<B>, With<C>), (With<C>, With<D>))>, With<A>)>,
760 _: Query<&mut E, Without<D>>,
761 ) {
762 }
763 let mut world = World::default();
764 run_system(&mut world, sys);
765 }
766
767 #[test]
768 #[should_panic = "error[B0001]"]
769 fn or_expanded_nested_or_with_and_disjoint_without() {
770 fn sys(
771 _: Query<&mut D, Or<(Or<(With<A>, With<B>)>, Or<(With<A>, With<C>)>)>>,
772 _: Query<&mut D, Without<A>>,
773 ) {
774 }
775 let mut world = World::default();
776 run_system(&mut world, sys);
777 }
778
779 #[test]
780 fn or_expanded_nested_with_and_common_nested_without() {
781 fn sys(
782 _: Query<&mut D, Or<((With<A>, With<B>), (With<B>, With<C>))>>,
783 _: Query<&mut D, Or<(Without<D>, Without<B>)>>,
784 ) {
785 }
786 let mut world = World::default();
787 run_system(&mut world, sys);
788 }
789
790 #[test]
791 fn or_with_without_and_compatible_with_without() {
792 fn sys(
793 _: Query<&mut C, Or<(With<A>, Without<B>)>>,
794 _: Query<&mut C, (With<B>, Without<A>)>,
795 ) {
796 }
797 let mut world = World::default();
798 run_system(&mut world, sys);
799 }
800
801 #[test]
802 #[should_panic = "error[B0001]"]
803 fn with_and_disjoint_or_empty_without() {
804 fn sys(_: Query<&mut B, With<A>>, _: Query<&mut B, Or<((), Without<A>)>>) {}
805 let mut world = World::default();
806 run_system(&mut world, sys);
807 }
808
809 #[test]
810 #[should_panic = "error[B0001]"]
811 fn or_expanded_with_and_disjoint_nested_without() {
812 fn sys(
813 _: Query<&mut D, Or<(With<A>, With<B>)>>,
814 _: Query<&mut D, Or<(Without<A>, Without<B>)>>,
815 ) {
816 }
817 let mut world = World::default();
818 run_system(&mut world, sys);
819 }
820
821 #[test]
822 #[should_panic = "error[B0001]"]
823 fn or_expanded_nested_with_and_disjoint_nested_without() {
824 fn sys(
825 _: Query<&mut D, Or<((With<A>, With<B>), (With<B>, With<C>))>>,
826 _: Query<&mut D, Or<(Without<A>, Without<B>)>>,
827 ) {
828 }
829 let mut world = World::default();
830 run_system(&mut world, sys);
831 }
832
833 #[test]
834 fn or_doesnt_remove_unrelated_filter_with() {
835 fn sys(_: Query<&mut B, (Or<(With<A>, With<B>)>, With<A>)>, _: Query<&mut B, Without<A>>) {}
836 let mut world = World::default();
837 run_system(&mut world, sys);
838 }
839
840 #[test]
841 #[should_panic]
842 fn conflicting_query_mut_system() {
843 fn sys(_q1: Query<&mut A>, _q2: Query<&mut A>) {}
844
845 let mut world = World::default();
846 run_system(&mut world, sys);
847 }
848
849 #[test]
850 fn disjoint_query_mut_system() {
851 fn sys(_q1: Query<&mut A, With<B>>, _q2: Query<&mut A, Without<B>>) {}
852
853 let mut world = World::default();
854 run_system(&mut world, sys);
855 }
856
857 #[test]
858 fn disjoint_query_mut_read_component_system() {
859 fn sys(_q1: Query<(&mut A, &B)>, _q2: Query<&mut A, Without<B>>) {}
860
861 let mut world = World::default();
862 run_system(&mut world, sys);
863 }
864
865 #[test]
866 #[should_panic]
867 fn conflicting_query_immut_system() {
868 fn sys(_q1: Query<&A>, _q2: Query<&mut A>) {}
869
870 let mut world = World::default();
871 run_system(&mut world, sys);
872 }
873
874 #[test]
875 #[should_panic]
876 fn changed_trackers_or_conflict() {
877 fn sys(_: Query<&mut A>, _: Query<(), Or<(Changed<A>,)>>) {}
878
879 let mut world = World::default();
880 run_system(&mut world, sys);
881 }
882
883 #[test]
884 fn query_set_system() {
885 fn sys(mut _set: ParamSet<(Query<&mut A>, Query<&A>)>) {}
886 let mut world = World::default();
887 run_system(&mut world, sys);
888 }
889
890 #[test]
891 #[should_panic]
892 fn conflicting_query_with_query_set_system() {
893 fn sys(_query: Query<&mut A>, _set: ParamSet<(Query<&mut A>, Query<&B>)>) {}
894
895 let mut world = World::default();
896 run_system(&mut world, sys);
897 }
898
899 #[test]
900 #[should_panic]
901 fn conflicting_query_sets_system() {
902 fn sys(_set_1: ParamSet<(Query<&mut A>,)>, _set_2: ParamSet<(Query<&mut A>, Query<&B>)>) {}
903
904 let mut world = World::default();
905 run_system(&mut world, sys);
906 }
907
908 #[derive(Default, Resource)]
909 struct BufferRes {
910 _buffer: Vec<u8>,
911 }
912
913 fn test_for_conflicting_resources<Marker, S: IntoSystem<(), (), Marker>>(sys: S) {
914 let mut world = World::default();
915 world.insert_resource(BufferRes::default());
916 world.insert_resource(A);
917 world.insert_resource(B);
918 run_system(&mut world, sys);
919 }
920
921 #[test]
922 #[should_panic]
923 fn conflicting_system_resources() {
924 fn sys(_: ResMut<BufferRes>, _: Res<BufferRes>) {}
925 test_for_conflicting_resources(sys);
926 }
927
928 #[test]
929 #[should_panic]
930 fn conflicting_system_resources_reverse_order() {
931 fn sys(_: Res<BufferRes>, _: ResMut<BufferRes>) {}
932 test_for_conflicting_resources(sys);
933 }
934
935 #[test]
936 #[should_panic]
937 fn conflicting_system_resources_multiple_mutable() {
938 fn sys(_: ResMut<BufferRes>, _: ResMut<BufferRes>) {}
939 test_for_conflicting_resources(sys);
940 }
941
942 #[test]
943 fn nonconflicting_system_resources() {
944 fn sys(_: Local<BufferRes>, _: ResMut<BufferRes>, _: Local<A>, _: ResMut<A>) {}
945 test_for_conflicting_resources(sys);
946 }
947
948 #[test]
949 fn local_system() {
950 let mut world = World::default();
951 world.insert_resource(ProtoFoo { value: 1 });
952 world.insert_resource(SystemRan::No);
953
954 struct Foo {
955 value: u32,
956 }
957
958 #[derive(Resource)]
959 struct ProtoFoo {
960 value: u32,
961 }
962
963 impl FromWorld for Foo {
964 fn from_world(world: &mut World) -> Self {
965 Foo {
966 value: world.resource::<ProtoFoo>().value + 1,
967 }
968 }
969 }
970
971 fn sys(local: Local<Foo>, mut system_ran: ResMut<SystemRan>) {
972 assert_eq!(local.value, 2);
973 *system_ran = SystemRan::Yes;
974 }
975
976 run_system(&mut world, sys);
977
978 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
980 }
981
982 #[test]
983 #[expect(
984 dead_code,
985 reason = "The `NotSend1` and `NotSend2` structs is used to verify that a system will run, even if the system params include a non-Send resource. As such, the inner value doesn't matter."
986 )]
987 fn non_send_option_system() {
988 let mut world = World::default();
989
990 world.insert_resource(SystemRan::No);
991 struct NotSend1(alloc::rc::Rc<i32>);
995 struct NotSend2(alloc::rc::Rc<i32>);
996 world.insert_non_send_resource(NotSend1(alloc::rc::Rc::new(0)));
997
998 fn sys(
999 op: Option<NonSend<NotSend1>>,
1000 mut _op2: Option<NonSendMut<NotSend2>>,
1001 mut system_ran: ResMut<SystemRan>,
1002 ) {
1003 op.expect("NonSend should exist");
1004 *system_ran = SystemRan::Yes;
1005 }
1006
1007 run_system(&mut world, sys);
1008 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1010 }
1011
1012 #[test]
1013 #[expect(
1014 dead_code,
1015 reason = "The `NotSend1` and `NotSend2` structs are used to verify that a system will run, even if the system params include a non-Send resource. As such, the inner value doesn't matter."
1016 )]
1017 fn non_send_system() {
1018 let mut world = World::default();
1019
1020 world.insert_resource(SystemRan::No);
1021 struct NotSend1(alloc::rc::Rc<i32>);
1022 struct NotSend2(alloc::rc::Rc<i32>);
1023
1024 world.insert_non_send_resource(NotSend1(alloc::rc::Rc::new(1)));
1025 world.insert_non_send_resource(NotSend2(alloc::rc::Rc::new(2)));
1026
1027 fn sys(
1028 _op: NonSend<NotSend1>,
1029 mut _op2: NonSendMut<NotSend2>,
1030 mut system_ran: ResMut<SystemRan>,
1031 ) {
1032 *system_ran = SystemRan::Yes;
1033 }
1034
1035 run_system(&mut world, sys);
1036 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1037 }
1038
1039 #[test]
1040 fn removal_tracking() {
1041 let mut world = World::new();
1042
1043 let entity_to_despawn = world.spawn(W(1)).id();
1044 let entity_to_remove_w_from = world.spawn(W(2)).id();
1045 let spurious_entity = world.spawn_empty().id();
1046
1047 #[derive(Resource)]
1049 struct Despawned(Entity);
1050 world.insert_resource(Despawned(entity_to_despawn));
1051
1052 #[derive(Resource)]
1053 struct Removed(Entity);
1054 world.insert_resource(Removed(entity_to_remove_w_from));
1055
1056 #[derive(Default, Resource)]
1058 struct NSystems(usize);
1059 world.insert_resource(NSystems::default());
1060
1061 world.entity_mut(entity_to_despawn).despawn();
1063 world.entity_mut(spurious_entity).despawn();
1064
1065 fn validate_despawn(
1066 mut removed_i32: RemovedComponents<W<i32>>,
1067 despawned: Res<Despawned>,
1068 mut n_systems: ResMut<NSystems>,
1069 ) {
1070 assert_eq!(
1071 removed_i32.read().collect::<Vec<_>>(),
1072 &[despawned.0],
1073 "despawning causes the correct entity to show up in the 'RemovedComponent' system parameter."
1074 );
1075
1076 n_systems.0 += 1;
1077 }
1078
1079 run_system(&mut world, validate_despawn);
1080
1081 world.clear_trackers();
1084
1085 world.spawn(W(3));
1087 world.spawn(W(4));
1088 world.entity_mut(entity_to_remove_w_from).remove::<W<i32>>();
1089
1090 fn validate_remove(
1091 mut removed_i32: RemovedComponents<W<i32>>,
1092 despawned: Res<Despawned>,
1093 removed: Res<Removed>,
1094 mut n_systems: ResMut<NSystems>,
1095 ) {
1096 assert_eq!(
1099 removed_i32.read().collect::<Vec<_>>(),
1100 &[despawned.0, removed.0],
1101 "removing a component causes the correct entity to show up in the 'RemovedComponent' system parameter."
1102 );
1103
1104 n_systems.0 += 1;
1105 }
1106
1107 run_system(&mut world, validate_remove);
1108
1109 assert_eq!(world.resource::<NSystems>().0, 2);
1111 }
1112
1113 #[test]
1114 fn world_collections_system() {
1115 let mut world = World::default();
1116 world.insert_resource(SystemRan::No);
1117 world.spawn((W(42), W(true)));
1118 fn sys(
1119 archetypes: &Archetypes,
1120 components: &Components,
1121 entities: &Entities,
1122 bundles: &Bundles,
1123 query: Query<Entity, With<W<i32>>>,
1124 mut system_ran: ResMut<SystemRan>,
1125 ) {
1126 assert_eq!(query.iter().count(), 1, "entity exists");
1127 for entity in &query {
1128 let location = entities.get(entity).unwrap();
1129 let archetype = archetypes.get(location.archetype_id).unwrap();
1130 let archetype_components = archetype.components();
1131 let bundle_id = bundles
1132 .get_id(TypeId::of::<(W<i32>, W<bool>)>())
1133 .expect("Bundle used to spawn entity should exist");
1134 let bundle_info = bundles.get(bundle_id).unwrap();
1135 let mut bundle_components = bundle_info.contributed_components().to_vec();
1136 bundle_components.sort();
1137 for component_id in &bundle_components {
1138 assert!(
1139 components.get_info(*component_id).is_some(),
1140 "every bundle component exists in Components"
1141 );
1142 }
1143 assert_eq!(
1144 bundle_components, archetype_components,
1145 "entity's bundle components exactly match entity's archetype components"
1146 );
1147 }
1148 *system_ran = SystemRan::Yes;
1149 }
1150
1151 run_system(&mut world, sys);
1152
1153 assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1155 }
1156
1157 #[test]
1158 fn get_system_conflicts() {
1159 fn sys_x(_: Res<A>, _: Res<B>, _: Query<(&C, &D)>) {}
1160
1161 fn sys_y(_: Res<A>, _: ResMut<B>, _: Query<(&C, &mut D)>) {}
1162
1163 let mut world = World::default();
1164 let mut x = IntoSystem::into_system(sys_x);
1165 let mut y = IntoSystem::into_system(sys_y);
1166 let x_access = x.initialize(&mut world);
1167 let y_access = y.initialize(&mut world);
1168
1169 let conflicts = x_access.get_conflicts(&y_access);
1170 let b_id = world
1171 .components()
1172 .get_resource_id(TypeId::of::<B>())
1173 .unwrap();
1174 let d_id = world.components().get_id(TypeId::of::<D>()).unwrap();
1175 assert_eq!(conflicts, vec![b_id, d_id].into());
1176 }
1177
1178 #[test]
1179 fn query_is_empty() {
1180 fn without_filter(not_empty: Query<&A>, empty: Query<&B>) {
1181 assert!(!not_empty.is_empty());
1182 assert!(empty.is_empty());
1183 }
1184
1185 fn with_filter(not_empty: Query<&A, With<C>>, empty: Query<&A, With<D>>) {
1186 assert!(!not_empty.is_empty());
1187 assert!(empty.is_empty());
1188 }
1189
1190 let mut world = World::default();
1191 world.spawn(A).insert(C);
1192
1193 let mut without_filter = IntoSystem::into_system(without_filter);
1194 without_filter.initialize(&mut world);
1195 without_filter.run((), &mut world).unwrap();
1196
1197 let mut with_filter = IntoSystem::into_system(with_filter);
1198 with_filter.initialize(&mut world);
1199 with_filter.run((), &mut world).unwrap();
1200 }
1201
1202 #[test]
1203 fn can_have_16_parameters() {
1204 fn sys_x(
1205 _: Res<A>,
1206 _: Res<B>,
1207 _: Res<C>,
1208 _: Res<D>,
1209 _: Res<E>,
1210 _: Res<F>,
1211 _: Query<&A>,
1212 _: Query<&B>,
1213 _: Query<&C>,
1214 _: Query<&D>,
1215 _: Query<&E>,
1216 _: Query<&F>,
1217 _: Query<(&A, &B)>,
1218 _: Query<(&C, &D)>,
1219 _: Query<(&E, &F)>,
1220 ) {
1221 }
1222 fn sys_y(
1223 _: (
1224 Res<A>,
1225 Res<B>,
1226 Res<C>,
1227 Res<D>,
1228 Res<E>,
1229 Res<F>,
1230 Query<&A>,
1231 Query<&B>,
1232 Query<&C>,
1233 Query<&D>,
1234 Query<&E>,
1235 Query<&F>,
1236 Query<(&A, &B)>,
1237 Query<(&C, &D)>,
1238 Query<(&E, &F)>,
1239 ),
1240 ) {
1241 }
1242 let mut world = World::default();
1243 let mut x = IntoSystem::into_system(sys_x);
1244 let mut y = IntoSystem::into_system(sys_y);
1245 x.initialize(&mut world);
1246 y.initialize(&mut world);
1247 }
1248
1249 #[test]
1250 fn read_system_state() {
1251 #[derive(Eq, PartialEq, Debug, Resource)]
1252 struct A(usize);
1253
1254 #[derive(Component, Eq, PartialEq, Debug)]
1255 struct B(usize);
1256
1257 let mut world = World::default();
1258 world.insert_resource(A(42));
1259 world.spawn(B(7));
1260
1261 let mut system_state: SystemState<(
1262 Res<A>,
1263 Option<Single<&B>>,
1264 ParamSet<(Query<&C>, Query<&D>)>,
1265 )> = SystemState::new(&mut world);
1266 let (a, query, _) = system_state.get(&world);
1267 assert_eq!(*a, A(42), "returned resource matches initial value");
1268 assert_eq!(
1269 **query.unwrap(),
1270 B(7),
1271 "returned component matches initial value"
1272 );
1273 }
1274
1275 #[test]
1276 fn write_system_state() {
1277 #[derive(Resource, Eq, PartialEq, Debug)]
1278 struct A(usize);
1279
1280 #[derive(Component, Eq, PartialEq, Debug)]
1281 struct B(usize);
1282
1283 let mut world = World::default();
1284 world.insert_resource(A(42));
1285 world.spawn(B(7));
1286
1287 let mut system_state: SystemState<(ResMut<A>, Option<Single<&mut B>>)> =
1288 SystemState::new(&mut world);
1289
1290 let (a, query) = system_state.get_mut(&mut world);
1294 assert_eq!(*a, A(42), "returned resource matches initial value");
1295 assert_eq!(
1296 **query.unwrap(),
1297 B(7),
1298 "returned component matches initial value"
1299 );
1300 }
1301
1302 #[test]
1303 fn system_state_change_detection() {
1304 #[derive(Component, Eq, PartialEq, Debug)]
1305 struct A(usize);
1306
1307 let mut world = World::default();
1308 let entity = world.spawn(A(1)).id();
1309
1310 let mut system_state: SystemState<Option<Single<&A, Changed<A>>>> =
1311 SystemState::new(&mut world);
1312 {
1313 let query = system_state.get(&world);
1314 assert_eq!(**query.unwrap(), A(1));
1315 }
1316
1317 {
1318 let query = system_state.get(&world);
1319 assert!(query.is_none());
1320 }
1321
1322 world.entity_mut(entity).get_mut::<A>().unwrap().0 = 2;
1323 {
1324 let query = system_state.get(&world);
1325 assert_eq!(**query.unwrap(), A(2));
1326 }
1327 }
1328
1329 #[test]
1330 fn system_state_spawned() {
1331 let mut world = World::default();
1332 world.spawn_empty();
1333 let spawn_tick = world.change_tick();
1334
1335 let mut system_state: SystemState<Option<Single<SpawnDetails, Spawned>>> =
1336 SystemState::new(&mut world);
1337 {
1338 let query = system_state.get(&world);
1339 assert_eq!(query.unwrap().spawn_tick(), spawn_tick);
1340 }
1341
1342 {
1343 let query = system_state.get(&world);
1344 assert!(query.is_none());
1345 }
1346 }
1347
1348 #[test]
1349 #[should_panic]
1350 fn system_state_invalid_world() {
1351 let mut world = World::default();
1352 let mut system_state = SystemState::<Query<&A>>::new(&mut world);
1353 let mismatched_world = World::default();
1354 system_state.get(&mismatched_world);
1355 }
1356
1357 #[test]
1358 fn system_state_archetype_update() {
1359 #[derive(Component, Eq, PartialEq, Debug)]
1360 struct A(usize);
1361
1362 #[derive(Component, Eq, PartialEq, Debug)]
1363 struct B(usize);
1364
1365 let mut world = World::default();
1366 world.spawn(A(1));
1367
1368 let mut system_state = SystemState::<Query<&A>>::new(&mut world);
1369 {
1370 let query = system_state.get(&world);
1371 assert_eq!(
1372 query.iter().collect::<Vec<_>>(),
1373 vec![&A(1)],
1374 "exactly one component returned"
1375 );
1376 }
1377
1378 world.spawn((A(2), B(2)));
1379 {
1380 let query = system_state.get(&world);
1381 assert_eq!(
1382 query.iter().collect::<Vec<_>>(),
1383 vec![&A(1), &A(2)],
1384 "components from both archetypes returned"
1385 );
1386 }
1387 }
1388
1389 #[test]
1390 #[expect(
1391 dead_code,
1392 reason = "This test exists to show that read-only world-only queries can return data that lives as long as `'world`."
1393 )]
1394 fn long_life_test() {
1395 struct Holder<'w> {
1396 value: &'w A,
1397 }
1398
1399 struct State {
1400 state: SystemState<Res<'static, A>>,
1401 state_q: SystemState<Query<'static, 'static, &'static A>>,
1402 }
1403
1404 impl State {
1405 fn hold_res<'w>(&mut self, world: &'w World) -> Holder<'w> {
1406 let a = self.state.get(world);
1407 Holder {
1408 value: a.into_inner(),
1409 }
1410 }
1411 fn hold_component<'w>(&mut self, world: &'w World, entity: Entity) -> Holder<'w> {
1412 let q = self.state_q.get(world);
1413 let a = q.get_inner(entity).unwrap();
1414 Holder { value: a }
1415 }
1416 fn hold_components<'w>(&mut self, world: &'w World) -> Vec<Holder<'w>> {
1417 let mut components = Vec::new();
1418 let q = self.state_q.get(world);
1419 for a in q.iter_inner() {
1420 components.push(Holder { value: a });
1421 }
1422 components
1423 }
1424 }
1425 }
1426
1427 #[test]
1428 fn immutable_mut_test() {
1429 #[derive(Component, Eq, PartialEq, Debug, Clone, Copy)]
1430 struct A(usize);
1431
1432 let mut world = World::default();
1433 world.spawn(A(1));
1434 world.spawn(A(2));
1435
1436 let mut system_state = SystemState::<Query<&mut A>>::new(&mut world);
1437 {
1438 let mut query = system_state.get_mut(&mut world);
1439 assert_eq!(
1440 query.iter_mut().map(|m| *m).collect::<Vec<A>>(),
1441 vec![A(1), A(2)],
1442 "both components returned by iter_mut of &mut"
1443 );
1444 assert_eq!(
1445 query.iter().collect::<Vec<&A>>(),
1446 vec![&A(1), &A(2)],
1447 "both components returned by iter of &mut"
1448 );
1449 }
1450 }
1451
1452 #[test]
1453 fn convert_mut_to_immut() {
1454 {
1455 let mut world = World::new();
1456
1457 fn mutable_query(mut query: Query<&mut A>) {
1458 for _ in &mut query {}
1459
1460 immutable_query(query.as_readonly());
1461 }
1462
1463 fn immutable_query(_: Query<&A>) {}
1464
1465 let mut sys = IntoSystem::into_system(mutable_query);
1466 sys.initialize(&mut world);
1467 }
1468
1469 {
1470 let mut world = World::new();
1471
1472 fn mutable_query(mut query: Query<Option<&mut A>>) {
1473 for _ in &mut query {}
1474
1475 immutable_query(query.as_readonly());
1476 }
1477
1478 fn immutable_query(_: Query<Option<&A>>) {}
1479
1480 let mut sys = IntoSystem::into_system(mutable_query);
1481 sys.initialize(&mut world);
1482 }
1483
1484 {
1485 let mut world = World::new();
1486
1487 fn mutable_query(mut query: Query<(&mut A, &B)>) {
1488 for _ in &mut query {}
1489
1490 immutable_query(query.as_readonly());
1491 }
1492
1493 fn immutable_query(_: Query<(&A, &B)>) {}
1494
1495 let mut sys = IntoSystem::into_system(mutable_query);
1496 sys.initialize(&mut world);
1497 }
1498
1499 {
1500 let mut world = World::new();
1501
1502 fn mutable_query(mut query: Query<(&mut A, &mut B)>) {
1503 for _ in &mut query {}
1504
1505 immutable_query(query.as_readonly());
1506 }
1507
1508 fn immutable_query(_: Query<(&A, &B)>) {}
1509
1510 let mut sys = IntoSystem::into_system(mutable_query);
1511 sys.initialize(&mut world);
1512 }
1513
1514 {
1515 let mut world = World::new();
1516
1517 fn mutable_query(mut query: Query<(&mut A, &mut B), With<C>>) {
1518 for _ in &mut query {}
1519
1520 immutable_query(query.as_readonly());
1521 }
1522
1523 fn immutable_query(_: Query<(&A, &B), With<C>>) {}
1524
1525 let mut sys = IntoSystem::into_system(mutable_query);
1526 sys.initialize(&mut world);
1527 }
1528
1529 {
1530 let mut world = World::new();
1531
1532 fn mutable_query(mut query: Query<(&mut A, &mut B), Without<C>>) {
1533 for _ in &mut query {}
1534
1535 immutable_query(query.as_readonly());
1536 }
1537
1538 fn immutable_query(_: Query<(&A, &B), Without<C>>) {}
1539
1540 let mut sys = IntoSystem::into_system(mutable_query);
1541 sys.initialize(&mut world);
1542 }
1543
1544 {
1545 let mut world = World::new();
1546
1547 fn mutable_query(mut query: Query<(&mut A, &mut B), Added<C>>) {
1548 for _ in &mut query {}
1549
1550 immutable_query(query.as_readonly());
1551 }
1552
1553 fn immutable_query(_: Query<(&A, &B), Added<C>>) {}
1554
1555 let mut sys = IntoSystem::into_system(mutable_query);
1556 sys.initialize(&mut world);
1557 }
1558
1559 {
1560 let mut world = World::new();
1561
1562 fn mutable_query(mut query: Query<(&mut A, &mut B), Changed<C>>) {
1563 for _ in &mut query {}
1564
1565 immutable_query(query.as_readonly());
1566 }
1567
1568 fn immutable_query(_: Query<(&A, &B), Changed<C>>) {}
1569
1570 let mut sys = IntoSystem::into_system(mutable_query);
1571 sys.initialize(&mut world);
1572 }
1573
1574 {
1575 let mut world = World::new();
1576
1577 fn mutable_query(mut query: Query<(&mut A, &mut B, SpawnDetails), Spawned>) {
1578 for _ in &mut query {}
1579
1580 immutable_query(query.as_readonly());
1581 }
1582
1583 fn immutable_query(_: Query<(&A, &B, SpawnDetails), Spawned>) {}
1584
1585 let mut sys = IntoSystem::into_system(mutable_query);
1586 sys.initialize(&mut world);
1587 }
1588 }
1589
1590 #[test]
1591 fn commands_param_set() {
1592 let mut world = World::new();
1594 let entity = world.spawn_empty().id();
1595
1596 run_system(
1597 &mut world,
1598 move |mut commands_set: ParamSet<(Commands, Commands)>| {
1599 commands_set.p0().entity(entity).insert(A);
1600 commands_set.p1().entity(entity).insert(B);
1601 },
1602 );
1603
1604 let entity = world.entity(entity);
1605 assert!(entity.contains::<A>());
1606 assert!(entity.contains::<B>());
1607 }
1608
1609 #[test]
1610 fn into_iter_impl() {
1611 let mut world = World::new();
1612 world.spawn(W(42u32));
1613 run_system(&mut world, |mut q: Query<&mut W<u32>>| {
1614 for mut a in &mut q {
1615 assert_eq!(a.0, 42);
1616 a.0 = 0;
1617 }
1618 for a in &q {
1619 assert_eq!(a.0, 0);
1620 }
1621 });
1622 }
1623
1624 #[test]
1625 #[should_panic]
1626 fn assert_system_does_not_conflict() {
1627 fn system(_query: Query<(&mut W<u32>, &mut W<u32>)>) {}
1628 super::assert_system_does_not_conflict(system);
1629 }
1630
1631 #[test]
1632 #[should_panic]
1633 fn assert_world_and_entity_mut_system_does_conflict_first() {
1634 fn system(_query: &World, _q2: Query<EntityMut>) {}
1635 super::assert_system_does_not_conflict(system);
1636 }
1637
1638 #[test]
1639 #[should_panic]
1640 fn assert_world_and_entity_mut_system_does_conflict_second() {
1641 fn system(_: Query<EntityMut>, _: &World) {}
1642 super::assert_system_does_not_conflict(system);
1643 }
1644
1645 #[test]
1646 #[should_panic]
1647 fn assert_entity_ref_and_entity_mut_system_does_conflict() {
1648 fn system(_query: Query<EntityRef>, _q2: Query<EntityMut>) {}
1649 super::assert_system_does_not_conflict(system);
1650 }
1651
1652 #[test]
1653 #[should_panic]
1654 fn assert_entity_mut_system_does_conflict() {
1655 fn system(_query: Query<EntityMut>, _q2: Query<EntityMut>) {}
1656 super::assert_system_does_not_conflict(system);
1657 }
1658
1659 #[test]
1660 #[should_panic]
1661 fn assert_deferred_world_and_entity_ref_system_does_conflict_first() {
1662 fn system(_world: DeferredWorld, _query: Query<EntityRef>) {}
1663 super::assert_system_does_not_conflict(system);
1664 }
1665
1666 #[test]
1667 #[should_panic]
1668 fn assert_deferred_world_and_entity_ref_system_does_conflict_second() {
1669 fn system(_query: Query<EntityRef>, _world: DeferredWorld) {}
1670 super::assert_system_does_not_conflict(system);
1671 }
1672
1673 #[test]
1674 fn assert_deferred_world_and_empty_query_does_not_conflict_first() {
1675 fn system(_world: DeferredWorld, _query: Query<Entity>) {}
1676 super::assert_system_does_not_conflict(system);
1677 }
1678
1679 #[test]
1680 fn assert_deferred_world_and_empty_query_does_not_conflict_second() {
1681 fn system(_query: Query<Entity>, _world: DeferredWorld) {}
1682 super::assert_system_does_not_conflict(system);
1683 }
1684
1685 #[test]
1686 #[should_panic]
1687 fn panic_inside_system() {
1688 let mut world = World::new();
1689 let system: fn() = || {
1690 panic!("this system panics");
1691 };
1692 run_system(&mut world, system);
1693 }
1694
1695 #[test]
1696 fn assert_systems() {
1697 use core::str::FromStr;
1698
1699 use crate::{prelude::*, system::assert_is_system};
1700
1701 fn returning<T>() -> T {
1703 unimplemented!()
1704 }
1705
1706 fn exclusive_in_out<A, B>(_: In<A>, _: &mut World) -> B {
1708 unimplemented!()
1709 }
1710
1711 fn static_system_param(_: StaticSystemParam<Query<'static, 'static, &W<u32>>>) {
1712 unimplemented!()
1713 }
1714
1715 fn exclusive_with_state(
1716 _: &mut World,
1717 _: Local<bool>,
1718 _: (&mut QueryState<&W<i32>>, &mut SystemState<Query<&W<u32>>>),
1719 _: (),
1720 ) {
1721 unimplemented!()
1722 }
1723
1724 fn not(In(val): In<bool>) -> bool {
1725 !val
1726 }
1727
1728 assert_is_system(returning::<Result<u32, std::io::Error>>.map(Result::unwrap));
1729 assert_is_system(returning::<Option<()>>.map(drop));
1730 assert_is_system(returning::<&str>.map(u64::from_str).map(Result::unwrap));
1731 assert_is_system(static_system_param);
1732 assert_is_system(
1733 exclusive_in_out::<(), Result<(), std::io::Error>>.map(|_out| {
1734 #[cfg(feature = "trace")]
1735 if let Err(error) = _out {
1736 tracing::error!("{}", error);
1737 }
1738 }),
1739 );
1740 assert_is_system(exclusive_with_state);
1741 assert_is_system(returning::<bool>.pipe(exclusive_in_out::<bool, ()>));
1742
1743 returning::<()>.run_if(returning::<bool>.pipe(not));
1744 }
1745
1746 #[test]
1747 fn pipe_change_detection() {
1748 #[derive(Resource, Default)]
1749 struct Flag;
1750
1751 #[derive(Default)]
1752 struct Info {
1753 do_first: bool,
1755 do_second: bool,
1756
1757 first_flag: bool,
1759 second_flag: bool,
1760 }
1761
1762 fn first(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
1763 if flag.is_changed() {
1764 info.first_flag = true;
1765 }
1766 if info.do_first {
1767 *flag = Flag;
1768 }
1769
1770 info
1771 }
1772
1773 fn second(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
1774 if flag.is_changed() {
1775 info.second_flag = true;
1776 }
1777 if info.do_second {
1778 *flag = Flag;
1779 }
1780
1781 info
1782 }
1783
1784 let mut world = World::new();
1785 world.init_resource::<Flag>();
1786 let mut sys = IntoSystem::into_system(first.pipe(second));
1787 sys.initialize(&mut world);
1788
1789 sys.run(default(), &mut world).unwrap();
1790
1791 let info = sys
1793 .run(
1794 Info {
1795 do_first: true,
1796 ..default()
1797 },
1798 &mut world,
1799 )
1800 .unwrap();
1801 assert!(!info.first_flag);
1802 assert!(info.second_flag);
1803
1804 let info1 = sys
1807 .run(
1808 Info {
1809 do_second: true,
1810 ..default()
1811 },
1812 &mut world,
1813 )
1814 .unwrap();
1815 let info2 = sys.run(default(), &mut world).unwrap();
1816 assert!(!info1.first_flag);
1817 assert!(!info1.second_flag);
1818 assert!(info2.first_flag);
1819 assert!(!info2.second_flag);
1820 }
1821
1822 #[test]
1823 fn test_combinator_clone() {
1824 let mut world = World::new();
1825 #[derive(Resource)]
1826 struct A;
1827 #[derive(Resource)]
1828 struct B;
1829 #[derive(Resource, PartialEq, Eq, Debug)]
1830 struct C(i32);
1831
1832 world.insert_resource(A);
1833 world.insert_resource(C(0));
1834 let mut sched = Schedule::default();
1835 sched.add_systems(
1836 (
1837 |mut res: ResMut<C>| {
1838 res.0 += 1;
1839 },
1840 |mut res: ResMut<C>| {
1841 res.0 += 2;
1842 },
1843 )
1844 .distributive_run_if(resource_exists::<A>.or(resource_exists::<B>)),
1845 );
1846 sched.initialize(&mut world).unwrap();
1847 sched.run(&mut world);
1848 assert_eq!(world.get_resource(), Some(&C(3)));
1849 }
1850
1851 #[test]
1852 #[should_panic(
1853 expected = "Encountered an error in system `bevy_ecs::system::tests::simple_fallible_system::sys`: error"
1854 )]
1855 fn simple_fallible_system() {
1856 fn sys() -> Result {
1857 Err("error")?;
1858 Ok(())
1859 }
1860
1861 let mut world = World::new();
1862 run_system(&mut world, sys);
1863 }
1864
1865 #[test]
1866 #[should_panic(
1867 expected = "Encountered an error in system `bevy_ecs::system::tests::simple_fallible_exclusive_system::sys`: error"
1868 )]
1869 fn simple_fallible_exclusive_system() {
1870 fn sys(_world: &mut World) -> Result {
1871 Err("error")?;
1872 Ok(())
1873 }
1874
1875 let mut world = World::new();
1876 run_system(&mut world, sys);
1877 }
1878
1879 #[test]
1893 fn nondiverging_never_trait_impls() {
1894 let mut world = World::new();
1899 let mut schedule = Schedule::default();
1900
1901 fn sys(_query: Query<&Name>) {
1902 todo!()
1903 }
1904
1905 schedule.add_systems(sys);
1906 schedule.add_systems(|_query: Query<&Name>| {});
1907 schedule.add_systems(|_query: Query<&Name>| todo!());
1908 schedule.add_systems(|_query: Query<&Name>| -> () { todo!() });
1909
1910 fn obs(_event: On<Add, Name>) {
1911 todo!()
1912 }
1913
1914 world.add_observer(obs);
1915 world.add_observer(|_event: On<Add, Name>| {});
1916 world.add_observer(|_event: On<Add, Name>| todo!());
1917 world.add_observer(|_event: On<Add, Name>| -> () { todo!() });
1918
1919 fn my_command(_world: &mut World) {
1920 todo!()
1921 }
1922
1923 world.commands().queue(my_command);
1924 world.commands().queue(|_world: &mut World| {});
1925 world.commands().queue(|_world: &mut World| todo!());
1926 world
1927 .commands()
1928 .queue(|_world: &mut World| -> () { todo!() });
1929 }
1930
1931 #[test]
1932 fn with_input() {
1933 fn sys(InMut(v): InMut<usize>) {
1934 *v += 1;
1935 }
1936
1937 let mut world = World::new();
1938 let mut system = IntoSystem::into_system(sys.with_input(42));
1939 system.initialize(&mut world);
1940 system.run((), &mut world).unwrap();
1941 assert_eq!(*system.value(), 43);
1942 }
1943
1944 #[test]
1945 fn with_input_from() {
1946 struct TestData(usize);
1947
1948 impl FromWorld for TestData {
1949 fn from_world(_world: &mut World) -> Self {
1950 Self(5)
1951 }
1952 }
1953
1954 fn sys(InMut(v): InMut<TestData>) {
1955 v.0 += 1;
1956 }
1957
1958 let mut world = World::new();
1959 let mut system = IntoSystem::into_system(sys.with_input_from::<TestData>());
1960 assert!(system.value().is_none());
1961 system.initialize(&mut world);
1962 assert!(system.value().is_some());
1963 system.run((), &mut world).unwrap();
1964 assert_eq!(system.value().unwrap().0, 6);
1965 }
1966}