Merge pull request #22658 from peppy/gameplay-sample-trigger-source-test-fix

Refactor `GameplaySampleTriggerSource` test to not be realtime dependent
This commit is contained in:
Bartłomiej Dach
2023-02-16 19:39:18 +01:00
committed by GitHub

View File

@ -1,10 +1,12 @@
// 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.
#nullable disable using System.Diagnostics;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Timing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
@ -14,16 +16,23 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Storyboards;
using osuTK.Input; using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay namespace osu.Game.Tests.Visual.Gameplay
{ {
public partial class TestSceneGameplaySampleTriggerSource : PlayerTestScene public partial class TestSceneGameplaySampleTriggerSource : PlayerTestScene
{ {
private TestGameplaySampleTriggerSource sampleTriggerSource; private TestGameplaySampleTriggerSource sampleTriggerSource = null!;
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset(); protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
private Beatmap beatmap; private Beatmap beatmap = null!;
[Resolved]
private AudioManager audio { get; set; } = null!;
protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard? storyboard = null)
=> new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audio);
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
@ -39,12 +48,13 @@ namespace osu.Game.Tests.Visual.Gameplay
const double start_offset = 8000; const double start_offset = 8000;
const double spacing = 2000; const double spacing = 2000;
// intentionally start objects a bit late so we can test the case of no alive objects.
double t = start_offset; double t = start_offset;
beatmap.HitObjects.AddRange(new[] beatmap.HitObjects.AddRange(new[]
{ {
new HitCircle new HitCircle
{ {
// intentionally start objects a bit late so we can test the case of no alive objects.
StartTime = t += spacing, StartTime = t += spacing,
Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) } Samples = new[] { new HitSampleInfo(HitSampleInfo.HIT_NORMAL) }
}, },
@ -80,42 +90,66 @@ namespace osu.Game.Tests.Visual.Gameplay
[Test] [Test]
public void TestCorrectHitObject() public void TestCorrectHitObject()
{ {
HitObjectLifetimeEntry nextObjectEntry = null; waitForAliveObjectIndex(null);
checkValidObjectIndex(0);
AddAssert("no alive objects", () => getNextAliveObject() == null); seekBeforeIndex(0);
waitForAliveObjectIndex(0);
checkValidObjectIndex(0);
AddAssert("check initially correct object", () => sampleTriggerSource.GetMostValidObject() == beatmap.HitObjects[0]); AddAssert("first object not hit", () => getNextAliveObject()?.Entry?.Result?.HasResult != true);
AddUntilStep("get next object", () => AddStep("hit first object", () =>
{ {
var nextDrawableObject = getNextAliveObject(); var next = getNextAliveObject();
if (nextDrawableObject != null) if (next != null)
{ {
nextObjectEntry = nextDrawableObject.Entry; Debug.Assert(next.Entry?.Result?.HasResult != true);
InputManager.MoveMouseTo(nextDrawableObject.ScreenSpaceDrawQuad.Centre);
return true;
}
return false; InputManager.MoveMouseTo(next.ScreenSpaceDrawQuad.Centre);
});
AddUntilStep("hit first hitobject", () =>
{
InputManager.Click(MouseButton.Left); InputManager.Click(MouseButton.Left);
return nextObjectEntry.Result?.HasResult == true; }
}); });
AddAssert("check correct object after hit", () => sampleTriggerSource.GetMostValidObject() == beatmap.HitObjects[1]); AddAssert("first object hit", () => getNextAliveObject()?.Entry?.Result?.HasResult == true);
AddUntilStep("check correct object after miss", () => sampleTriggerSource.GetMostValidObject() == beatmap.HitObjects[2]); checkValidObjectIndex(1);
AddUntilStep("check correct object after miss", () => sampleTriggerSource.GetMostValidObject() == beatmap.HitObjects[3]);
AddUntilStep("no alive objects", () => getNextAliveObject() == null); // Still object 1 as it's not hit yet.
AddAssert("check correct object after none alive", () => sampleTriggerSource.GetMostValidObject() == beatmap.HitObjects[3]); seekBeforeIndex(1);
waitForAliveObjectIndex(1);
checkValidObjectIndex(1);
seekBeforeIndex(2);
waitForAliveObjectIndex(2);
checkValidObjectIndex(2);
seekBeforeIndex(3);
waitForAliveObjectIndex(3);
checkValidObjectIndex(3);
AddStep("Seek into future", () => Beatmap.Value.Track.Seek(beatmap.HitObjects.Last().GetEndTime() + 10000));
waitForAliveObjectIndex(null);
checkValidObjectIndex(3);
} }
private DrawableHitObject getNextAliveObject() => private void seekBeforeIndex(int index) =>
AddStep($"seek to just before object {index}", () => Beatmap.Value.Track.Seek(beatmap.HitObjects[index].StartTime - 100));
private void waitForAliveObjectIndex(int? index)
{
if (index == null)
AddUntilStep("wait for no alive objects", getNextAliveObject, () => Is.Null);
else
AddUntilStep($"wait for next alive to be {index}", () => getNextAliveObject()?.HitObject, () => Is.EqualTo(beatmap.HitObjects[index.Value]));
}
private void checkValidObjectIndex(int index) =>
AddAssert($"check valid object is {index}", () => sampleTriggerSource.GetMostValidObject(), () => Is.EqualTo(beatmap.HitObjects[index]));
private DrawableHitObject? getNextAliveObject() =>
Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.FirstOrDefault(); Player.DrawableRuleset.Playfield.HitObjectContainer.AliveObjects.FirstOrDefault();
[Test] [Test]