bevy/tests/ecs/ambiguity_detection.rs
Zachary Harrold 4742f74fc4
Broaden "Check for bevy_internal imports" CI Task (#15333)
# Objective

- Fixes #15319
- Fixes #15317

## Solution

- Updated CI task to check for _any_ `bevy_*` crates, rather than just
`bevy_internal`

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2024-09-20 17:08:37 +00:00

80 lines
3 KiB
Rust

//! A test to confirm that `bevy` doesn't regress its system ambiguities count when using [`DefaultPlugins`].
//! This is run in CI.
//!
//! Note that because this test requires rendering, it isn't actually an integration test!
//! Instead, it's secretly an example: you can run this test manually using `cargo run --example ambiguity_detection`.
use bevy::{
ecs::schedule::{InternedScheduleLabel, LogLevel, ScheduleBuildSettings},
prelude::*,
render::pipelined_rendering::RenderExtractApp,
utils::HashMap,
};
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins);
let main_app = app.main_mut();
configure_ambiguity_detection(main_app);
let render_extract_app = app.sub_app_mut(RenderExtractApp);
configure_ambiguity_detection(render_extract_app);
// Ambiguities in the RenderApp are currently allowed.
// Eventually, we should forbid these: see https://github.com/bevyengine/bevy/issues/7386
// Uncomment the lines below to show the current ambiguities in the RenderApp.
// let sub_app = app.sub_app_mut(bevy_render::RenderApp);
// configure_ambiguity_detection(sub_app);
app.finish();
app.cleanup();
app.update();
let main_app_ambiguities = count_ambiguities(app.main());
assert_eq!(
main_app_ambiguities.total(),
0,
"Main app has unexpected ambiguities among the following schedules: \n{main_app_ambiguities:#?}.",
);
// RenderApp is not checked here, because it is not within the App at this point.
let render_extract_ambiguities = count_ambiguities(app.sub_app(RenderExtractApp));
assert_eq!(
render_extract_ambiguities.total(),
0,
"RenderExtract app has unexpected ambiguities among the following schedules: \n{render_extract_ambiguities:#?}",
);
}
/// Contains the number of conflicting systems per schedule.
#[derive(Debug, Deref, DerefMut)]
struct AmbiguitiesCount(pub HashMap<InternedScheduleLabel, usize>);
impl AmbiguitiesCount {
fn total(&self) -> usize {
self.values().sum()
}
}
fn configure_ambiguity_detection(sub_app: &mut SubApp) {
let mut schedules = sub_app.world_mut().resource_mut::<Schedules>();
for (_, schedule) in schedules.iter_mut() {
schedule.set_build_settings(ScheduleBuildSettings {
// NOTE: you can change this to `LogLevel::Ignore` to easily see the current number of ambiguities.
ambiguity_detection: LogLevel::Warn,
use_shortnames: false,
..default()
});
}
}
/// Returns the number of conflicting systems per schedule.
fn count_ambiguities(sub_app: &SubApp) -> AmbiguitiesCount {
let schedules = sub_app.world().resource::<Schedules>();
let mut ambiguities = HashMap::new();
for (_, schedule) in schedules.iter() {
let ambiguities_in_schedule = schedule.graph().conflicting_systems().len();
ambiguities.insert(schedule.label(), ambiguities_in_schedule);
}
AmbiguitiesCount(ambiguities)
}