Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/tests/ecs/ambiguity_detection.rs
6595 views
1
//! A test to confirm that `bevy` doesn't regress its system ambiguities count when using [`DefaultPlugins`].
2
//! This is run in CI.
3
//!
4
//! Note that because this test requires rendering, it isn't actually an integration test!
5
//! Instead, it's secretly an example: you can run this test manually using `cargo run --example ambiguity_detection`.
6
7
use bevy::{
8
ecs::schedule::{InternedScheduleLabel, LogLevel, ScheduleBuildSettings},
9
platform::collections::HashMap,
10
prelude::*,
11
render::{pipelined_rendering::PipelinedRenderingPlugin, RenderPlugin},
12
};
13
14
fn main() {
15
let mut app = App::new();
16
app.add_plugins(
17
DefaultPlugins
18
.build()
19
.set(RenderPlugin {
20
// llvmpipe driver can cause segfaults when aborting the binary while pipelines are being
21
// compiled (which happens very quickly in this example since we only run for a single
22
// frame). Synchronous pipeline compilation helps prevent these segfaults as the
23
// rendering thread blocks on these pipeline compilations.
24
synchronous_pipeline_compilation: true,
25
..Default::default()
26
})
27
// We also have to disable pipelined rendering to ensure the test doesn't end while the
28
// rendering frame is still executing in another thread.
29
.disable::<PipelinedRenderingPlugin>(),
30
);
31
32
let main_app = app.main_mut();
33
configure_ambiguity_detection(main_app);
34
35
// Ambiguities in the RenderApp are currently allowed.
36
// Eventually, we should forbid these: see https://github.com/bevyengine/bevy/issues/7386
37
// Uncomment the lines below to show the current ambiguities in the RenderApp.
38
// let sub_app = app.sub_app_mut(bevy_render::RenderApp);
39
// configure_ambiguity_detection(sub_app);
40
41
app.finish();
42
app.cleanup();
43
app.update();
44
45
let main_app_ambiguities = count_ambiguities(app.main());
46
assert_eq!(
47
main_app_ambiguities.total(),
48
0,
49
"Main app has unexpected ambiguities among the following schedules: \n{main_app_ambiguities:#?}.",
50
);
51
}
52
53
/// Contains the number of conflicting systems per schedule.
54
#[derive(Debug, Deref, DerefMut)]
55
struct AmbiguitiesCount(pub HashMap<InternedScheduleLabel, usize>);
56
57
impl AmbiguitiesCount {
58
fn total(&self) -> usize {
59
self.values().sum()
60
}
61
}
62
63
fn configure_ambiguity_detection(sub_app: &mut SubApp) {
64
let mut schedules = sub_app.world_mut().resource_mut::<Schedules>();
65
for (_, schedule) in schedules.iter_mut() {
66
schedule.set_build_settings(ScheduleBuildSettings {
67
// NOTE: you can change this to `LogLevel::Ignore` to easily see the current number of ambiguities.
68
ambiguity_detection: LogLevel::Warn,
69
use_shortnames: false,
70
..default()
71
});
72
}
73
}
74
75
/// Returns the number of conflicting systems per schedule.
76
fn count_ambiguities(sub_app: &SubApp) -> AmbiguitiesCount {
77
let schedules = sub_app.world().resource::<Schedules>();
78
let mut ambiguities = <HashMap<_, _>>::default();
79
for (_, schedule) in schedules.iter() {
80
let ambiguities_in_schedule = schedule.graph().conflicting_systems().len();
81
ambiguities.insert(schedule.label(), ambiguities_in_schedule);
82
}
83
AmbiguitiesCount(ambiguities)
84
}
85
86