1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-15 12:27:26 +08:00

Merge pull request #30526 from smoogipoo/fix-beatmap-recommender-test

Fix intermittent beatmap recommendations test
This commit is contained in:
Dean Herbert 2024-11-07 18:40:31 +09:00 committed by GitHub
commit aad9f4078e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 116 additions and 53 deletions

View File

@ -10,9 +10,12 @@ using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Platform;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Extensions; using osu.Game.Extensions;
using osu.Game.Online.API;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania;
@ -191,8 +194,39 @@ namespace osu.Game.Tests.Visual.SongSelect
{ {
AddStep("present beatmap", () => Game.PresentBeatmap(getImport())); AddStep("present beatmap", () => Game.PresentBeatmap(getImport()));
AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect); AddUntilStep("wait for song select", () => Game.ScreenStack.CurrentScreen is Screens.Select.SongSelect select && select.BeatmapSetsLoaded);
AddUntilStep("recommended beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.MatchesOnlineID(getImport().Beatmaps[expectedDiff - 1])); AddUntilStep("recommended beatmap displayed", () => Game.Beatmap.Value.BeatmapInfo.MatchesOnlineID(getImport().Beatmaps[expectedDiff - 1]));
} }
protected override TestOsuGame CreateTestGame() => new NoBeatmapUpdateGame(LocalStorage, API);
private partial class NoBeatmapUpdateGame : TestOsuGame
{
public NoBeatmapUpdateGame(Storage storage, IAPIProvider api, string[] args = null)
: base(storage, api, args)
{
}
protected override IBeatmapUpdater CreateBeatmapUpdater() => new TestBeatmapUpdater();
private class TestBeatmapUpdater : IBeatmapUpdater
{
public void Queue(Live<BeatmapSetInfo> beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst)
{
}
public void Process(BeatmapSetInfo beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst)
{
}
public void ProcessObjectCounts(BeatmapInfo beatmapInfo, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst)
{
}
public void Dispose()
{
}
}
}
} }
} }

View File

@ -13,11 +13,11 @@ namespace osu.Game.Beatmaps
/// </summary> /// </summary>
public partial class BeatmapOnlineChangeIngest : Component public partial class BeatmapOnlineChangeIngest : Component
{ {
private readonly BeatmapUpdater beatmapUpdater; private readonly IBeatmapUpdater beatmapUpdater;
private readonly RealmAccess realm; private readonly RealmAccess realm;
private readonly MetadataClient metadataClient; private readonly MetadataClient metadataClient;
public BeatmapOnlineChangeIngest(BeatmapUpdater beatmapUpdater, RealmAccess realm, MetadataClient metadataClient) public BeatmapOnlineChangeIngest(IBeatmapUpdater beatmapUpdater, RealmAccess realm, MetadataClient metadataClient)
{ {
this.beatmapUpdater = beatmapUpdater; this.beatmapUpdater = beatmapUpdater;
this.realm = realm; this.realm = realm;

View File

@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -15,10 +14,7 @@ using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
/// <summary> public class BeatmapUpdater : IBeatmapUpdater
/// Handles all processing required to ensure a local beatmap is in a consistent state with any changes.
/// </summary>
public class BeatmapUpdater : IDisposable
{ {
private readonly IWorkingBeatmapCache workingBeatmapCache; private readonly IWorkingBeatmapCache workingBeatmapCache;
@ -38,11 +34,6 @@ namespace osu.Game.Beatmaps
metadataLookup = new BeatmapUpdaterMetadataLookup(api, storage); metadataLookup = new BeatmapUpdaterMetadataLookup(api, storage);
} }
/// <summary>
/// Queue a beatmap for background processing.
/// </summary>
/// <param name="beatmapSet">The managed beatmap set to update. A transaction will be opened to apply changes.</param>
/// <param name="lookupScope">The preferred scope to use for metadata lookup.</param>
public void Queue(Live<BeatmapSetInfo> beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst) public void Queue(Live<BeatmapSetInfo> beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst)
{ {
Logger.Log($"Queueing change for local beatmap {beatmapSet}"); Logger.Log($"Queueing change for local beatmap {beatmapSet}");
@ -50,12 +41,9 @@ namespace osu.Game.Beatmaps
updateScheduler); updateScheduler);
} }
/// <summary> public void Process(BeatmapSetInfo beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst)
/// Run all processing on a beatmap immediately. {
/// </summary> beatmapSet.Realm!.Write(_ =>
/// <param name="beatmapSet">The managed beatmap set to update. A transaction will be opened to apply changes.</param>
/// <param name="lookupScope">The preferred scope to use for metadata lookup.</param>
public void Process(BeatmapSetInfo beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst) => beatmapSet.Realm!.Write(_ =>
{ {
// Before we use below, we want to invalidate. // Before we use below, we want to invalidate.
workingBeatmapCache.Invalidate(beatmapSet); workingBeatmapCache.Invalidate(beatmapSet);
@ -84,8 +72,11 @@ namespace osu.Game.Beatmaps
// And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required. // And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required.
workingBeatmapCache.Invalidate(beatmapSet); workingBeatmapCache.Invalidate(beatmapSet);
}); });
}
public void ProcessObjectCounts(BeatmapInfo beatmapInfo, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst) => beatmapInfo.Realm!.Write(_ => public void ProcessObjectCounts(BeatmapInfo beatmapInfo, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst)
{
beatmapInfo.Realm!.Write(_ =>
{ {
// Before we use below, we want to invalidate. // Before we use below, we want to invalidate.
workingBeatmapCache.Invalidate(beatmapInfo); workingBeatmapCache.Invalidate(beatmapInfo);
@ -99,6 +90,7 @@ namespace osu.Game.Beatmaps
// And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required. // And invalidate again afterwards as re-fetching the most up-to-date database metadata will be required.
workingBeatmapCache.Invalidate(beatmapInfo); workingBeatmapCache.Invalidate(beatmapInfo);
}); });
}
#region Implementation of IDisposable #region Implementation of IDisposable

