From d04208a9f64f9dbfc8a1ddd666973cecd8375f99 Mon Sep 17 00:00:00 2001 From: Lucas Farias Date: Tue, 20 May 2025 14:59:17 -0300 Subject: [PATCH] Add test that reproduces #18808 --- tests/render_asset_leaks.rs | 90 ++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/tests/render_asset_leaks.rs b/tests/render_asset_leaks.rs index 7ad616eae8..18c16b4f31 100644 --- a/tests/render_asset_leaks.rs +++ b/tests/render_asset_leaks.rs @@ -151,6 +151,71 @@ fn check_standard_material_churn_leak() { } } +#[ignore = "FIXME Failing test"] +#[test] +fn check_mesh_churn_insert_leak() { + let mut app = App::new(); + app.add_plugins(( + DefaultPlugins + .build() + .disable::() + .disable::() + .disable::(), + LogDiagnosticsPlugin { + wait_duration: Duration::ZERO, + ..Default::default() + }, + RenderAssetDiagnosticPlugin::::new(" meshes"), + MeshAllocatorDiagnosticPlugin, + )) + .add_systems(Startup, mesh_setup) + .add_systems( + Update, + (churn_using_insert::, crash_on_mesh_leak_detection), + ); + + app.finish(); + app.cleanup(); + + for _ in 0..100 { + app.update(); + } +} + +#[ignore = "FIXME Failing test"] +#[test] +fn check_standard_material_churn_insert_leak() { + let mut app = App::new(); + app.add_plugins(( + DefaultPlugins + .build() + .disable::() + .disable::() + .disable::(), + LogDiagnosticsPlugin { + wait_duration: Duration::ZERO, + ..Default::default() + }, + RenderAssetDiagnosticPlugin::>::new(" materials"), + MaterialAllocatorDiagnosticPlugin::::default(), + )) + .add_systems(Startup, mesh_setup) + .add_systems( + Update, + ( + churn_using_insert::, + crash_on_material_leak_detection::, + ), + ); + + app.finish(); + app.cleanup(); + + for _ in 0..100 { + app.update(); + } +} + #[derive(Resource)] struct Leaker(Vec>); @@ -185,13 +250,23 @@ fn churn(mut assets: ResMut>, mut leaker: ResMut>) } } +fn churn_using_insert(mut assets: ResMut>, leaker: Res>) { + for id in &leaker.0 { + let asset = assets.remove(id.id()).unwrap(); + assets.insert(id.id(), asset); + } +} + fn crash_on_mesh_leak_detection(diagnostic_store: Res) { - if let (Some(render_meshes), Some(allocations)) = ( + if let (Some(render_meshes), Some(slab_size), Some(allocations)) = ( diagnostic_store .get_measurement( &RenderAssetDiagnosticPlugin::::render_asset_diagnostic_path(), ) .filter(|diag| diag.value > 0.), + diagnostic_store + .get_measurement(MeshAllocatorDiagnosticPlugin::slabs_size_diagnostic_path()) + .filter(|diag| diag.value > 0.), diagnostic_store .get_measurement(MeshAllocatorDiagnosticPlugin::allocations_diagnostic_path()) .filter(|diag| diag.value > 0.), @@ -200,20 +275,31 @@ fn crash_on_mesh_leak_detection(diagnostic_store: Res) { allocations.value < render_meshes.value * 10., "Detected leak" ); + assert!( + slab_size.value < (1 << 30) as f64, + "Exceeded 1GB of allocations." + ); } } fn crash_on_material_leak_detection(diagnostic_store: Res) { - if let (Some(materials), Some(allocations)) = ( + if let (Some(materials), Some(slab_size), Some(allocations)) = ( diagnostic_store .get_measurement( &RenderAssetDiagnosticPlugin::>::render_asset_diagnostic_path(), ) .filter(|diag| diag.value > 0.), + diagnostic_store + .get_measurement(&MaterialAllocatorDiagnosticPlugin::::slabs_size_diagnostic_path()) + .filter(|diag| diag.value > 0.), diagnostic_store .get_measurement(&MaterialAllocatorDiagnosticPlugin::::allocations_diagnostic_path()) .filter(|diag| diag.value > 0.), ) { assert!(allocations.value < materials.value * 10., "Detected leak"); + assert!( + slab_size.value < (1 << 30) as f64, + "Exceeded 1GB of allocations." + ); } }