From 1f01714ec207c4fb4090efe72769234037bc9071 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Apr 2022 17:02:53 +0900 Subject: [PATCH] Apply initial structural changes to `TestSceneMatchStartControl` --- .../Multiplayer/TestSceneMatchStartControl.cs | 233 +++++++++++------- 1 file changed, 148 insertions(+), 85 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs index 5c2fd26857..dcf73f9633 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchStartControl.cs @@ -3,74 +3,119 @@ using System; using System.Linq; +using Moq; using NUnit.Framework; using osu.Framework.Allocation; -using osu.Framework.Audio; using osu.Framework.Bindables; using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.UserInterface; -using osu.Framework.Platform; using osu.Framework.Testing; using osu.Framework.Utils; -using osu.Game.Beatmaps; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.Countdown; using osu.Game.Online.Rooms; -using osu.Game.Rulesets; +using osu.Game.Screens.OnlinePlay; using osu.Game.Screens.OnlinePlay.Multiplayer.Match; -using osu.Game.Tests.Resources; using osuTK; using osuTK.Input; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMatchStartControl : MultiplayerTestScene + public class TestSceneMatchStartControl : OsuManualInputManagerTestScene { + private readonly Mock multiplayerClient = new Mock(); + private readonly Mock availabilityTracker = new Mock(); + + private readonly Bindable beatmapAvailability = new Bindable(); + private readonly Bindable room = new Bindable(); + + private MultiplayerRoom multiplayerRoom; + private MultiplayerRoomUser localUser; + private OngoingOperationTracker ongoingOperationTracker; + + private PopoverContainer content; private MatchStartControl control; - private BeatmapSetInfo importedSet; - private readonly Bindable selectedItem = new Bindable(); - - private BeatmapManager beatmaps; - private RulesetStore rulesets; + protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) => + new CachedModelDependencyContainer(base.CreateChildDependencies(parent)) { Model = { BindTarget = room } }; [BackgroundDependencyLoader] - private void load(GameHost host, AudioManager audio) + private void load() { - Dependencies.Cache(rulesets = new RealmRulesetStore(Realm)); - Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, Realm, rulesets, null, audio, Resources, host, Beatmap.Default)); - Dependencies.Cache(Realm); + Dependencies.CacheAs(multiplayerClient.Object); + Dependencies.CacheAs(ongoingOperationTracker = new OngoingOperationTracker()); + + availabilityTracker.SetupGet(a => a.Availability).Returns(beatmapAvailability); + Dependencies.CacheAs(availabilityTracker.Object); + + multiplayerClient.SetupGet(m => m.LocalUser).Returns(() => localUser); + multiplayerClient.SetupGet(m => m.Room).Returns(() => multiplayerRoom); + + // By default, the local user is to be the host. + multiplayerClient.SetupGet(m => m.IsHost).Returns(true); + + // Assume all state changes are accepted by the server. + multiplayerClient.Setup(m => m.ChangeState(It.IsAny())) + .Callback((MultiplayerUserState r) => + { + localUser.State = r; + raiseRoomUpdated(); + }); + + Children = new Drawable[] + { + ongoingOperationTracker, + content = new PopoverContainer { RelativeSizeAxes = Axes.Both } + }; } - [SetUp] - public new void Setup() => Schedule(() => + [SetUpSteps] + public void SetUpSteps() { - AvailabilityTracker.SelectedItem.BindTo(selectedItem); - - beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); - importedSet = beatmaps.GetAllUsableBeatmapSets().First(); - Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()); - - selectedItem.Value = new PlaylistItem(Beatmap.Value.BeatmapInfo) + AddStep("reset state", () => { - RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID - }; + multiplayerClient.Invocations.Clear(); - Child = new PopoverContainer + beatmapAvailability.Value = BeatmapAvailability.LocallyAvailable(); + + var playlistItem = new PlaylistItem(Beatmap.Value.BeatmapInfo) + { + RulesetID = Beatmap.Value.BeatmapInfo.Ruleset.OnlineID + }; + + room.Value = new Room + { + Playlist = { playlistItem }, + CurrentPlaylistItem = { Value = playlistItem } + }; + + multiplayerRoom = new MultiplayerRoom(0) + { + Playlist = + { + new MultiplayerPlaylistItem(playlistItem), + }, + Users = + { + (localUser = new MultiplayerRoomUser(API.LocalUser.Value.Id) { User = API.LocalUser.Value }), + } + }; + }); + + AddStep("create control", () => { - RelativeSizeAxes = Axes.Both, - Child = control = new MatchStartControl + content.Child = control = new MatchStartControl { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(250, 50), - } - }; - }); + }; + }); + } [Test] public void TestStartWithCountdown() @@ -85,8 +130,12 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.Click(MouseButton.Left); }); - AddStep("finish countdown", () => MultiplayerClient.SkipToEndOfCountdown()); - AddUntilStep("match started", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.WaitingForLoad); + AddStep("check request received", () => + { + multiplayerClient.Verify(m => m.SendMatchRequest(It.Is(req => + req.Duration == TimeSpan.FromSeconds(10) + )), Times.Once); + }); } [Test] @@ -110,7 +159,7 @@ namespace osu.Game.Tests.Visual.Multiplayer InputManager.Click(MouseButton.Left); }); - AddStep("finish countdown", () => MultiplayerClient.SkipToEndOfCountdown()); + // AddStep("finish countdown", skipToEndOfCountdown); AddUntilStep("match not started", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); } @@ -119,32 +168,32 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add second user as host", () => { - MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); - MultiplayerClient.TransferHost(2); + addUser(new APIUser { Id = 2, Username = "Another user" }); + multiplayerClient.Object.TransferHost(2); }); - AddStep("start with countdown", () => MultiplayerClient.SendMatchRequest(new StartMatchCountdownRequest { Duration = TimeSpan.FromMinutes(2) }).WaitSafely()); + AddStep("start with countdown", () => multiplayerClient.Object.SendMatchRequest(new StartMatchCountdownRequest { Duration = TimeSpan.FromMinutes(2) }).WaitSafely()); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); - AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Idle); } [Test] public void TestCountdownWhileSpectating() { - AddStep("set spectating", () => MultiplayerClient.ChangeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); - AddUntilStep("local user is spectating", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Spectating); + AddStep("set spectating", () => changeUserState(API.LocalUser.Value.OnlineID, MultiplayerUserState.Spectating)); + AddUntilStep("local user is spectating", () => multiplayerClient.Object.LocalUser?.State == MultiplayerUserState.Spectating); AddAssert("countdown button is visible", () => this.ChildrenOfType().Single().IsPresent); AddAssert("countdown button enabled", () => this.ChildrenOfType().Single().Enabled.Value); - AddStep("add second user", () => MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" })); + AddStep("add second user", () => addUser(new APIUser { Id = 2, Username = "Another user" })); AddAssert("countdown button enabled", () => this.ChildrenOfType().Single().Enabled.Value); - AddStep("set second user ready", () => MultiplayerClient.ChangeUserState(2, MultiplayerUserState.Ready)); + AddStep("set second user ready", () => changeUserState(2, MultiplayerUserState.Ready)); AddAssert("countdown button enabled", () => this.ChildrenOfType().Single().Enabled.Value); } @@ -153,44 +202,44 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add second user as host", () => { - MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); - MultiplayerClient.TransferHost(2); + addUser(new APIUser { Id = 2, Username = "Another user" }); + multiplayerClient.Object.TransferHost(2); }); - AddStep("start countdown", () => MultiplayerClient.SendMatchRequest(new StartMatchCountdownRequest { Duration = TimeSpan.FromMinutes(1) }).WaitSafely()); - AddUntilStep("countdown started", () => MultiplayerClient.Room?.Countdown != null); + AddStep("start countdown", () => multiplayerClient.Object.SendMatchRequest(new StartMatchCountdownRequest { Duration = TimeSpan.FromMinutes(1) }).WaitSafely()); + AddUntilStep("countdown started", () => multiplayerClient.Object.Room?.Countdown != null); - AddStep("transfer host to local user", () => MultiplayerClient.TransferHost(API.LocalUser.Value.OnlineID)); - AddUntilStep("local user is host", () => MultiplayerClient.Room?.Host?.Equals(MultiplayerClient.LocalUser) == true); + AddStep("transfer host to local user", () => multiplayerClient.Object.TransferHost(API.LocalUser.Value.OnlineID)); + AddUntilStep("local user is host", () => multiplayerClient.Object.Room?.Host?.Equals(multiplayerClient.Object.LocalUser) == true); ClickButtonWhenEnabled(); - AddUntilStep("local user became ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); - AddAssert("countdown still active", () => MultiplayerClient.Room?.Countdown != null); + AddUntilStep("local user became ready", () => multiplayerClient.Object.LocalUser?.State == MultiplayerUserState.Ready); + AddAssert("countdown still active", () => multiplayerClient.Object.Room?.Countdown != null); } [Test] public void TestCountdownButtonVisibilityWithAutoStartEnablement() { ClickButtonWhenEnabled(); - AddUntilStep("local user became ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); + AddUntilStep("local user became ready", () => multiplayerClient.Object.LocalUser?.State == MultiplayerUserState.Ready); AddUntilStep("countdown button visible", () => this.ChildrenOfType().Single().IsPresent); - AddStep("enable auto start", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { AutoStartDuration = TimeSpan.FromMinutes(1) }).WaitSafely()); + AddStep("enable auto start", () => multiplayerClient.Object.ChangeSettings(new MultiplayerRoomSettings { AutoStartDuration = TimeSpan.FromMinutes(1) }).WaitSafely()); ClickButtonWhenEnabled(); - AddUntilStep("local user became ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); + AddUntilStep("local user became ready", () => multiplayerClient.Object.LocalUser?.State == MultiplayerUserState.Ready); AddUntilStep("countdown button not visible", () => !this.ChildrenOfType().Single().IsPresent); } [Test] public void TestClickingReadyButtonUnReadiesDuringAutoStart() { - AddStep("enable auto start", () => MultiplayerClient.ChangeSettings(new MultiplayerRoomSettings { AutoStartDuration = TimeSpan.FromMinutes(1) }).WaitSafely()); + AddStep("enable auto start", () => multiplayerClient.Object.ChangeSettings(new MultiplayerRoomSettings { AutoStartDuration = TimeSpan.FromMinutes(1) }).WaitSafely()); ClickButtonWhenEnabled(); - AddUntilStep("local user became ready", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Ready); + AddUntilStep("local user became ready", () => multiplayerClient.Object.LocalUser?.State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); - AddUntilStep("local user became idle", () => MultiplayerClient.LocalUser?.State == MultiplayerUserState.Idle); + AddUntilStep("local user became idle", () => multiplayerClient.Object.LocalUser?.State == MultiplayerUserState.Idle); } [Test] @@ -204,9 +253,9 @@ namespace osu.Game.Tests.Visual.Multiplayer return readyButton.Enabled.Value; }); - AddStep("delete beatmap", () => beatmaps.Delete(importedSet)); + // TODO: AddStep("delete beatmap", () => beatmaps.Delete(importedSet)); AddUntilStep("ready button disabled", () => !readyButton.Enabled.Value); - AddStep("undelete beatmap", () => beatmaps.Undelete(importedSet)); + // TODO: AddStep("undelete beatmap", () => beatmaps.Undelete(importedSet)); AddUntilStep("ready button enabled back", () => readyButton.Enabled.Value); } @@ -215,15 +264,15 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add second user as host", () => { - MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); - MultiplayerClient.TransferHost(2); + addUser(new APIUser { Id = 2, Username = "Another user" }); + multiplayerClient.Object.TransferHost(2); }); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); - AddUntilStep("user is idle", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Idle); } [TestCase(true)] @@ -232,14 +281,14 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("setup", () => { - MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0); + multiplayerClient.Object.TransferHost(multiplayerClient.Object.Room?.Users[0].UserID ?? 0); if (!allReady) - MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); + addUser(new APIUser { Id = 2, Username = "Another user" }); }); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Ready); verifyGameplayStartFlow(); } @@ -249,12 +298,12 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("add host", () => { - MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); - MultiplayerClient.TransferHost(2); + addUser(new APIUser { Id = 2, Username = "Another user" }); + multiplayerClient.Object.TransferHost(2); }); ClickButtonWhenEnabled(); - AddStep("make user host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0)); + AddStep("make user host", () => multiplayerClient.Object.TransferHost(multiplayerClient.Object.Room?.Users[0].UserID ?? 0)); verifyGameplayStartFlow(); } @@ -264,17 +313,17 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("setup", () => { - MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0); - MultiplayerClient.AddUser(new APIUser { Id = 2, Username = "Another user" }); + multiplayerClient.Object.TransferHost(multiplayerClient.Object.Room?.Users[0].UserID ?? 0); + addUser(new APIUser { Id = 2, Username = "Another user" }); }); ClickButtonWhenEnabled(); - AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Ready); - AddStep("transfer host", () => MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[1].UserID ?? 0)); + AddStep("transfer host", () => multiplayerClient.Object.TransferHost(multiplayerClient.Object.Room?.Users[1].UserID ?? 0)); ClickButtonWhenEnabled(); - AddUntilStep("user is idle (match not started)", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Idle); + AddUntilStep("user is idle (match not started)", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Idle); AddUntilStep("ready button enabled", () => control.ChildrenOfType().Single().Enabled.Value); } @@ -285,42 +334,56 @@ namespace osu.Game.Tests.Visual.Multiplayer const int users = 10; AddStep("setup", () => { - MultiplayerClient.TransferHost(MultiplayerClient.Room?.Users[0].UserID ?? 0); + multiplayerClient.Object.TransferHost(multiplayerClient.Object.Room?.Users[0].UserID ?? 0); for (int i = 0; i < users; i++) - MultiplayerClient.AddUser(new APIUser { Id = i, Username = "Another user" }); + addUser(new APIUser { Id = i, Username = "Another user" }); }); if (!isHost) - AddStep("transfer host", () => MultiplayerClient.TransferHost(2)); + AddStep("transfer host", () => multiplayerClient.Object.TransferHost(2)); ClickButtonWhenEnabled(); AddRepeatStep("change user ready state", () => { - MultiplayerClient.ChangeUserState(RNG.Next(0, users), RNG.NextBool() ? MultiplayerUserState.Ready : MultiplayerUserState.Idle); + changeUserState(RNG.Next(0, users), RNG.NextBool() ? MultiplayerUserState.Ready : MultiplayerUserState.Idle); }, 20); AddRepeatStep("ready all users", () => { - var nextUnready = MultiplayerClient.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); + var nextUnready = multiplayerClient.Object.Room?.Users.FirstOrDefault(c => c.State == MultiplayerUserState.Idle); if (nextUnready != null) - MultiplayerClient.ChangeUserState(nextUnready.UserID, MultiplayerUserState.Ready); + changeUserState(nextUnready.UserID, MultiplayerUserState.Ready); }, users); } private void verifyGameplayStartFlow() { - AddUntilStep("user is ready", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.Ready); + AddUntilStep("user is ready", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.Ready); ClickButtonWhenEnabled(); - AddUntilStep("user waiting for load", () => MultiplayerClient.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad); + AddUntilStep("user waiting for load", () => multiplayerClient.Object.Room?.Users[0].State == MultiplayerUserState.WaitingForLoad); AddStep("finish gameplay", () => { - MultiplayerClient.ChangeUserState(MultiplayerClient.Room?.Users[0].UserID ?? 0, MultiplayerUserState.Loaded); - MultiplayerClient.ChangeUserState(MultiplayerClient.Room?.Users[0].UserID ?? 0, MultiplayerUserState.FinishedPlay); + changeUserState(multiplayerClient.Object.Room?.Users[0].UserID ?? 0, MultiplayerUserState.Loaded); + changeUserState(multiplayerClient.Object.Room?.Users[0].UserID ?? 0, MultiplayerUserState.FinishedPlay); }); AddUntilStep("ready button enabled", () => control.ChildrenOfType().Single().Enabled.Value); } + + private void changeUserState(int userId, MultiplayerUserState newState) + { + multiplayerRoom.Users.Single(u => u.UserID == userId).State = newState; + raiseRoomUpdated(); + } + + private void addUser(APIUser user) + { + multiplayerRoom.Users.Add(new MultiplayerRoomUser(user.Id) { User = user }); + raiseRoomUpdated(); + } + + private void raiseRoomUpdated() => multiplayerClient.Raise(m => m.RoomUpdated -= null); } }