diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index de9dfa5ca583a..c594f0690b75a 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -94,6 +94,9 @@ pub enum ParseAssetPathError { /// Error that occurs when a path string has an [`AssetPath::label`] delimiter `#` with no characters succeeding it. E.g. `file.test#` #[error("Asset label must be at least one character. Either specify the label after the '#' or remove the '#'")] MissingLabel, + // Error that occurs when a path string is empty + #[error("asset path cannot be empty")] + EmptyPath, } impl<'a> AssetPath<'a> { @@ -123,6 +126,7 @@ impl<'a> AssetPath<'a> { /// /// This will return a [`ParseAssetPathError`] if `asset_path` is in an invalid format. pub fn try_parse(asset_path: &'a str) -> Result, ParseAssetPathError> { + let (source, path, label) = Self::parse_internal(asset_path)?; Ok(Self { source: match source { @@ -189,6 +193,10 @@ impl<'a> AssetPath<'a> { } } } + // If string is empty + if asset_path.trim().is_empty() { + return Err(ParseAssetPathError::EmptyPath); + } // If we found an `AssetPath::label` if let Some(range) = label_range.clone() { // If the `AssetPath::label` contained a `://` substring, it is invalid. diff --git a/tests/asset/empty_asset.rs b/tests/asset/empty_asset.rs new file mode 100644 index 0000000000000..124fe553991db --- /dev/null +++ b/tests/asset/empty_asset.rs @@ -0,0 +1,58 @@ +use bevy::prelude::*; +use bevy::asset::LoadState; + +#[test] +fn test_asset_load_valid_file() { + let mut app = App::new(); + app.add_plugins(MinimalPlugins) + .add_plugins(AssetPlugin::default()) + .init_asset::(); + + let asset_server = app.world().resource::(); + let handle: Handle = asset_server.load("branding/bevy_bird_dark.png"); + + // Confirm the asset exists in Bevy's registry + let state = asset_server.get_load_state(handle.id()); + assert!( + matches!(state, Some(LoadState::NotLoaded) | Some(LoadState::Loading) | Some(LoadState::Loaded)), + "Valid file should be in a valid load state, got {:?}", + state + ); +} + +#[test] +fn test_asset_load_invalid_file() { + let mut app = App::new(); + app.add_plugins(MinimalPlugins) + .add_plugins(AssetPlugin::default()) + .init_asset::(); + + let asset_server = app.world().resource::(); + + // Bevy doesn't panic on invalid paths - it creates a handle and marks it as failed + let handle: Handle = asset_server.load("nonexistent/fake_file.png"); + + // The handle should be created successfully (no panic) + let state = asset_server.get_load_state(handle.id()); + + // We just verify that a handle was created - Bevy will handle the error internally + assert!( + state.is_some(), + "Invalid file should still create a handle, got {:?}", + state + ); +} + +#[test] +#[should_panic] +fn test_asset_load_empty_path_panics() { + let mut app = App::new(); + app.add_plugins(MinimalPlugins) + .add_plugins(AssetPlugin::default()) + .init_asset::(); + + let asset_server = app.world().resource::(); + + // Test that load panics with empty string + let _handle: Handle = asset_server.load(""); +} \ No newline at end of file