diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs index 5ff2e9c439..d7edb33c42 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerScoreSubmission.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using osu.Framework.Screens; using osu.Game.Beatmaps; @@ -10,10 +11,13 @@ using osu.Game.Online.API; using osu.Game.Online.Rooms; using osu.Game.Online.Solo; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko; +using osu.Game.Scoring; using osu.Game.Screens.Ranking; using osu.Game.Tests.Beatmaps; @@ -32,7 +36,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override bool HasCustomSteps => true; - protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(false); + protected override TestPlayer CreatePlayer(Ruleset ruleset) => new NonImportingPlayer(false); protected override Ruleset CreatePlayerRuleset() => createCustomRuleset?.Invoke() ?? new OsuRuleset(); @@ -86,6 +90,46 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("ensure passing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == true); } + [Test] + public void TestSubmissionForDifferentRuleset() + { + prepareTokenResponse(true); + + createPlayerTest(createRuleset: () => new TaikoRuleset()); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + + addFakeHit(); + + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + AddAssert("ensure passing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == true); + AddAssert("submitted score has correct ruleset ID", () => Player.SubmittedScore?.ScoreInfo.RulesetID == new TaikoRuleset().RulesetInfo.ID); + } + + [Test] + public void TestSubmissionForConvertedBeatmap() + { + prepareTokenResponse(true); + + createPlayerTest(createRuleset: () => new ManiaRuleset(), createBeatmap: _ => createTestBeatmap(new OsuRuleset().RulesetInfo)); + + AddUntilStep("wait for token request", () => Player.TokenCreationRequested); + + AddUntilStep("wait for track to start running", () => Beatmap.Value.Track.IsRunning); + + addFakeHit(); + + AddStep("seek to completion", () => Player.GameplayClockContainer.Seek(Player.DrawableRuleset.Objects.Last().GetEndTime())); + + AddUntilStep("results displayed", () => Player.GetChildScreen() is ResultsScreen); + AddAssert("ensure passing submission", () => Player.SubmittedScore?.ScoreInfo.Passed == true); + AddAssert("submitted score has correct ruleset ID", () => Player.SubmittedScore?.ScoreInfo.RulesetID == new ManiaRuleset().RulesetInfo.ID); + } + [Test] public void TestNoSubmissionOnExitWithNoToken() { @@ -242,5 +286,33 @@ namespace osu.Game.Tests.Visual.Gameplay }); }); } + + private class NonImportingPlayer : TestPlayer + { + public NonImportingPlayer(bool allowPause = true, bool showResults = true, bool pauseOnFocusLost = false) + : base(allowPause, showResults, pauseOnFocusLost) + { + } + + protected override Task ImportScore(Score score) + { + // It was discovered that Score members could sometimes be half-populated. + // In particular, the RulesetID property could be set to 0 even on non-osu! maps. + // We want to test that the state of that property is consistent in this test. + // EF makes this impossible. + // + // First off, because of the EF navigational property-explicit foreign key field duality, + // it can happen that - for example - the Ruleset navigational property is correctly initialised to mania, + // but the RulesetID foreign key property is not initialised and remains 0. + // EF silently bypasses this by prioritising the Ruleset navigational property over the RulesetID foreign key one. + // + // Additionally, adding an entity to an EF DbSet CAUSES SIDE EFFECTS with regard to the foreign key property. + // In the above instance, if a ScoreInfo with Ruleset = {mania} and RulesetID = 0 is attached to an EF context, + // RulesetID WILL BE SILENTLY SET TO THE CORRECT VALUE of 3. + // + // For the above reasons, importing is disabled in this test. + return Task.CompletedTask; + } + } } }