1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-28 14:12:55 +08:00

Centralise and harden editor-ready-for-use check

Not only does this combine the check into one location, but it also adds
a check on the global `WorkingBeatmap` being updated, which is the only
way I can see the following failure happening:

```csharp
05:19:07     osu.Game.Tests: osu.Game.Tests.Visual.Editing.TestSceneEditorBeatmapCreation.TestAddAudioTrack
05:19:07       Failed TestAddAudioTrack [161 ms]
05:19:07       Error Message:
05:19:07        TearDown : System.NullReferenceException : Object reference not set to an instance of an object.
05:19:07       Stack Trace:
05:19:07       --TearDown
05:19:07        at osu.Game.Database.ModelManager`1.<>c__DisplayClass7_0.<AddFile>b__0(TModel managed) in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Database\ModelManager.cs:line 36
05:19:07        at osu.Game.Database.ModelManager`1.<>c__DisplayClass8_0.<performFileOperation>b__0(Realm realm) in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Database\ModelManager.cs:line 49
05:19:07        at osu.Game.Database.RealmExtensions.Write(Realm realm, Action`1 function) in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Database\RealmExtensions.cs:line 14
05:19:07        at osu.Game.Database.ModelManager`1.performFileOperation(TModel item, Action`1 operation) in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Database\ModelManager.cs:line 46
05:19:07        at osu.Game.Database.ModelManager`1.AddFile(TModel item, Stream contents, String filename) in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Database\ModelManager.cs:line 36
05:19:07        at osu.Game.Screens.Edit.Setup.ResourcesSection.ChangeAudioTrack(FileInfo source) in C:\BuildAgent\work\ecd860037212ac52\osu.Game\Screens\Edit\Setup\ResourcesSection.cs:line 115
05:19:07        at osu.Game.Tests.Visual.Editing.TestSceneEditorBeatmapCreation.<TestAddAudioTrack>b__13_0() in C:\BuildAgent\work\ecd860037212ac52\osu.Game.Tests\Visual\Editing\TestSceneEditorBeatmapCreation.cs:line 101
05:19:07        at osu.Framework.Testing.Drawables.Steps.AssertButton.checkAssert()
05:19:07        at osu.Framework.Testing.Drawables.Steps.StepButton.PerformStep(Boolean userTriggered)
05:19:07        at osu.Framework.Testing.TestScene.runNextStep(Action onCompletion, Action`1 onError, Func`2 stopCondition)
```
This commit is contained in:
Dean Herbert 2022-06-27 16:19:31 +09:00
parent 10d1bbb131
commit 5a7d339cc8
5 changed files with 34 additions and 21 deletions

View File

@ -10,7 +10,6 @@ using osu.Framework.Input;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.UI;
using osu.Game.Screens.Edit;
@ -41,10 +40,6 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
private bool editorComponentsReady => editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
&& editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true
&& editor?.ChildrenOfType<Playfield>().FirstOrDefault()?.IsLoaded == true;
[TestCase(true)]
[TestCase(false)]
public void TestVelocityChangeSavesCorrectly(bool adjustVelocity)
@ -52,7 +47,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
double? velocity = null;
AddStep("enter editor", () => Game.ScreenStack.Push(new EditorLoader()));
AddUntilStep("wait for editor load", () => editorComponentsReady);
AddUntilStep("wait for editor load", () => editor?.ReadyForUse == true);
AddStep("seek to first control point", () => editorClock.Seek(editorBeatmap.ControlPointInfo.TimingPoints.First().Time));
AddStep("enter slider placement mode", () => InputManager.Key(Key.Number3));
@ -91,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
AddStep("exit", () => InputManager.Key(Key.Escape));
AddStep("enter editor (again)", () => Game.ScreenStack.Push(new EditorLoader()));
AddUntilStep("wait for editor load", () => editorComponentsReady);
AddUntilStep("wait for editor load", () => editor?.ReadyForUse == true);
AddStep("seek to slider", () => editorClock.Seek(slider.StartTime));
AddAssert("slider has correct velocity", () => slider.Velocity == velocity);

View File

