From c37a53d52d13ab4a19345698109097440baa054f Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 13 Apr 2023 13:59:29 -0400 Subject: [PATCH] Add a regression test for change detection between piped systems (#8368) # Objective The behavior of change detection within `PipeSystem` is very tricky and subtle, and is not currently covered by any of our tests as far as I'm aware. --- crates/bevy_ecs/src/system/system_piping.rs | 85 ++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/system_piping.rs b/crates/bevy_ecs/src/system/system_piping.rs index dc1f3dc55a..cf3abdb7d4 100644 --- a/crates/bevy_ecs/src/system/system_piping.rs +++ b/crates/bevy_ecs/src/system/system_piping.rs @@ -306,8 +306,15 @@ pub mod adapter { /// } /// ``` pub fn ignore(In(_): In) {} +} + +#[cfg(test)] +mod tests { + use bevy_utils::default; + + use super::adapter::*; + use crate::{self as bevy_ecs, prelude::*, system::PipeSystem}; - #[cfg(test)] #[test] fn assert_systems() { use std::str::FromStr; @@ -336,4 +343,80 @@ pub mod adapter { returning::<()>.run_if(returning::.pipe(not)); } + + #[test] + fn pipe_change_detection() { + #[derive(Resource, Default)] + struct Flag; + + #[derive(Default)] + struct Info { + // If true, the respective system will mutate `Flag`. + do_first: bool, + do_second: bool, + + // Will be set to true if the respective system saw that `Flag` changed. + first_flag: bool, + second_flag: bool, + } + + fn first(In(mut info): In, mut flag: ResMut) -> Info { + if flag.is_changed() { + info.first_flag = true; + } + if info.do_first { + *flag = Flag; + } + + info + } + + fn second(In(mut info): In, mut flag: ResMut) -> Info { + if flag.is_changed() { + info.second_flag = true; + } + if info.do_second { + *flag = Flag; + } + + info + } + + let mut world = World::new(); + world.init_resource::(); + let mut sys = PipeSystem::new( + IntoSystem::into_system(first), + IntoSystem::into_system(second), + "".into(), + ); + sys.initialize(&mut world); + + sys.run(default(), &mut world); + + // The second system should observe a change made in the first system. + let info = sys.run( + Info { + do_first: true, + ..default() + }, + &mut world, + ); + assert!(!info.first_flag); + assert!(info.second_flag); + + // When a change is made in the second system, the first system + // should observe it the next time they are run. + let info1 = sys.run( + Info { + do_second: true, + ..default() + }, + &mut world, + ); + let info2 = sys.run(default(), &mut world); + assert!(!info1.first_flag); + assert!(!info1.second_flag); + assert!(info2.first_flag); + assert!(!info2.second_flag); + } }