View File

@ -0,0 +1,35 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Game.Database;
namespace osu.Game.Beatmaps
{
/// <summary>
/// Handles all processing required to ensure a local beatmap is in a consistent state with any changes.
/// </summary>
public interface IBeatmapUpdater : IDisposable
{
/// <summary>
/// Queue a beatmap for background processing.
/// </summary>
/// <param name="beatmapSet">The managed beatmap set to update. A transaction will be opened to apply changes.</param>
/// <param name="lookupScope">The preferred scope to use for metadata lookup.</param>
void Queue(Live<BeatmapSetInfo> beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst);
/// <summary>
/// Run all processing on a beatmap immediately.
/// </summary>
/// <param name="beatmapSet">The managed beatmap set to update. A transaction will be opened to apply changes.</param>
/// <param name="lookupScope">The preferred scope to use for metadata lookup.</param>
void Process(BeatmapSetInfo beatmapSet, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst);
/// <summary>
/// Runs a subset of processing focused on updating any cached beatmap object counts.
/// </summary>
/// <param name="beatmapInfo">The managed beatmap to update. A transaction will be opened to apply changes.</param>
/// <param name="lookupScope">The preferred scope to use for metadata lookup.</param>
void ProcessObjectCounts(BeatmapInfo beatmapInfo, MetadataLookupScope lookupScope = MetadataLookupScope.LocalCacheFirst);
}
}

View File

@ -46,7 +46,7 @@ namespace osu.Game.Database
private RealmAccess realmAccess { get; set; } = null!; private RealmAccess realmAccess { get; set; } = null!;
[Resolved] [Resolved]
private BeatmapUpdater beatmapUpdater { get; set; } = null!; private IBeatmapUpdater beatmapUpdater { get; set; } = null!;
[Resolved] [Resolved]
private IBindable<WorkingBeatmap> gameBeatmap { get; set; } = null!; private IBindable<WorkingBeatmap> gameBeatmap { get; set; } = null!;

View File

@ -198,7 +198,7 @@ namespace osu.Game
public readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> AvailableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>(new Dictionary<ModType, IReadOnlyList<Mod>>()); public readonly Bindable<Dictionary<ModType, IReadOnlyList<Mod>>> AvailableMods = new Bindable<Dictionary<ModType, IReadOnlyList<Mod>>>(new Dictionary<ModType, IReadOnlyList<Mod>>());
private BeatmapDifficultyCache difficultyCache; private BeatmapDifficultyCache difficultyCache;
private BeatmapUpdater beatmapUpdater; private IBeatmapUpdater beatmapUpdater;
private UserLookupCache userCache; private UserLookupCache userCache;
private BeatmapLookupCache beatmapCache; private BeatmapLookupCache beatmapCache;
@ -324,7 +324,7 @@ namespace osu.Game
base.Content.Add(difficultyCache); base.Content.Add(difficultyCache);
// TODO: OsuGame or OsuGameBase? // TODO: OsuGame or OsuGameBase?
dependencies.CacheAs(beatmapUpdater = new BeatmapUpdater(BeatmapManager, difficultyCache, API, Storage)); dependencies.CacheAs(beatmapUpdater = CreateBeatmapUpdater());
dependencies.CacheAs(SpectatorClient = new OnlineSpectatorClient(endpoints)); dependencies.CacheAs(SpectatorClient = new OnlineSpectatorClient(endpoints));
dependencies.CacheAs(MultiplayerClient = new OnlineMultiplayerClient(endpoints)); dependencies.CacheAs(MultiplayerClient = new OnlineMultiplayerClient(endpoints));
dependencies.CacheAs(metadataClient = new OnlineMetadataClient(endpoints)); dependencies.CacheAs(metadataClient = new OnlineMetadataClient(endpoints));
@ -563,6 +563,8 @@ namespace osu.Game
} }
} }
protected virtual IBeatmapUpdater CreateBeatmapUpdater() => new BeatmapUpdater(BeatmapManager, difficultyCache, API, Storage);
protected override UserInputManager CreateUserInputManager() => new OsuUserInputManager(); protected override UserInputManager CreateUserInputManager() => new OsuUserInputManager();
protected virtual BatteryInfo CreateBatteryInfo() => null; protected virtual BatteryInfo CreateBatteryInfo() => null;