@ -36,8 +36,6 @@ namespace osu.Game.Tests.Visual.Editing
{
protected override Ruleset CreateEditorRuleset() => new OsuRuleset();
protected override bool EditorComponentsReady => Editor.ChildrenOfType<SetupScreen>().SingleOrDefault()?.IsLoaded == true;
protected override bool IsolateSavingFromDatabase => false;
[Resolved]

View File

@ -9,12 +9,10 @@ using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Components.Timelines.Summary;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osu.Game.Screens.Edit.GameplayTest;
using osu.Game.Screens.Select;
using osu.Game.Tests.Resources;
@ -40,10 +38,7 @@ namespace osu.Game.Tests.Visual.Editing
AddStep("switch ruleset", () => Game.Ruleset.Value = new ManiaRuleset().RulesetInfo);
AddStep("open editor", () => ((PlaySongSelect)Game.ScreenStack.CurrentScreen).Edit(beatmapSet.Beatmaps.First(beatmap => beatmap.Ruleset.OnlineID == 0)));
AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor
&& editor.IsLoaded
&& editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
&& editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true);
AddUntilStep("wait for editor open", () => Game.ScreenStack.CurrentScreen is Editor editor && editor.ReadyForUse);
AddStep("test gameplay", () =>
{
var testGameplayButton = this.ChildrenOfType<TestGameplayButton>().Single();

View File

@ -21,6 +21,7 @@ using osu.Framework.Input.Events;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Audio;
using osu.Game.Beatmaps;
@ -39,6 +40,7 @@ using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit.Components.Menus;
using osu.Game.Screens.Edit.Compose;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osu.Game.Screens.Edit.Design;
using osu.Game.Screens.Edit.GameplayTest;
using osu.Game.Screens.Edit.Setup;
@ -97,6 +99,32 @@ namespace osu.Game.Screens.Edit
public IBindable<bool> SamplePlaybackDisabled => samplePlaybackDisabled;
/// <summary>
/// Ensure all asynchronously loading pieces of the editor are in a good state.
/// This exists here for convenience for tests, not for actual use.
/// Eventually we'd probably want a better way to signal this.
/// </summary>
public bool ReadyForUse
{
get
{
if (!workingBeatmapUpdated)
return false;
var loadedScreen = screenContainer?.Children.SingleOrDefault(s => s.IsLoaded);
if (loadedScreen == null)
return false;
if (loadedScreen is EditorScreenWithTimeline)
return loadedScreen.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true;
return true;
}
}
private bool workingBeatmapUpdated;
private readonly Bindable<bool> samplePlaybackDisabled = new Bindable<bool>();
private bool canSave;
@ -219,6 +247,7 @@ namespace osu.Game.Screens.Edit
// this assumes that nothing during the rest of this load() method is accessing Beatmap.Value (loadableBeatmap should be preferred).
// generally this is quite safe, as the actual load of editor content comes after menuBar.Mode.ValueChanged is fired in its own LoadComplete.
Beatmap.Value = loadableBeatmap;
workingBeatmapUpdated = true;
});
OsuMenuItem undoMenuItem;

View File

@ -17,9 +17,7 @@ using osu.Game.Online.API;
using osu.Game.Overlays;
using osu.Game.Overlays.Dialog;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Edit;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Compose.Components.Timeline;
using osu.Game.Screens.Menu;
using osu.Game.Skinning;
@ -58,15 +56,13 @@ namespace osu.Game.Tests.Visual
Dependencies.CacheAs<BeatmapManager>(testBeatmapManager = new TestBeatmapManager(LocalStorage, Realm, rulesets, null, audio, Resources, host, Beatmap.Default));
}
protected virtual bool EditorComponentsReady => Editor.ChildrenOfType<HitObjectComposer>().FirstOrDefault()?.IsLoaded == true
&& Editor.ChildrenOfType<TimelineArea>().FirstOrDefault()?.IsLoaded == true;
public override void SetUpSteps()
{
base.SetUpSteps();
AddStep("load editor", LoadEditor);
AddUntilStep("wait for editor to load", () => EditorComponentsReady);
AddUntilStep("wait for editor to load", () => Editor?.ReadyForUse == true);
AddUntilStep("wait for beatmap updated", () => !Beatmap.IsDefault);
}
protected virtual void LoadEditor()