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