Skip to content

Commit c224bae

Browse files
authored
Add tests to document three separate asset issues. (#21566)
# Objective - Add tests "showing off" the problems with #20651, #12756, and #21564. ## Solution - Added some tests! ## Testing - Yes
1 parent bd3b23e commit c224bae

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed

crates/bevy_asset/src/lib.rs

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3258,4 +3258,231 @@ mod tests {
32583258
// This assertion exists to "prove" that this problem exists.
32593259
assert!(processed_dir.get_asset(gltfx_path).is_none());
32603260
}
3261+
3262+
#[test]
3263+
fn same_asset_different_settings() {
3264+
// Test loading the same asset twice with different settings. This should
3265+
// produce two distinct assets.
3266+
3267+
// First, implement an asset that's a single u8, whose value is copied from
3268+
// the loader settings.
3269+
3270+
#[derive(Asset, TypePath)]
3271+
struct U8Asset(u8);
3272+
3273+
#[derive(Serialize, Deserialize, Default)]
3274+
struct U8LoaderSettings(u8);
3275+
3276+
struct U8Loader;
3277+
3278+
impl AssetLoader for U8Loader {
3279+
type Asset = U8Asset;
3280+
type Settings = U8LoaderSettings;
3281+
type Error = crate::loader::LoadDirectError;
3282+
3283+
async fn load(
3284+
&self,
3285+
_: &mut dyn Reader,
3286+
settings: &Self::Settings,
3287+
_: &mut LoadContext<'_>,
3288+
) -> Result<Self::Asset, Self::Error> {
3289+
Ok(U8Asset(settings.0))
3290+
}
3291+
3292+
fn extensions(&self) -> &[&str] {
3293+
&["u8"]
3294+
}
3295+
}
3296+
3297+
// Create a test asset.
3298+
3299+
let dir = Dir::default();
3300+
dir.insert_asset(Path::new("test.u8"), &[]);
3301+
3302+
let asset_source = AssetSource::build()
3303+
.with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() }));
3304+
3305+
// Set up the app.
3306+
3307+
let mut app = App::new();
3308+
3309+
app.register_asset_source(AssetSourceId::Default, asset_source)
3310+
.add_plugins((TaskPoolPlugin::default(), AssetPlugin::default()))
3311+
.init_asset::<U8Asset>()
3312+
.register_asset_loader(U8Loader);
3313+
3314+
let asset_server = app.world().resource::<AssetServer>();
3315+
3316+
// Load the test asset twice but with different settings.
3317+
3318+
fn load(asset_server: &AssetServer, path: &'static str, value: u8) -> Handle<U8Asset> {
3319+
asset_server.load_with_settings::<U8Asset, U8LoaderSettings>(
3320+
path,
3321+
move |s: &mut U8LoaderSettings| s.0 = value,
3322+
)
3323+
}
3324+
3325+
let handle_1 = load(asset_server, "test.u8", 1);
3326+
let handle_2 = load(asset_server, "test.u8", 2);
3327+
3328+
// Handles should be different.
3329+
3330+
// These handles should be different, but due to
3331+
// https://github.com/bevyengine/bevy/pull/21564, they are not. Once 21564 is fixed, we
3332+
// should replace these expects.
3333+
//
3334+
// assert_ne!(handle_1, handle_2);
3335+
assert_eq!(handle_1, handle_2);
3336+
3337+
run_app_until(&mut app, |world| {
3338+
let (Some(asset_1), Some(asset_2)) = (
3339+
world.resource::<Assets<U8Asset>>().get(&handle_1),
3340+
world.resource::<Assets<U8Asset>>().get(&handle_2),
3341+
) else {
3342+
return None;
3343+
};
3344+
3345+
// Values should match the settings.
3346+
3347+
// These values should be different, but due to
3348+
// https://github.com/bevyengine/bevy/pull/21564, they are not. Once 21564 is fixed, we
3349+
// should replace these expects.
3350+
//
3351+
// assert_eq!(asset_1.0, 1);
3352+
// assert_eq!(asset_2.0, 2);
3353+
assert_eq!(asset_1.0, asset_2.0);
3354+
3355+
Some(())
3356+
});
3357+
}
3358+
3359+
#[test]
3360+
fn loading_two_subassets_does_not_start_two_loads() {
3361+
let mut app = App::new();
3362+
3363+
let dir = Dir::default();
3364+
dir.insert_asset(Path::new("test.txt"), &[]);
3365+
3366+
let asset_source = AssetSource::build()
3367+
.with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() }));
3368+
3369+
app.register_asset_source(AssetSourceId::Default, asset_source)
3370+
.add_plugins((TaskPoolPlugin::default(), AssetPlugin::default()))
3371+
.init_asset::<TestAsset>();
3372+
3373+
struct TwoSubassetLoader;
3374+
3375+
impl AssetLoader for TwoSubassetLoader {
3376+
type Asset = TestAsset;
3377+
type Settings = ();
3378+
type Error = std::io::Error;
3379+
3380+
async fn load(
3381+
&self,
3382+
_reader: &mut dyn Reader,
3383+
_settings: &Self::Settings,
3384+
load_context: &mut LoadContext<'_>,
3385+
) -> Result<Self::Asset, Self::Error> {
3386+
load_context.add_labeled_asset("A".into(), TestAsset);
3387+
load_context.add_labeled_asset("B".into(), TestAsset);
3388+
Ok(TestAsset)
3389+
}
3390+
3391+
fn extensions(&self) -> &[&str] {
3392+
&["txt"]
3393+
}
3394+
}
3395+
3396+
app.register_asset_loader(TwoSubassetLoader);
3397+
3398+
let asset_server = app.world().resource::<AssetServer>().clone();
3399+
let _subasset_1: Handle<TestAsset> = asset_server.load("test.txt#A");
3400+
let _subasset_2: Handle<TestAsset> = asset_server.load("test.txt#B");
3401+
3402+
app.update();
3403+
3404+
// Due to https://github.com/bevyengine/bevy/issues/12756, this expectation fails. Once
3405+
// #12756 is fixed, we should swap these asserts.
3406+
//
3407+
// assert_eq!(get_started_load_count(app.world()), 1);
3408+
assert_eq!(get_started_load_count(app.world()), 2);
3409+
}
3410+
3411+
#[test]
3412+
fn get_strong_handle_prevents_reload_when_asset_still_alive() {
3413+
let mut app = App::new();
3414+
3415+
let dir = Dir::default();
3416+
dir.insert_asset(Path::new("test.txt"), &[]);
3417+
3418+
let asset_source = AssetSource::build()
3419+
.with_reader(move || Box::new(MemoryAssetReader { root: dir.clone() }));
3420+
3421+
app.register_asset_source(AssetSourceId::Default, asset_source)
3422+
.add_plugins((TaskPoolPlugin::default(), AssetPlugin::default()))
3423+
.init_asset::<TestAsset>();
3424+
3425+
struct TrivialLoader;
3426+
3427+
impl AssetLoader for TrivialLoader {
3428+
type Asset = TestAsset;
3429+
type Settings = ();
3430+
type Error = std::io::Error;
3431+
3432+
async fn load(
3433+
&self,
3434+
_reader: &mut dyn Reader,
3435+
_settings: &Self::Settings,
3436+
_load_context: &mut LoadContext<'_>,
3437+
) -> Result<Self::Asset, Self::Error> {
3438+
Ok(TestAsset)
3439+
}
3440+
3441+
fn extensions(&self) -> &[&str] {
3442+
&["txt"]
3443+
}
3444+
}
3445+
3446+
app.register_asset_loader(TrivialLoader);
3447+
3448+
let asset_server = app.world().resource::<AssetServer>().clone();
3449+
let original_handle: Handle<TestAsset> = asset_server.load("test.txt");
3450+
3451+
// Wait for the asset to load.
3452+
run_app_until(&mut app, |world| {
3453+
world
3454+
.resource::<Assets<TestAsset>>()
3455+
.get(&original_handle)
3456+
.map(|_| ())
3457+
});
3458+
3459+
assert_eq!(get_started_load_count(app.world()), 1);
3460+
3461+
// Get a new strong handle from the original handle's ID.
3462+
let new_handle = app
3463+
.world_mut()
3464+
.resource_mut::<Assets<TestAsset>>()
3465+
.get_strong_handle(original_handle.id())
3466+
.unwrap();
3467+
3468+
// Drop the original handle. This should still leave the asset alive.
3469+
drop(original_handle);
3470+
3471+
app.update();
3472+
assert!(app
3473+
.world()
3474+
.resource::<Assets<TestAsset>>()
3475+
.get(&new_handle)
3476+
.is_some());
3477+
3478+
let _other_handle: Handle<TestAsset> = asset_server.load("test.txt");
3479+
app.update();
3480+
// The asset server should **not** have started a new load, since the asset is still alive.
3481+
3482+
// Due to https://github.com/bevyengine/bevy/issues/20651, we do get a second load. Once
3483+
// #20651 is fixed, we should swap these asserts.
3484+
//
3485+
// assert_eq!(get_started_load_count(app.world()), 1);
3486+
assert_eq!(get_started_load_count(app.world()), 2);
3487+
}
32613488
}

0 commit comments

Comments
 (0)