Skip to content

Commit 545eebb

Browse files
committed
Create a test to show that an asset can be loaded from a runtime added source.
1 parent b7010aa commit 545eebb

File tree

1 file changed

+112
-21
lines changed

1 file changed

+112
-21
lines changed

crates/bevy_asset/src/lib.rs

Lines changed: 112 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,6 +2657,28 @@ mod tests {
26572657
assert_eq!(get_started_load_count(app.world()), 2);
26582658
}
26592659

2660+
/// A trivial asset loader that just immediately produces a [`TestAsset`].
2661+
struct TrivialLoader;
2662+
2663+
impl AssetLoader for TrivialLoader {
2664+
type Asset = TestAsset;
2665+
type Settings = ();
2666+
type Error = std::io::Error;
2667+
2668+
async fn load(
2669+
&self,
2670+
_reader: &mut dyn Reader,
2671+
_settings: &Self::Settings,
2672+
_load_context: &mut LoadContext<'_>,
2673+
) -> Result<Self::Asset, Self::Error> {
2674+
Ok(TestAsset)
2675+
}
2676+
2677+
fn extensions(&self) -> &[&str] {
2678+
&["txt"]
2679+
}
2680+
}
2681+
26602682
#[test]
26612683
fn get_strong_handle_prevents_reload_when_asset_still_alive() {
26622684
let mut app = App::new();
@@ -2676,27 +2698,6 @@ mod tests {
26762698
))
26772699
.init_asset::<TestAsset>();
26782700

2679-
struct TrivialLoader;
2680-
2681-
impl AssetLoader for TrivialLoader {
2682-
type Asset = TestAsset;
2683-
type Settings = ();
2684-
type Error = std::io::Error;
2685-
2686-
async fn load(
2687-
&self,
2688-
_reader: &mut dyn Reader,
2689-
_settings: &Self::Settings,
2690-
_load_context: &mut LoadContext<'_>,
2691-
) -> Result<Self::Asset, Self::Error> {
2692-
Ok(TestAsset)
2693-
}
2694-
2695-
fn extensions(&self) -> &[&str] {
2696-
&["txt"]
2697-
}
2698-
}
2699-
27002701
app.register_asset_loader(TrivialLoader);
27012702

27022703
let asset_server = app.world().resource::<AssetServer>().clone();
@@ -2739,4 +2740,94 @@ mod tests {
27392740
// assert_eq!(get_started_load_count(app.world()), 1);
27402741
assert_eq!(get_started_load_count(app.world()), 2);
27412742
}
2743+
2744+
// Creates a new asset source that reads from the returned dir.
2745+
fn create_dir_source() -> (AssetSourceBuilder, Dir) {
2746+
let dir = Dir::default();
2747+
let dir_clone = dir.clone();
2748+
(
2749+
AssetSourceBuilder::new(move || {
2750+
Box::new(MemoryAssetReader {
2751+
root: dir_clone.clone(),
2752+
})
2753+
}),
2754+
dir,
2755+
)
2756+
}
2757+
2758+
#[test]
2759+
fn can_load_asset_from_runtime_added_sources() {
2760+
let mut app = App::new();
2761+
let (default_source, _) = create_dir_source();
2762+
app.add_plugins((
2763+
TaskPoolPlugin::default(),
2764+
AssetPlugin {
2765+
default_source: DefaultAssetSource::FromBuilder(Mutex::new(default_source)),
2766+
..Default::default()
2767+
},
2768+
DiagnosticsPlugin,
2769+
));
2770+
2771+
app.init_asset::<TestAsset>()
2772+
.register_asset_loader(TrivialLoader);
2773+
2774+
let asset_server = app.world().resource::<AssetServer>().clone();
2775+
let custom_handle: Handle<TestAsset> = asset_server.load("custom://asset.txt");
2776+
2777+
run_app_until(&mut app, |_| {
2778+
match asset_server.get_load_state(&custom_handle).unwrap() {
2779+
LoadState::Loading => None,
2780+
LoadState::Failed(err) => match err.as_ref() {
2781+
AssetLoadError::MissingAssetSourceError(_) => Some(()),
2782+
err => panic!("Unexpected load error: {err}"),
2783+
},
2784+
err => panic!("Unexpected state for asset load: {err:?}"),
2785+
}
2786+
});
2787+
2788+
// Drop the handle, and let the app update to react to that.
2789+
drop(custom_handle);
2790+
app.update();
2791+
2792+
let (mut custom_source, custom_dir) = create_dir_source();
2793+
custom_dir.insert_asset_text(Path::new("asset.txt"), "");
2794+
2795+
asset_server
2796+
.add_source("custom", &mut custom_source)
2797+
.unwrap();
2798+
2799+
// Now that we have added the "custom" asset source, loading the asset should work!
2800+
let custom_handle: Handle<TestAsset> = asset_server.load("custom://asset.txt");
2801+
run_app_until(&mut app, |_| {
2802+
match asset_server.get_load_state(&custom_handle).unwrap() {
2803+
LoadState::Loading => None,
2804+
LoadState::Loaded => Some(()),
2805+
err => panic!("Unexpected state for asset load: {err:?}"),
2806+
}
2807+
});
2808+
2809+
// Removing the source shouldn't change anything about the asset, so it should still be alive.
2810+
asset_server.remove_source("custom").unwrap();
2811+
app.update();
2812+
assert!(app
2813+
.world()
2814+
.resource::<Assets<TestAsset>>()
2815+
.contains(&custom_handle));
2816+
2817+
drop(custom_handle);
2818+
app.update();
2819+
2820+
// After removing the "custom" asset source, trying to load the asset again should fail.
2821+
let custom_handle: Handle<TestAsset> = asset_server.load("custom://asset.txt");
2822+
run_app_until(&mut app, |_| {
2823+
match asset_server.get_load_state(&custom_handle).unwrap() {
2824+
LoadState::Loading => None,
2825+
LoadState::Failed(err) => match err.as_ref() {
2826+
AssetLoadError::MissingAssetSourceError(_) => Some(()),
2827+
err => panic!("Unexpected load error: {err}"),
2828+
},
2829+
err => panic!("Unexpected state for asset load: {err:?}"),
2830+
}
2831+
});
2832+
}
27422833
}

0 commit comments

Comments
 (0)