From 952bc96bbf3223b2415a486c3b8b922e57328ee4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:05:38 +0900 Subject: [PATCH 1/7] Use GameBase data sources for Beatmap/Mods/Ruleset Sourced in via OsuScreenDependencies for management --- osu.Game/Tests/Visual/OsuTestScene.cs | 40 ++++++++++----------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 4ca0ec0f7e..4a561f17a3 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -12,7 +12,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Timing; @@ -21,6 +20,7 @@ using osu.Game.Database; using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Screens; using osu.Game.Storyboards; using osu.Game.Tests.Beatmaps; @@ -28,21 +28,13 @@ namespace osu.Game.Tests.Visual { public abstract class OsuTestScene : TestScene { - [Cached(typeof(Bindable))] - [Cached(typeof(IBindable))] - private NonNullableBindable beatmap; + protected Bindable Beatmap { get; private set; } - protected Bindable Beatmap => beatmap; + protected Bindable Ruleset; - [Cached] - [Cached(typeof(IBindable))] - protected readonly Bindable Ruleset = new Bindable(); + protected Bindable> Mods; - [Cached] - [Cached(Type = typeof(IBindable>))] - protected readonly Bindable> Mods = new Bindable>(Array.Empty()); - - protected new DependencyContainer Dependencies { get; private set; } + protected new OsuScreenDependencies Dependencies { get; private set; } private readonly Lazy localStorage; protected Storage LocalStorage => localStorage.Value; @@ -72,18 +64,16 @@ namespace osu.Game.Tests.Visual protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { - // This is the earliest we can get OsuGameBase, which is used by the dummy working beatmap to find textures - var working = new DummyWorkingBeatmap(parent.Get(), parent.Get()); + Dependencies = new OsuScreenDependencies(false, base.CreateChildDependencies(parent)); - beatmap = new NonNullableBindable(working) { Default = working }; - beatmap.BindValueChanged(b => ScheduleAfterChildren(() => - { - // compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo) - if (b.OldValue?.TrackLoaded == true && b.OldValue?.Track != b.NewValue?.Track) - b.OldValue.RecycleTrack(); - })); + Beatmap = Dependencies.Beatmap; + Beatmap.SetDefault(); - Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); + Ruleset = Dependencies.Ruleset; + Ruleset.SetDefault(); + + Mods = Dependencies.Mods; + Mods.SetDefault(); if (!UseOnlineAPI) { @@ -135,8 +125,8 @@ namespace osu.Game.Tests.Visual { base.Dispose(isDisposing); - if (beatmap?.Value.TrackLoaded == true) - beatmap.Value.Track.Stop(); + if (Beatmap?.Value.TrackLoaded == true) + Beatmap.Value.Track.Stop(); if (contextFactory.IsValueCreated) contextFactory.Value.ResetDatabase(); From 395b058ff872a28cf74554088ec04f26eff319d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:05:54 +0900 Subject: [PATCH 2/7] Fix OsuScreenDependencies not caching non-leased versions --- osu.Game/Screens/OsuScreenDependencies.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osu.Game/Screens/OsuScreenDependencies.cs b/osu.Game/Screens/OsuScreenDependencies.cs index 115f4b7e1a..8d54829d49 100644 --- a/osu.Game/Screens/OsuScreenDependencies.cs +++ b/osu.Game/Screens/OsuScreenDependencies.cs @@ -26,16 +26,26 @@ namespace osu.Game.Screens Beatmap = parent.Get>()?.GetBoundCopy(); if (Beatmap == null) + { Cache(Beatmap = parent.Get>().BeginLease(false)); + CacheAs(Beatmap); + } Ruleset = parent.Get>()?.GetBoundCopy(); if (Ruleset == null) + { Cache(Ruleset = parent.Get>().BeginLease(true)); + CacheAs(Ruleset); + } Mods = parent.Get>>()?.GetBoundCopy(); + if (Mods == null) + { Cache(Mods = parent.Get>>().BeginLease(true)); + CacheAs(Mods); + } } else { From 3dc2b59d2a066e4827f52aff6c7951cd72cfddd4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:06:12 +0900 Subject: [PATCH 3/7] Move variable above common bindables --- osu.Game/Screens/OsuScreen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/OsuScreen.cs b/osu.Game/Screens/OsuScreen.cs index 94165fe4b7..6394fb8d23 100644 --- a/osu.Game/Screens/OsuScreen.cs +++ b/osu.Game/Screens/OsuScreen.cs @@ -87,12 +87,12 @@ namespace osu.Game.Screens public virtual float BackgroundParallaxAmount => 1; + public virtual bool AllowRateAdjustments => true; + public Bindable Beatmap { get; private set; } public Bindable Ruleset { get; private set; } - public virtual bool AllowRateAdjustments => true; - public Bindable> Mods { get; private set; } protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 7033974733537e4d32984f4efeae2c578534fc04 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:06:56 +0900 Subject: [PATCH 4/7] Fix test regressions (incorrect from the start) --- .../TestSceneDrawableHitObjectsHidden.cs | 6 ++++-- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs | 5 +++-- osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs | 5 +++-- osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs | 5 +++-- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 +- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs index f6d26addaa..08107e01eb 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjectsHidden.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using NUnit.Framework; using osu.Game.Rulesets.Catch.Mods; namespace osu.Game.Rulesets.Catch.Tests @@ -12,9 +13,10 @@ namespace osu.Game.Rulesets.Catch.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(CatchModHidden) }).ToList(); - public TestSceneDrawableHitObjectsHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new CatchModHidden() }; - } + }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs index 55c6b22146..eaba82a469 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleHidden.cs @@ -14,9 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestSceneHitCircleHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new OsuModHidden() }; - } + }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs index 2a9c1d167b..a1795fb877 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSliderHidden.cs @@ -14,9 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestSceneSliderHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new OsuModHidden() }; - } + }); } } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs index a0ab1908d6..2976d4fdce 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneSpinnerHidden.cs @@ -14,9 +14,10 @@ namespace osu.Game.Rulesets.Osu.Tests { public override IReadOnlyList RequiredTypes => base.RequiredTypes.Concat(new[] { typeof(OsuModHidden) }).ToList(); - public TestSceneSpinnerHidden() + [SetUp] + public void SetUp() => Schedule(() => { Mods.Value = new[] { new OsuModHidden() }; - } + }); } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index be50200e1c..8cf2d29906 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.UserInterface var easierMods = instance.GetModsFor(ModType.DifficultyReduction); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); - AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; }); + AddStep("set mods externally", () => { Mods.Value = new[] { noFailMod }; }); changeRuleset(rulesetOsu); From a1f8ab1735b755bd98b27697dbf3f99828716f28 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:13:53 +0900 Subject: [PATCH 5/7] Fix unrequired type keyword --- osu.Game/OsuGameBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs index f310da3883..207fb91aab 100644 --- a/osu.Game/OsuGameBase.cs +++ b/osu.Game/OsuGameBase.cs @@ -80,7 +80,7 @@ namespace osu.Game // todo: move this to SongSelect once Screen has the ability to unsuspend. [Cached] - [Cached(Type = typeof(IBindable>))] + [Cached(typeof(IBindable>))] protected readonly Bindable> Mods = new Bindable>(Array.Empty()); protected Bindable Beatmap { get; private set; } // cached via load() method From 0bbaf9b7fbe760d4b57ca66bf82c114e952cf824 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:21:35 +0900 Subject: [PATCH 6/7] Fix mod select overlay tests not running individually --- .../TestSceneModSelectOverlay.cs | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 8cf2d29906..5f77116c67 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -8,13 +8,16 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Testing; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Overlays.Mods; using osu.Game.Overlays.Mods.Sections; using osu.Game.Rulesets; +using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play.HUD; @@ -48,42 +51,48 @@ namespace osu.Game.Tests.Visual.UserInterface private void load(RulesetStore rulesets) { this.rulesets = rulesets; + } - Add(modSelect = new TestModSelectOverlay + [SetUp] + public void SetUp() => Schedule(() => + { + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Origin = Anchor.BottomCentre, - Anchor = Anchor.BottomCentre, - }); + modSelect = new TestModSelectOverlay + { + RelativeSizeAxes = Axes.X, + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + }, - Add(modDisplay = new ModDisplay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - AutoSizeAxes = Axes.Both, - Position = new Vector2(0, 25), - }); + modDisplay = new ModDisplay + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + AutoSizeAxes = Axes.Both, + Position = new Vector2(0, 25), + Current = { BindTarget = modSelect.SelectedMods } + } + }; + }); - modDisplay.Current.UnbindBindings(); - modDisplay.Current.BindTo(modSelect.SelectedMods); - - AddStep("Show", modSelect.Show); - AddStep("Toggle", modSelect.ToggleVisibility); - AddStep("Toggle", modSelect.ToggleVisibility); + [SetUpSteps] + public void SetUpSteps() + { + AddStep("show", () => modSelect.Show()); } [Test] public void TestOsuMods() { - var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0); - changeRuleset(ruleset); + changeRuleset(0); - var instance = ruleset.CreateInstance(); + var osu = new OsuRuleset(); - var easierMods = instance.GetModsFor(ModType.DifficultyReduction); - var harderMods = instance.GetModsFor(ModType.DifficultyIncrease); + var easierMods = osu.GetModsFor(ModType.DifficultyReduction); + var harderMods = osu.GetModsFor(ModType.DifficultyIncrease); - var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); + var noFailMod = osu.GetModsFor(ModType.DifficultyReduction).FirstOrDefault(m => m is OsuModNoFail); var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); @@ -97,8 +106,8 @@ namespace osu.Game.Tests.Visual.UserInterface testMultiMod(doubleTimeMod); testIncompatibleMods(easy, hardRock); testDeselectAll(easierMods.Where(m => !(m is MultiMod))); - testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); - testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); + testMultiplierTextColour(noFailMod, () => modSelect.LowMultiplierColour); + testMultiplierTextColour(hiddenMod, () => modSelect.HighMultiplierColour); testUnimplementedMod(spunOutMod); } @@ -106,37 +115,31 @@ namespace osu.Game.Tests.Visual.UserInterface [Test] public void TestManiaMods() { - var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3); - changeRuleset(ruleset); + changeRuleset(3); - testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); + testRankedText(new ManiaRuleset().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); } [Test] public void TestRulesetChanges() { - var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0); - var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3); + changeRuleset(0); - changeRuleset(null); - - var instance = rulesetOsu.CreateInstance(); - var easierMods = instance.GetModsFor(ModType.DifficultyReduction); - var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); + var noFailMod = new OsuRuleset().GetModsFor(ModType.DifficultyReduction).FirstOrDefault(m => m is OsuModNoFail); AddStep("set mods externally", () => { Mods.Value = new[] { noFailMod }; }); - changeRuleset(rulesetOsu); + changeRuleset(0); AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null); - changeRuleset(rulesetMania); + changeRuleset(3); - AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail)); + AddAssert("ensure mods not selected", () => modDisplay.Current.Value.Count == 0); - changeRuleset(rulesetOsu); + changeRuleset(0); - AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any()); + AddAssert("ensure mods not selected", () => modDisplay.Current.Value.Count == 0); } private void testSingleMod(Mod mod) @@ -198,19 +201,19 @@ namespace osu.Game.Tests.Visual.UserInterface selectNext(mod); AddAssert("check for any selection", () => modSelect.SelectedMods.Value.Any()); - AddStep("deselect all", modSelect.DeselectAllButton.Action.Invoke); + AddStep("deselect all", () => modSelect.DeselectAllButton.Action.Invoke()); AddAssert("check for no selection", () => !modSelect.SelectedMods.Value.Any()); } - private void testMultiplierTextColour(Mod mod, Color4 colour) + private void testMultiplierTextColour(Mod mod, Func getCorrectColour) { - checkLabelColor(Color4.White); + checkLabelColor(() => Color4.White); selectNext(mod); AddWaitStep("wait for changing colour", 1); - checkLabelColor(colour); + checkLabelColor(getCorrectColour); selectPrevious(mod); AddWaitStep("wait for changing colour", 1); - checkLabelColor(Color4.White); + checkLabelColor(() => Color4.White); } private void testRankedText(Mod mod) @@ -235,9 +238,9 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void changeRuleset(RulesetInfo ruleset) + private void changeRuleset(int? id) { - AddStep($"change ruleset to {ruleset}", () => { Ruleset.Value = ruleset; }); + AddStep($"change ruleset to {(id.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); waitForLoad(); } @@ -253,7 +256,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void checkLabelColor(Color4 color) => AddAssert("check label has expected colour", () => modSelect.MultiplierLabel.Colour.AverageColour == color); + private void checkLabelColor(Func getColour) => AddAssert("check label has expected colour", () => modSelect.MultiplierLabel.Colour.AverageColour == getColour()); private class TestModSelectOverlay : ModSelectOverlay { From f349e7ff78f9f3a7dec1851241c5478209dc8ca2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Dec 2019 20:35:34 +0900 Subject: [PATCH 7/7] Fix non-null ?? usage --- .../Visual/UserInterface/TestSceneModSelectOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5f77116c67..2738b5b8fc 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.UserInterface private void changeRuleset(int? id) { - AddStep($"change ruleset to {(id.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); + AddStep($"change ruleset to {(id?.ToString() ?? "none")}", () => { Ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault(r => r.ID == id); }); waitForLoad(); }