From fc6c245de5dc362489706fbae2b1c299260f9fb8 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 19 Apr 2020 05:36:04 +0300 Subject: [PATCH 1/9] Replace all judged event logic with HasCompleted bindable --- .../TestSceneHoldNoteInput.cs | 8 +------- .../TestSceneOutOfOrderHits.cs | 8 +------- .../TestSceneSliderInput.cs | 8 +------- .../TestSceneSwellJudgements.cs | 2 +- osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 17 +++++++++-------- osu.Game/Screens/Play/BreakTracker.cs | 2 +- osu.Game/Tests/Visual/ModPerfectTestScene.cs | 2 +- 7 files changed, 15 insertions(+), 32 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs index 7b0cf40d45..0d13b85901 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHoldNoteInput.cs @@ -27,7 +27,6 @@ namespace osu.Game.Rulesets.Mania.Tests private const double time_after_tail = 5250; private List judgementResults; - private bool allJudgedFired; /// /// -----[ ]----- @@ -283,20 +282,15 @@ namespace osu.Game.Rulesets.Mania.Tests { if (currentPlayer == p) judgementResults.Add(result); }; - p.ScoreProcessor.AllJudged += () => - { - if (currentPlayer == p) allJudgedFired = true; - }; }; LoadScreen(currentPlayer = p); - allJudgedFired = false; judgementResults = new List(); }); AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); - AddUntilStep("Wait for all judged", () => allJudgedFired); + AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } private class ScoreAccessibleReplayPlayer : ReplayPlayer diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs index d6858f831e..91d5e04f6f 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneOutOfOrderHits.cs @@ -316,7 +316,6 @@ namespace osu.Game.Rulesets.Osu.Tests private ScoreAccessibleReplayPlayer currentPlayer; private List judgementResults; - private bool allJudgedFired; private void performTest(List hitObjects, List frames) { @@ -342,20 +341,15 @@ namespace osu.Game.Rulesets.Osu.Tests { if (currentPlayer == p) judgementResults.Add(result); }; - p.ScoreProcessor.AllJudged += () => - { - if (currentPlayer == p) allJudgedFired = true; - }; }; LoadScreen(currentPlayer = p); - allJudgedFired = false; judgementResults = new List(); }); AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); - AddUntilStep("Wait for all judged", () => allJudgedFired); + AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } private class TestHitCircle : HitCircle diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs index 67e1b77770..b0c2e56c3e 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderInput.cs @@ -47,7 +47,6 @@ namespace osu.Game.Rulesets.Osu.Tests private const double time_slider_end = 4000; private List judgementResults; - private bool allJudgedFired; /// /// Scenario: @@ -375,20 +374,15 @@ namespace osu.Game.Rulesets.Osu.Tests { if (currentPlayer == p) judgementResults.Add(result); }; - p.ScoreProcessor.AllJudged += () => - { - if (currentPlayer == p) allJudgedFired = true; - }; }; LoadScreen(currentPlayer = p); - allJudgedFired = false; judgementResults = new List(); }); AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0); AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen()); - AddUntilStep("Wait for all judged", () => allJudgedFired); + AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value); } private class ScoreAccessibleReplayPlayer : ReplayPlayer diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs index 303f0163b1..923e28a45e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Taiko.Tests [Test] public void TestZeroTickTimeOffsets() { - AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted); + AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted.Value); AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.HitObject is SwellTick).All(r => r.TimeOffset == 0)); } diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index 334b95f808..d878ef0a5c 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Bindables; using osu.Framework.Extensions.TypeExtensions; using osu.Framework.Graphics; using osu.Game.Beatmaps; @@ -12,11 +13,6 @@ namespace osu.Game.Rulesets.Scoring { public abstract class JudgementProcessor : Component { - /// - /// Invoked when all s have been judged by this . - /// - public event Action AllJudged; - /// /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by this . /// @@ -32,10 +28,12 @@ namespace osu.Game.Rulesets.Scoring /// public int JudgedHits { get; private set; } + private readonly BindableBool hasCompleted = new BindableBool(); + /// /// Whether all s have been processed. /// - public bool HasCompleted => JudgedHits == MaxHits; + public IBindable HasCompleted => hasCompleted; /// /// Applies a to this . @@ -60,8 +58,8 @@ namespace osu.Game.Rulesets.Scoring NewJudgement?.Invoke(result); - if (HasCompleted) - AllJudged?.Invoke(); + if (JudgedHits == MaxHits) + hasCompleted.Value = true; } /// @@ -72,6 +70,9 @@ namespace osu.Game.Rulesets.Scoring { JudgedHits--; + if (JudgedHits < MaxHits) + hasCompleted.Value = false; + RevertResultInternal(result); } diff --git a/osu.Game/Screens/Play/BreakTracker.cs b/osu.Game/Screens/Play/BreakTracker.cs index 64262d52b5..fcd7ed6b73 100644 --- a/osu.Game/Screens/Play/BreakTracker.cs +++ b/osu.Game/Screens/Play/BreakTracker.cs @@ -51,7 +51,7 @@ namespace osu.Game.Screens.Play isBreakTime.Value = getCurrentBreak()?.HasEffect == true || Clock.CurrentTime < gameplayStartTime - || scoreProcessor?.HasCompleted == true; + || scoreProcessor?.HasCompleted.Value == true; } private BreakPeriod getCurrentBreak() diff --git a/osu.Game/Tests/Visual/ModPerfectTestScene.cs b/osu.Game/Tests/Visual/ModPerfectTestScene.cs index 798947eb40..5948283428 100644 --- a/osu.Game/Tests/Visual/ModPerfectTestScene.cs +++ b/osu.Game/Tests/Visual/ModPerfectTestScene.cs @@ -46,7 +46,7 @@ namespace osu.Game.Tests.Visual public bool CheckFailed(bool failed) { if (!failed) - return ScoreProcessor.HasCompleted && !HealthProcessor.HasFailed; + return ScoreProcessor.HasCompleted.Value && !HealthProcessor.HasFailed; return HealthProcessor.HasFailed; } From 7e64bec94f286b4d1bbc550d4e95f9ca601ca997 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 19 Apr 2020 05:58:22 +0300 Subject: [PATCH 2/9] Use HasCompleted in Player --- osu.Game/Screens/Play/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 4597ae760c..542e226809 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -197,7 +197,7 @@ namespace osu.Game.Screens.Play }; // Bind the judgement processors to ourselves - ScoreProcessor.AllJudged += onCompletion; + ScoreProcessor.HasCompleted.ValueChanged += updateCompletionState; HealthProcessor.Failed += onFail; foreach (var mod in Mods.Value.OfType()) @@ -412,7 +412,7 @@ namespace osu.Game.Screens.Play private ScheduledDelegate completionProgressDelegate; - private void onCompletion() + private void updateCompletionState(ValueChangedEvent completionState) { // screen may be in the exiting transition phase. if (!this.IsCurrentScreen()) From 6d276890a7dca11c37855655f8f760c4b3176314 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 19 Apr 2020 05:59:56 +0300 Subject: [PATCH 3/9] Fix results screen pushed after rewinding in-between push delay --- osu.Game/Screens/Play/Player.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 542e226809..c6c83e5379 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -418,6 +418,16 @@ namespace osu.Game.Screens.Play if (!this.IsCurrentScreen()) return; + // cancel push delegate in case judges reverted + // after delegate may have already been scheduled. + if (!completionState.NewValue) + { + completionProgressDelegate?.Cancel(); + completionProgressDelegate = null; + ValidForResume = true; + return; + } + // Only show the completion screen if the player hasn't failed if (HealthProcessor.HasFailed || completionProgressDelegate != null) return; From 65a8860a65812dc4de6aae708d5352508898cdb7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sun, 19 Apr 2020 06:01:09 +0300 Subject: [PATCH 4/9] Add test cases to ensure no regression in "cancelling completion" --- .../TestSceneCompletionCancellation.cs | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs new file mode 100644 index 0000000000..54e1ff5345 --- /dev/null +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -0,0 +1,129 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Track; +using osu.Framework.Screens; +using osu.Framework.Testing; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Storyboards; +using osuTK; + +namespace osu.Game.Tests.Visual.Gameplay +{ + public class TestSceneCompletionCancellation : PlayerTestScene + { + private Track track; + + [Resolved] + private AudioManager audio { get; set; } + + protected override bool AllowFail => false; + + public TestSceneCompletionCancellation() + : base(new OsuRuleset()) + { + } + + [SetUpSteps] + public override void SetUpSteps() + { + base.SetUpSteps(); + + // Ensure track has actually running before attempting to seek + AddUntilStep("wait for track to start running", () => track.IsRunning); + } + + [Test] + public void TestCancelCompletionOnRewind() + { + cancelCompletionSteps(); + + AddAssert("no attempt to push ranking", () => !((FakeRankingPushPlayer)Player).GotoRankingInvoked); + } + + [Test] + public void TestReCompleteAfterCancellation() + { + cancelCompletionSteps(); + + // Attempt completing again. + AddStep("seek to completion again", () => track.Seek(5000)); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + + AddWaitStep("wait", 5); + + AddAssert("attempted to push ranking", () => ((FakeRankingPushPlayer)Player).GotoRankingInvoked); + } + + /// + /// Tests whether can still pause after cancelling completion + /// by reverting back to true. + /// + [Test] + public void TestCanPauseAfterCancellation() + { + cancelCompletionSteps(); + + AddStep("pause", () => Player.Pause()); + AddAssert("paused successfully", () => Player.GameplayClockContainer.IsPaused.Value); + } + + private void cancelCompletionSteps() + { + AddStep("seek to completion", () => track.Seek(5000)); + AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + + AddStep("rewind to cancel", () => track.Seek(4000)); + AddUntilStep("completion cleared by processor", () => !Player.ScoreProcessor.HasCompleted.Value); + + AddWaitStep("wait", 5); + } + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) + { + var working = new ClockBackedTestWorkingBeatmap(beatmap, storyboard, new FramedClock(new ManualClock { Rate = 1 }), audio); + track = working.Track; + return working; + } + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) + { + var beatmap = new Beatmap(); + + for (int i = 1; i <= 19; i++) + { + beatmap.HitObjects.Add(new HitCircle + { + Position = new Vector2(256, 192), + StartTime = i * 250, + }); + } + + return beatmap; + } + + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new FakeRankingPushPlayer(); + + public class FakeRankingPushPlayer : TestPlayer + { + public bool GotoRankingInvoked; + + public FakeRankingPushPlayer() + : base(true, true) + { + } + + protected override void GotoRanking() + { + GotoRankingInvoked = true; + } + } + } +} From 6f233917b18dc05bb5f7d620cfc8fc512a6df9f7 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 20 Apr 2020 06:40:51 +0300 Subject: [PATCH 5/9] Centralize updating HasCompleted bindable logic --- osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index d878ef0a5c..8aef615b5f 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -58,8 +58,7 @@ namespace osu.Game.Rulesets.Scoring NewJudgement?.Invoke(result); - if (JudgedHits == MaxHits) - hasCompleted.Value = true; + updateHasCompleted(); } /// @@ -70,8 +69,7 @@ namespace osu.Game.Rulesets.Scoring { JudgedHits--; - if (JudgedHits < MaxHits) - hasCompleted.Value = false; + updateHasCompleted(); RevertResultInternal(result); } @@ -135,5 +133,7 @@ namespace osu.Game.Rulesets.Scoring ApplyResult(result); } } + + private void updateHasCompleted() => hasCompleted.Value = JudgedHits == MaxHits; } } From e12e3391fb803f9bdf75ebb51abaf275427c1d07 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 20 Apr 2020 06:42:33 +0300 Subject: [PATCH 6/9] Base wait steps duration on the delay used for results display With `* 2` for safety of not potentially going to the next step and the delegate not executed yet. --- .../Visual/Gameplay/TestSceneCompletionCancellation.cs | 6 +++++- osu.Game/Screens/Play/Player.cs | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index 54e1ff5345..aef173c36a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -24,6 +24,9 @@ namespace osu.Game.Tests.Visual.Gameplay [Resolved] private AudioManager audio { get; set; } + private int resultsDisplayWaitCount => + (int)((Screens.Play.Player.RESULTS_DISPLAY_DELAY / TimePerAction) * 2); + protected override bool AllowFail => false; public TestSceneCompletionCancellation() @@ -83,7 +86,8 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("rewind to cancel", () => track.Seek(4000)); AddUntilStep("completion cleared by processor", () => !Player.ScoreProcessor.HasCompleted.Value); - AddWaitStep("wait", 5); + // wait to ensure there was no attempt of pushing the results screen. + AddWaitStep("wait", resultsDisplayWaitCount); } protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index c6c83e5379..2f3807753a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -37,6 +37,11 @@ namespace osu.Game.Screens.Play [Cached] public class Player : ScreenWithBeatmapBackground { + /// + /// The delay upon completion of the beatmap before displaying the results screen. + /// + public const double RESULTS_DISPLAY_DELAY = 1000.0; + public override bool AllowBackButton => false; // handled by HoldForMenuButton protected override UserActivity InitialActivity => new UserActivity.SoloGame(Beatmap.Value.BeatmapInfo, Ruleset.Value); @@ -436,7 +441,7 @@ namespace osu.Game.Screens.Play if (!showResults) return; - using (BeginDelayedSequence(1000)) + using (BeginDelayedSequence(RESULTS_DISPLAY_DELAY)) scheduleGotoRanking(); } From 2c012b9af1106bbc154b25453a8cd71c3eb5001b Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Mon, 20 Apr 2020 06:43:18 +0300 Subject: [PATCH 7/9] Use AddUntilStep whenever possible Avoid redundant usage --- .../Visual/Gameplay/TestSceneCompletionCancellation.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index aef173c36a..a3fb17942f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -60,9 +60,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddStep("seek to completion again", () => track.Seek(5000)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); - AddWaitStep("wait", 5); - - AddAssert("attempted to push ranking", () => ((FakeRankingPushPlayer)Player).GotoRankingInvoked); + AddUntilStep("attempted to push ranking", () => ((FakeRankingPushPlayer)Player).GotoRankingInvoked); } /// From a91c63819b0f781f1fdba608aa398a6612bb2e61 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Apr 2020 11:51:20 +0900 Subject: [PATCH 8/9] Refactor updateCompletionState implementation for legibility and code share --- osu.Game/Screens/Play/Player.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 2f3807753a..ece4c6307e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -423,8 +423,6 @@ namespace osu.Game.Screens.Play if (!this.IsCurrentScreen()) return; - // cancel push delegate in case judges reverted - // after delegate may have already been scheduled. if (!completionState.NewValue) { completionProgressDelegate?.Cancel(); @@ -433,8 +431,11 @@ namespace osu.Game.Screens.Play return; } + if (completionProgressDelegate != null) + throw new InvalidOperationException($"{nameof(updateCompletionState)} was fired more than once"); + // Only show the completion screen if the player hasn't failed - if (HealthProcessor.HasFailed || completionProgressDelegate != null) + if (HealthProcessor.HasFailed) return; ValidForResume = false; @@ -442,7 +443,7 @@ namespace osu.Game.Screens.Play if (!showResults) return; using (BeginDelayedSequence(RESULTS_DISPLAY_DELAY)) - scheduleGotoRanking(); + completionProgressDelegate = Schedule(GotoRanking); } protected virtual ScoreInfo CreateScore() @@ -694,12 +695,6 @@ namespace osu.Game.Screens.Play storyboardReplacesBackground.Value = false; } - private void scheduleGotoRanking() - { - completionProgressDelegate?.Cancel(); - completionProgressDelegate = Schedule(GotoRanking); - } - #endregion } } From 3b0099c687edce710dfcac9ac2d8d0e1a67153f4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 Apr 2020 12:26:43 +0900 Subject: [PATCH 9/9] Refactor tests --- .../TestSceneCompletionCancellation.cs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs index a3fb17942f..512584bd42 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneCompletionCancellation.cs @@ -46,46 +46,54 @@ namespace osu.Game.Tests.Visual.Gameplay [Test] public void TestCancelCompletionOnRewind() { - cancelCompletionSteps(); + complete(); + cancel(); - AddAssert("no attempt to push ranking", () => !((FakeRankingPushPlayer)Player).GotoRankingInvoked); + checkNoRanking(); } [Test] public void TestReCompleteAfterCancellation() { - cancelCompletionSteps(); - - // Attempt completing again. - AddStep("seek to completion again", () => track.Seek(5000)); - AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + complete(); + cancel(); + complete(); AddUntilStep("attempted to push ranking", () => ((FakeRankingPushPlayer)Player).GotoRankingInvoked); } /// - /// Tests whether can still pause after cancelling completion - /// by reverting back to true. + /// Tests whether can still pause after cancelling completion by reverting back to true. /// [Test] public void TestCanPauseAfterCancellation() { - cancelCompletionSteps(); + complete(); + cancel(); AddStep("pause", () => Player.Pause()); AddAssert("paused successfully", () => Player.GameplayClockContainer.IsPaused.Value); + + checkNoRanking(); } - private void cancelCompletionSteps() + private void complete() { AddStep("seek to completion", () => track.Seek(5000)); AddUntilStep("completion set by processor", () => Player.ScoreProcessor.HasCompleted.Value); + } + private void cancel() + { AddStep("rewind to cancel", () => track.Seek(4000)); AddUntilStep("completion cleared by processor", () => !Player.ScoreProcessor.HasCompleted.Value); + } + private void checkNoRanking() + { // wait to ensure there was no attempt of pushing the results screen. AddWaitStep("wait", resultsDisplayWaitCount); + AddAssert("no attempt to push ranking", () => !((FakeRankingPushPlayer)Player).GotoRankingInvoked); } protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap, Storyboard storyboard = null)