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.
This commit is contained in:
JoJoJet 2023-04-13 13:59:29 -04:00 committed by GitHub
parent ff9a178818
commit c37a53d52d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -306,8 +306,15 @@ pub mod adapter {
/// } /// }
/// ``` /// ```
pub fn ignore<T>(In(_): In<T>) {} pub fn ignore<T>(In(_): In<T>) {}
}
#[cfg(test)]
mod tests {
use bevy_utils::default;
use super::adapter::*;
use crate::{self as bevy_ecs, prelude::*, system::PipeSystem};
#[cfg(test)]
#[test] #[test]
fn assert_systems() { fn assert_systems() {
use std::str::FromStr; use std::str::FromStr;
@ -336,4 +343,80 @@ pub mod adapter {
returning::<()>.run_if(returning::<bool>.pipe(not)); returning::<()>.run_if(returning::<bool>.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<Info>, mut flag: ResMut<Flag>) -> Info {
if flag.is_changed() {
info.first_flag = true;
}
if info.do_first {
*flag = Flag;
}
info
}
fn second(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
if flag.is_changed() {
info.second_flag = true;
}
if info.do_second {
*flag = Flag;
}
info
}
let mut world = World::new();
world.init_resource::<Flag>();
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);
}
} }