Repository: bevyengine/bevy
File: crates/bevy_asset/src/lib.rs (Rust)

Code before:

                Ok(TestAssetUD(untyped_handle))
            }

            fn extensions(&self) -> &[&str] {
                &["rsp"]
            }
        }

        app.init_asset::<TestAssetUD>()
            .register_asset_loader(ImmediateSelfLoader);

        let handle: Handle<TestAssetUD> = asset_server.load("abc.rsp");

        run_app_until(&mut app, |world| match asset_server.load_state(&handle) {
            LoadState::Loading => None,
            LoadState::Loaded => {
                let asset_id = {
                    let test_assets = world.resource::<Assets<TestAssetUD>>();
                    let asset = test_assets.get(&handle).unwrap();
                    asset.0.id()
                };
                let untyped = world.resource::<Assets<crate::LoadedUntypedAsset>>();
                if let Some(untyped_handle) = untyped.get(asset_id) {
                    assert_eq!(handle.id(), untyped_handle.handle.id());
                    if cfg!(target_os = "windows") {
                        panic!("Can unexpectedly get asset from self path on windows.");
                    }
                } else {
                    // Windows does not have this asset loaded. I don't know why
                    // it would behave any differently. This next line will
                    // effectively ignore the issue.
                    if !cfg!(target_os = "windows") {
                        panic!(
                            "Cannot get asset from self path on windows even \
                             though it claims it was loaded."
                        );
                    }
                }
                Some(())
            }
            state => panic!("Unexpected asset state: {state:?}"),
        });

        run_app_until(&mut app, |world| {
            let messages = collect_asset_events(world);
            if messages.is_empty() {
                return None;
            }
            assert_eq!(
                messages,

Review comment (bug):
I'm quite sure this is not a Windows problem - I think this is a flake-y test. We definitely shouldn't be cfg-ing out these asserts for Windows.

What's happening here is that the loader kicks off a **deferred** untyped load. That means its possible for the `TestAssetUD` to finish loading but for the untyped load to not even start. Hence you can have the TestAssetUD be loaded but the LoadedUntypedAsset not yet be loaded.

Instead of doing the assert here, use let-else to get the LoadedUntypedAsset and `return None;` if the let-else fails, and then do the assert afterwards.

Code after:
            fn extensions(&self) -> &[&str] {
                &["rsp"]
            }
        }

        app.init_asset::<TestAssetUD>()
            .register_asset_loader(ImmediateSelfLoader);

        let handle: Handle<TestAssetUD> = asset_server.load("abc.rsp");

        run_app_until(&mut app, |world| match asset_server.load_state(&handle) {
            LoadState::Loading => None,
            LoadState::Loaded => {
                let asset_id = {
                    let test_assets = world.resource::<Assets<TestAssetUD>>();
                    let asset = test_assets.get(&handle).unwrap();
                    asset.0.id()
                };
                let untyped = world.resource::<Assets<crate::LoadedUntypedAsset>>();
                if let Some(untyped_handle) = untyped.get(asset_id) {
                    assert_eq!(handle.id(), untyped_handle.handle.id());
                    Some(())
                } else {
                    None
                }
            }
            state => panic!("Unexpected asset state: {state:?}"),
        });

        run_app_until(&mut app, |world| {
            let messages = collect_asset_events(world);
            if messages.is_empty() {
                return None;
            }
            assert_eq!(
                messages,
                [
                    AssetEvent::LoadedWithDependencies { id: handle.id() },
                    AssetEvent::Added { id: handle.id() }
                ]
            );
            Some(())
        });

        // Sending an asset event should result in the asset being reloaded - resulting in a
        // "Modified" message.
        source_events
            .send_blocking(AssetSourceEvent::ModifiedAsset(PathBuf::from("abc.rsp")))
            .unwrap();

        run_app_until(&mut app, |world| {