From 34457b474229b383e14a18e2d6cefd4760e1abee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Apr 2022 18:51:37 +0900 Subject: [PATCH 1/6] Expose mocked members as `virtual` on `Multiplayer` and `SpectatorClient` --- osu.Game/Online/Multiplayer/MultiplayerClient.cs | 4 ++-- osu.Game/Online/Spectator/SpectatorClient.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index 1bd1952832..18db710cee 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -42,7 +42,7 @@ namespace osu.Game.Online.Multiplayer /// /// Invoked when a user leaves the room of their own accord. /// - public event Action? UserLeft; + public virtual event Action? UserLeft; /// /// Invoked when a user was kicked from the room forcefully. @@ -107,7 +107,7 @@ namespace osu.Game.Online.Multiplayer /// /// The users in the joined which are participating in the current gameplay loop. /// - public IBindableList CurrentMatchPlayingUserIds => PlayingUserIds; + public virtual IBindableList CurrentMatchPlayingUserIds => PlayingUserIds; protected readonly BindableList PlayingUserIds = new BindableList(); diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 8f22078010..138e8ac7d6 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -54,17 +54,17 @@ namespace osu.Game.Online.Spectator /// /// Called whenever new frames arrive from the server. /// - public event Action? OnNewFrames; + public virtual event Action? OnNewFrames; /// /// Called whenever a user starts a play session, or immediately if the user is being watched and currently in a play session. /// - public event Action? OnUserBeganPlaying; + public virtual event Action? OnUserBeganPlaying; /// /// Called whenever a user finishes a play session. /// - public event Action? OnUserFinishedPlaying; + public virtual event Action? OnUserFinishedPlaying; /// /// All users currently being watched. From 0ccac24f76dbd8f137cd59cda946a1a7d416aaae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Apr 2022 19:15:46 +0900 Subject: [PATCH 2/6] Split out base implementation of `MultiplayerGameplayLeaderboard` test --- ...MultiplayerGameplayLeaderboardTestScene.cs | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs new file mode 100644 index 0000000000..eb15282f75 --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -0,0 +1,191 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Linq; +using Moq; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Testing; +using osu.Framework.Utils; +using osu.Game.Configuration; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Spectator; +using osu.Game.Replays.Legacy; +using osu.Game.Rulesets.Osu.Scoring; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; +using osu.Game.Screens.Play.HUD; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public abstract class MultiplayerGameplayLeaderboardTestScene : OsuTestScene + { + protected readonly BindableList MultiplayerUsers = new BindableList(); + private readonly BindableList multiplayerUserIds = new BindableList(); + + protected MultiplayerGameplayLeaderboard Leaderboard { get; private set; } + + private OsuConfigManager config; + + private readonly Mock spectatorClient = new Mock(); + private readonly Mock multiplayerClient = new Mock(); + + private readonly Dictionary lastHeaders = new Dictionary(); + + [BackgroundDependencyLoader] + private void load() + { + Dependencies.Cache(config = new OsuConfigManager(LocalStorage)); + Dependencies.CacheAs(spectatorClient.Object); + Dependencies.CacheAs(multiplayerClient.Object); + + // To emulate `MultiplayerClient.CurrentMatchPlayingUserIds` we need a bindable list of *only IDs*. + // This tracks the list of users 1:1. + MultiplayerUsers.BindCollectionChanged((c, e) => + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + Debug.Assert(e.NewItems != null); + + foreach (var user in e.NewItems.OfType()) + multiplayerUserIds.Add(user.UserID); + break; + + case NotifyCollectionChangedAction.Remove: + Debug.Assert(e.OldItems != null); + + foreach (var user in e.OldItems.OfType()) + multiplayerUserIds.Remove(user.UserID); + break; + + case NotifyCollectionChangedAction.Reset: + multiplayerUserIds.Clear(); + break; + } + }); + + multiplayerClient.SetupGet(c => c.CurrentMatchPlayingUserIds) + .Returns(() => multiplayerUserIds); + } + + [SetUpSteps] + public virtual void SetUpSteps() + { + AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = new APIUser + { + Username = "local", + }); + + AddStep("populate users", () => + { + MultiplayerUsers.Clear(); + for (int i = 0; i < 16; i++) + MultiplayerUsers.Add(CreateUser(i)); + }); + + AddStep("create leaderboard", () => + { + Leaderboard?.Expire(); + + OsuScoreProcessor scoreProcessor; + Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); + + var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); + + Child = scoreProcessor = new OsuScoreProcessor(); + + scoreProcessor.ApplyBeatmap(playableBeatmap); + + LoadComponentAsync(Leaderboard = CreateLeaderboard(scoreProcessor), Add); + }); + + AddUntilStep("wait for load", () => Leaderboard.IsLoaded); + } + + protected virtual MultiplayerRoomUser CreateUser(int i) => new MultiplayerRoomUser(i); + + protected abstract MultiplayerGameplayLeaderboard CreateLeaderboard(OsuScoreProcessor scoreProcessor); + + [Test] + public void TestScoreUpdates() + { + AddRepeatStep("update state", UpdateUserStatesRandomly, 100); + AddToggleStep("switch compact mode", expanded => Leaderboard.Expanded.Value = expanded); + } + + [Test] + public void TestUserQuit() + { + AddUntilStep("mark users quit", () => + { + if (MultiplayerUsers.Count == 0) + return true; + + MultiplayerUsers.RemoveAt(0); + return false; + }); + } + + [Test] + public void TestChangeScoringMode() + { + AddRepeatStep("update state", UpdateUserStatesRandomly, 5); + AddStep("change to classic", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Classic)); + AddStep("change to standardised", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised)); + } + + protected void UpdateUserStatesRandomly() + { + foreach (var user in MultiplayerUsers) + { + if (RNG.NextBool()) + continue; + + int userId = user.UserID; + + if (!lastHeaders.TryGetValue(userId, out var header)) + { + lastHeaders[userId] = header = new FrameHeader(new ScoreInfo + { + Statistics = new Dictionary + { + [HitResult.Miss] = 0, + [HitResult.Meh] = 0, + [HitResult.Great] = 0 + } + }); + } + + switch (RNG.Next(0, 3)) + { + case 0: + header.Combo = 0; + header.Statistics[HitResult.Miss]++; + break; + + case 1: + header.Combo++; + header.MaxCombo = Math.Max(header.MaxCombo, header.Combo); + header.Statistics[HitResult.Meh]++; + break; + + default: + header.Combo++; + header.MaxCombo = Math.Max(header.MaxCombo, header.Combo); + header.Statistics[HitResult.Great]++; + break; + } + + spectatorClient.Raise(s => s.OnNewFrames -= null, userId, new FrameDataBundle(header, new[] { new LegacyReplayFrame(Time.Current, 0, 0, ReplayButtonState.None) })); + } + } + } +} From b52f070fdb79fa28aafc18d85ba0da7ac0a97d5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Apr 2022 19:15:57 +0900 Subject: [PATCH 3/6] Update existing multiplayer leaderboard tests to use new mocked implementation --- ...TestSceneMultiplayerGameplayLeaderboard.cs | 151 +----------------- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 116 +++----------- 2 files changed, 31 insertions(+), 236 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs index bcd4474876..6e4aa48b0e 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboard.cs @@ -1,161 +1,22 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using System.Collections.Generic; using System.Linq; -using NUnit.Framework; -using osu.Framework.Allocation; -using osu.Framework.Extensions; -using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; -using osu.Framework.Utils; -using osu.Game.Configuration; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; -using osu.Game.Online.Multiplayer; -using osu.Game.Online.Spectator; -using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Scoring; -using osu.Game.Scoring; using osu.Game.Screens.Play.HUD; -using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerGameplayLeaderboard : MultiplayerTestScene + public class TestSceneMultiplayerGameplayLeaderboard : MultiplayerGameplayLeaderboardTestScene { - private static IEnumerable users => Enumerable.Range(0, 16); - - public new TestMultiplayerSpectatorClient SpectatorClient => (TestMultiplayerSpectatorClient)OnlinePlayDependencies?.SpectatorClient; - - private MultiplayerGameplayLeaderboard leaderboard; - private OsuConfigManager config; - - [BackgroundDependencyLoader] - private void load() + protected override MultiplayerGameplayLeaderboard CreateLeaderboard(OsuScoreProcessor scoreProcessor) { - Dependencies.Cache(config = new OsuConfigManager(LocalStorage)); - } - - public override void SetUpSteps() - { - base.SetUpSteps(); - - AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = UserLookupCache.GetUserAsync(1).GetResultSafely()); - - AddStep("create leaderboard", () => + return new MultiplayerGameplayLeaderboard(Ruleset.Value, scoreProcessor, MultiplayerUsers.ToArray()) { - leaderboard?.Expire(); - - OsuScoreProcessor scoreProcessor; - Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); - - var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); - var multiplayerUsers = new List(); - - foreach (int user in users) - { - SpectatorClient.SendStartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID); - multiplayerUsers.Add(OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = user }, true)); - } - - Children = new Drawable[] - { - scoreProcessor = new OsuScoreProcessor(), - }; - - scoreProcessor.ApplyBeatmap(playableBeatmap); - - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(Ruleset.Value, scoreProcessor, multiplayerUsers.ToArray()) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, Add); - }); - - AddUntilStep("wait for load", () => leaderboard.IsLoaded); - AddUntilStep("wait for user population", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count > 0); - } - - [Test] - public void TestScoreUpdates() - { - AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 100); - AddToggleStep("switch compact mode", expanded => leaderboard.Expanded.Value = expanded); - } - - [Test] - public void TestUserQuit() - { - foreach (int user in users) - AddStep($"mark user {user} quit", () => MultiplayerClient.RemoveUser(UserLookupCache.GetUserAsync(user).GetResultSafely().AsNonNull())); - } - - [Test] - public void TestChangeScoringMode() - { - AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 5); - AddStep("change to classic", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Classic)); - AddStep("change to standardised", () => config.SetValue(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised)); - } - - protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); - - protected class TestDependencies : MultiplayerTestSceneDependencies - { - protected override TestSpectatorClient CreateSpectatorClient() => new TestMultiplayerSpectatorClient(); - } - - public class TestMultiplayerSpectatorClient : TestSpectatorClient - { - private readonly Dictionary lastHeaders = new Dictionary(); - - public void RandomlyUpdateState() - { - foreach ((int userId, _) in WatchedUserStates) - { - if (RNG.NextBool()) - continue; - - if (!lastHeaders.TryGetValue(userId, out var header)) - { - lastHeaders[userId] = header = new FrameHeader(new ScoreInfo - { - Statistics = new Dictionary - { - [HitResult.Miss] = 0, - [HitResult.Meh] = 0, - [HitResult.Great] = 0 - } - }); - } - - switch (RNG.Next(0, 3)) - { - case 0: - header.Combo = 0; - header.Statistics[HitResult.Miss]++; - break; - - case 1: - header.Combo++; - header.MaxCombo = Math.Max(header.MaxCombo, header.Combo); - header.Statistics[HitResult.Meh]++; - break; - - default: - header.Combo++; - header.MaxCombo = Math.Max(header.MaxCombo, header.Combo); - header.Statistics[HitResult.Great]++; - break; - } - - ((ISpectatorClient)this).UserSentFrames(userId, new FrameDataBundle(header, new[] { new LegacyReplayFrame(Time.Current, 0, 0, ReplayButtonState.None) })); - } - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; } } } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 7f5aced925..56a4f053c5 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -1,121 +1,55 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using System.Linq; -using NUnit.Framework; -using osu.Framework.Extensions; using osu.Framework.Graphics; using osu.Framework.Utils; -using osu.Game.Online.API; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus; -using osu.Game.Online.Rooms; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Screens.OnlinePlay.Multiplayer; using osu.Game.Screens.Play.HUD; -using osu.Game.Tests.Visual.OnlinePlay; -using osu.Game.Tests.Visual.Spectator; namespace osu.Game.Tests.Visual.Multiplayer { - public class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerTestScene + public class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerGameplayLeaderboardTestScene { - private static IEnumerable users => Enumerable.Range(0, 16); - - public new TestSceneMultiplayerGameplayLeaderboard.TestMultiplayerSpectatorClient SpectatorClient => - (TestSceneMultiplayerGameplayLeaderboard.TestMultiplayerSpectatorClient)OnlinePlayDependencies?.SpectatorClient; - - protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies(); - - protected class TestDependencies : MultiplayerTestSceneDependencies + protected override MultiplayerRoomUser CreateUser(int i) { - protected override TestSpectatorClient CreateSpectatorClient() => new TestSceneMultiplayerGameplayLeaderboard.TestMultiplayerSpectatorClient(); + var user = base.CreateUser(i); + user.MatchState = new TeamVersusUserState + { + TeamID = RNG.Next(0, 2) + }; + return user; } - private MultiplayerGameplayLeaderboard leaderboard; - private GameplayMatchScoreDisplay gameplayScoreDisplay; - - protected override Room CreateRoom() - { - var room = base.CreateRoom(); - room.Type.Value = MatchType.TeamVersus; - return room; - } + protected override MultiplayerGameplayLeaderboard CreateLeaderboard(OsuScoreProcessor scoreProcessor) => + new MultiplayerGameplayLeaderboard(Ruleset.Value, scoreProcessor, MultiplayerUsers.ToArray()) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }; public override void SetUpSteps() { base.SetUpSteps(); - AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = UserLookupCache.GetUserAsync(1).GetResultSafely()); - - AddStep("create leaderboard", () => + AddStep("Add external display components", () => { - leaderboard?.Expire(); - - OsuScoreProcessor scoreProcessor; - Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); - - var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); - var multiplayerUsers = new List(); - - foreach (int user in users) + LoadComponentAsync(new MatchScoreDisplay { - SpectatorClient.SendStartPlay(user, Beatmap.Value.BeatmapInfo.OnlineID); - var roomUser = OnlinePlayDependencies.MultiplayerClient.AddUser(new APIUser { Id = user }, true); + Team1Score = { BindTarget = Leaderboard.TeamScores[0] }, + Team2Score = { BindTarget = Leaderboard.TeamScores[1] } + }, Add); - roomUser.MatchState = new TeamVersusUserState - { - TeamID = RNG.Next(0, 2) - }; - - multiplayerUsers.Add(roomUser); - } - - Children = new Drawable[] + LoadComponentAsync(new GameplayMatchScoreDisplay { - scoreProcessor = new OsuScoreProcessor(), - }; - - scoreProcessor.ApplyBeatmap(playableBeatmap); - - LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(Ruleset.Value, scoreProcessor, multiplayerUsers.ToArray()) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - }, gameplayLeaderboard => - { - LoadComponentAsync(new MatchScoreDisplay - { - Team1Score = { BindTarget = leaderboard.TeamScores[0] }, - Team2Score = { BindTarget = leaderboard.TeamScores[1] } - }, Add); - - LoadComponentAsync(gameplayScoreDisplay = new GameplayMatchScoreDisplay - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Team1Score = { BindTarget = leaderboard.TeamScores[0] }, - Team2Score = { BindTarget = leaderboard.TeamScores[1] } - }, Add); - - Add(gameplayLeaderboard); - }); - }); - - AddUntilStep("wait for load", () => leaderboard.IsLoaded); - AddUntilStep("wait for user population", () => MultiplayerClient.CurrentMatchPlayingUserIds.Count > 0); - } - - [Test] - public void TestScoreUpdates() - { - AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 100); - AddToggleStep("switch compact mode", expanded => - { - leaderboard.Expanded.Value = expanded; - gameplayScoreDisplay.Expanded.Value = expanded; + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Team1Score = { BindTarget = Leaderboard.TeamScores[0] }, + Team2Score = { BindTarget = Leaderboard.TeamScores[1] } + }, Add); }); } } From 6a61fd95eb3e5b0b6bfdab55c8ed78b89ce9025c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Apr 2022 19:19:45 +0900 Subject: [PATCH 4/6] Tidy up base implementation --- ...MultiplayerGameplayLeaderboardTestScene.cs | 21 +++++++++---------- ...ceneMultiplayerGameplayLeaderboardTeams.cs | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs index eb15282f75..7c8a61b231 100644 --- a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -28,10 +28,15 @@ namespace osu.Game.Tests.Visual.Multiplayer public abstract class MultiplayerGameplayLeaderboardTestScene : OsuTestScene { protected readonly BindableList MultiplayerUsers = new BindableList(); - private readonly BindableList multiplayerUserIds = new BindableList(); protected MultiplayerGameplayLeaderboard Leaderboard { get; private set; } + protected virtual MultiplayerRoomUser CreateUser(int userId) => new MultiplayerRoomUser(userId); + + protected abstract MultiplayerGameplayLeaderboard CreateLeaderboard(OsuScoreProcessor scoreProcessor); + + private readonly BindableList multiplayerUserIds = new BindableList(); + private OsuConfigManager config; private readonly Mock spectatorClient = new Mock(); @@ -81,7 +86,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = new APIUser { - Username = "local", + Id = 1, }); AddStep("populate users", () => @@ -95,25 +100,19 @@ namespace osu.Game.Tests.Visual.Multiplayer { Leaderboard?.Expire(); - OsuScoreProcessor scoreProcessor; Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value); - var playableBeatmap = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value); - - Child = scoreProcessor = new OsuScoreProcessor(); - + OsuScoreProcessor scoreProcessor = new OsuScoreProcessor(); scoreProcessor.ApplyBeatmap(playableBeatmap); + Child = scoreProcessor; + LoadComponentAsync(Leaderboard = CreateLeaderboard(scoreProcessor), Add); }); AddUntilStep("wait for load", () => Leaderboard.IsLoaded); } - protected virtual MultiplayerRoomUser CreateUser(int i) => new MultiplayerRoomUser(i); - - protected abstract MultiplayerGameplayLeaderboard CreateLeaderboard(OsuScoreProcessor scoreProcessor); - [Test] public void TestScoreUpdates() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index 56a4f053c5..b37ba470ed 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -14,9 +14,9 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMultiplayerGameplayLeaderboardTeams : MultiplayerGameplayLeaderboardTestScene { - protected override MultiplayerRoomUser CreateUser(int i) + protected override MultiplayerRoomUser CreateUser(int userId) { - var user = base.CreateUser(i); + var user = base.CreateUser(userId); user.MatchState = new TeamVersusUserState { TeamID = RNG.Next(0, 2) From 09d560c93e7a04f7fa9389ba68678c13b76a6f7c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 11 Apr 2022 19:27:14 +0900 Subject: [PATCH 5/6] Add test coverage of spectator requests --- .../MultiplayerGameplayLeaderboardTestScene.cs | 14 ++++++++++++++ osu.Game/Online/Spectator/SpectatorClient.cs | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs index 7c8a61b231..98e6cd514b 100644 --- a/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs +++ b/osu.Game.Tests/Visual/Multiplayer/MultiplayerGameplayLeaderboardTestScene.cs @@ -84,6 +84,8 @@ namespace osu.Game.Tests.Visual.Multiplayer [SetUpSteps] public virtual void SetUpSteps() { + AddStep("reset counts", () => spectatorClient.Invocations.Clear()); + AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = new APIUser { Id = 1, @@ -111,6 +113,12 @@ namespace osu.Game.Tests.Visual.Multiplayer }); AddUntilStep("wait for load", () => Leaderboard.IsLoaded); + + AddStep("check watch requests were sent", () => + { + foreach (var user in MultiplayerUsers) + spectatorClient.Verify(s => s.WatchUser(user.UserID), Times.Once); + }); } [Test] @@ -131,6 +139,12 @@ namespace osu.Game.Tests.Visual.Multiplayer MultiplayerUsers.RemoveAt(0); return false; }); + + AddStep("check stop watching requests were sent", () => + { + foreach (var user in MultiplayerUsers) + spectatorClient.Verify(s => s.StopWatchingUser(user.UserID), Times.Once); + }); } [Test] diff --git a/osu.Game/Online/Spectator/SpectatorClient.cs b/osu.Game/Online/Spectator/SpectatorClient.cs index 138e8ac7d6..78beda6298 100644 --- a/osu.Game/Online/Spectator/SpectatorClient.cs +++ b/osu.Game/Online/Spectator/SpectatorClient.cs @@ -221,7 +221,7 @@ namespace osu.Game.Online.Spectator }); } - public void WatchUser(int userId) + public virtual void WatchUser(int userId) { Debug.Assert(ThreadSafety.IsUpdateThread); From a0e3a2102acd70cf3fc24e35bd70c647d7d40db3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Apr 2022 10:49:57 +0900 Subject: [PATCH 6/6] Also expand match score component when leaderboard is (in test) --- .../TestSceneMultiplayerGameplayLeaderboardTeams.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs index b37ba470ed..5cd3bb2f0f 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerGameplayLeaderboardTeams.cs @@ -48,7 +48,8 @@ namespace osu.Game.Tests.Visual.Multiplayer Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, Team1Score = { BindTarget = Leaderboard.TeamScores[0] }, - Team2Score = { BindTarget = Leaderboard.TeamScores[1] } + Team2Score = { BindTarget = Leaderboard.TeamScores[1] }, + Expanded = { BindTarget = Leaderboard.Expanded }, }, Add); }); }