1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 07:33:20 +08:00

Merge pull request #13657 from smoogipoo/rework-multiplayer-test-scenes

Rework multiplayer test scenes
This commit is contained in:
Dean Herbert 2021-06-30 15:04:15 +09:00 committed by GitHub
commit 162494596b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 763 additions and 697 deletions

View File

@ -7,6 +7,7 @@ using NUnit.Framework;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Testing;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
using osu.Game.Tests.Visual.Multiplayer;
using osu.Game.Users;
@ -50,7 +51,10 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
AddStep("create room initially in gameplay", () =>
{
Room.RoomID.Value = null;
var newRoom = new Room();
newRoom.CopyFrom(SelectedRoom.Value);
newRoom.RoomID.Value = null;
Client.RoomSetupAction = room =>
{
room.State = MultiplayerRoomState.Playing;
@ -61,7 +65,7 @@ namespace osu.Game.Tests.NonVisual.Multiplayer
});
};
RoomManager.CreateRoom(Room);
RoomManager.CreateRoom(newRoom);
});
AddUntilStep("wait for room join", () => Client.Room != null);

View File

@ -2,8 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
@ -232,14 +230,5 @@ namespace osu.Game.Tests.Visual.Gameplay
AddStep("load screen", () => LoadScreen(spectatorScreen = new SoloSpectator(streamingUser)));
AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded);
}
internal class TestUserLookupCache : UserLookupCache
{
protected override Task<User> ComputeValueAsync(int lookup, CancellationToken token = default) => Task.FromResult(new User
{
Id = lookup,
Username = $"User {lookup}"
});
}
}
}

View File

@ -1,61 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer
{
public abstract class RoomManagerTestScene : RoomTestScene
{
[Cached(Type = typeof(IRoomManager))]
protected TestRoomManager RoomManager { get; } = new TestRoomManager();
public override void SetUpSteps()
{
base.SetUpSteps();
AddStep("clear rooms", () => RoomManager.Rooms.Clear());
}
protected void AddRooms(int count, RulesetInfo ruleset = null)
{
AddStep("add rooms", () =>
{
for (int i = 0; i < count; i++)
{
var room = new Room
{
RoomID = { Value = i },
Name = { Value = $"Room {i}" },
Host = { Value = new User { Username = "Host" } },
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) },
Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal }
};
if (ruleset != null)
{
room.Playlist.Add(new PlaylistItem
{
Ruleset = { Value = ruleset },
Beatmap =
{
Value = new BeatmapInfo
{
Metadata = new BeatmapMetadata()
}
}
});
}
RoomManager.Rooms.Add(room);
}
});
}
}
}

View File

@ -1,35 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Bindables;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestRoomManager : IRoomManager
{
public event Action RoomsUpdated
{
add { }
remove { }
}
public readonly BindableList<Room> Rooms = new BindableList<Room>();
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
IBindableList<Room> IRoomManager.Rooms => Rooms;
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => Rooms.Add(room);
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
{
}
public void PartRoom()
{
}
}
}

View File

@ -4,17 +4,21 @@
using System;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Online.Rooms.RoomStatuses;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneLoungeRoomInfo : RoomTestScene
public class TestSceneLoungeRoomInfo : OnlinePlayTestScene
{
[SetUp]
public new void Setup() => Schedule(() =>
{
SelectedRoom.Value = new Room();
Child = new RoomInfo
{
Anchor = Anchor.Centre,
@ -23,15 +27,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
};
});
public override void SetUpSteps()
{
// Todo: Temp
}
[Test]
public void TestNonSelectedRoom()
{
AddStep("set null room", () => Room.RoomID.Value = null);
AddStep("set null room", () => SelectedRoom.Value.RoomID.Value = null);
}
[Test]
@ -39,11 +38,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("set open room", () =>
{
Room.RoomID.Value = 0;
Room.Name.Value = "Room 0";
Room.Host.Value = new User { Username = "peppy", Id = 2 };
Room.EndDate.Value = DateTimeOffset.Now.AddMonths(1);
Room.Status.Value = new RoomStatusOpen();
SelectedRoom.Value.RoomID.Value = 0;
SelectedRoom.Value.Name.Value = "Room 0";
SelectedRoom.Value.Host.Value = new User { Username = "peppy", Id = 2 };
SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMonths(1);
SelectedRoom.Value.Status.Value = new RoomStatusOpen();
});
}
}

View File

@ -3,24 +3,26 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Tests.Visual.OnlinePlay;
using osuTK.Graphics;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneLoungeRoomsContainer : RoomManagerTestScene
public class TestSceneLoungeRoomsContainer : OnlinePlayTestScene
{
protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager;
private RoomsContainer container;
[BackgroundDependencyLoader]
private void load()
[SetUp]
public new void Setup() => Schedule(() =>
{
Child = container = new RoomsContainer
{
@ -29,12 +31,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
Width = 0.5f,
JoinRequested = joinRequested
};
}
});
[Test]
public void TestBasicListChanges()
{
AddRooms(3);
AddStep("add rooms", () => RoomManager.AddRooms(3));
AddAssert("has 3 rooms", () => container.Rooms.Count == 3);
AddStep("remove first room", () => RoomManager.Rooms.Remove(RoomManager.Rooms.FirstOrDefault()));
@ -51,7 +53,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestKeyboardNavigation()
{
AddRooms(3);
AddStep("add rooms", () => RoomManager.AddRooms(3));
AddAssert("no selection", () => checkRoomSelected(null));
@ -72,7 +74,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestClickDeselection()
{
AddRooms(1);
AddStep("add room", () => RoomManager.AddRooms(1));
AddAssert("no selection", () => checkRoomSelected(null));
@ -91,7 +93,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestStringFiltering()
{
AddRooms(4);
AddStep("add rooms", () => RoomManager.AddRooms(4));
AddUntilStep("4 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 4);
@ -107,21 +109,21 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestRulesetFiltering()
{
AddRooms(2, new OsuRuleset().RulesetInfo);
AddRooms(3, new CatchRuleset().RulesetInfo);
AddStep("add rooms", () => RoomManager.AddRooms(2, new OsuRuleset().RulesetInfo));
AddStep("add rooms", () => RoomManager.AddRooms(3, new CatchRuleset().RulesetInfo));
// Todo: What even is this case...?
AddStep("set empty filter criteria", () => container.Filter(null));
AddUntilStep("5 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 5);
AddStep("filter osu! rooms", () => container.Filter(new FilterCriteria { Ruleset = new OsuRuleset().RulesetInfo }));
AddUntilStep("2 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 2);
AddStep("filter catch rooms", () => container.Filter(new FilterCriteria { Ruleset = new CatchRuleset().RulesetInfo }));
AddUntilStep("3 rooms visible", () => container.Rooms.Count(r => r.IsPresent) == 3);
}
private bool checkRoomSelected(Room room) => Room == room;
private bool checkRoomSelected(Room room) => SelectedRoom.Value == room;
private void joinRequested(Room room) => room.Status.Value = new JoinedRoomStatus();

View File

@ -11,11 +11,12 @@ using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual.OnlinePlay;
using osuTK;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMatchBeatmapDetailArea : RoomTestScene
public class TestSceneMatchBeatmapDetailArea : OnlinePlayTestScene
{
[Resolved]
private BeatmapManager beatmapManager { get; set; }
@ -26,6 +27,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
[SetUp]
public new void Setup() => Schedule(() =>
{
SelectedRoom.Value = new Room();
Child = new MatchBeatmapDetailArea
{
Anchor = Anchor.Centre,
@ -37,9 +40,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createNewItem()
{
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
ID = Room.Playlist.Count,
ID = SelectedRoom.Value.Playlist.Count,
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo },
RequiredMods =

View File

@ -7,46 +7,49 @@ using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMatchHeader : RoomTestScene
public class TestSceneMatchHeader : OnlinePlayTestScene
{
public TestSceneMatchHeader()
{
Child = new Header();
}
[SetUp]
public new void Setup() => Schedule(() =>
{
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value = new Room
{
Beatmap =
Name = { Value = "A very awesome room" },
Host = { Value = new User { Id = 2, Username = "peppy" } },
Playlist =
{
Value = new BeatmapInfo
new PlaylistItem
{
Metadata = new BeatmapMetadata
Beatmap =
{
Title = "Title",
Artist = "Artist",
AuthorString = "Author",
Value = new BeatmapInfo
{
Metadata = new BeatmapMetadata
{
Title = "Title",
Artist = "Artist",
AuthorString = "Author",
},
Version = "Version",
Ruleset = new OsuRuleset().RulesetInfo
}
},
Version = "Version",
Ruleset = new OsuRuleset().RulesetInfo
RequiredMods =
{
new OsuModDoubleTime(),
new OsuModNoFail(),
new OsuModRelax(),
}
}
},
RequiredMods =
{
new OsuModDoubleTime(),
new OsuModNoFail(),
new OsuModRelax(),
}
});
};
Room.Name.Value = "A very awesome room";
Room.Host.Value = new User { Id = 2, Username = "peppy" };
Child = new Header();
});
}
}

View File

@ -2,72 +2,74 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using Newtonsoft.Json;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Users;
using osuTK;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMatchLeaderboard : RoomTestScene
public class TestSceneMatchLeaderboard : OnlinePlayTestScene
{
protected override bool UseOnlineAPI => true;
public TestSceneMatchLeaderboard()
{
Add(new MatchLeaderboard
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f),
Scope = MatchLeaderboardScope.Overall,
});
}
[BackgroundDependencyLoader]
private void load(IAPIProvider api)
private void load()
{
var req = new GetRoomScoresRequest();
req.Success += v => { };
req.Failure += _ => { };
((DummyAPIAccess)API).HandleRequest = r =>
{
switch (r)
{
case GetRoomLeaderboardRequest leaderboardRequest:
leaderboardRequest.TriggerSuccess(new APILeaderboard
{
Leaderboard = new List<APIUserScoreAggregate>
{
new APIUserScoreAggregate
{
UserID = 2,
User = new User { Id = 2, Username = "peppy" },
TotalScore = 995533,
RoomID = 3,
CompletedBeatmaps = 1,
TotalAttempts = 6,
Accuracy = 0.9851
},
new APIUserScoreAggregate
{
UserID = 1040328,
User = new User { Id = 1040328, Username = "smoogipoo" },
TotalScore = 981100,
RoomID = 3,
CompletedBeatmaps = 1,
TotalAttempts = 9,
Accuracy = 0.937
}
}
});
return true;
}
api.Queue(req);
return false;
};
}
[SetUp]
public new void Setup() => Schedule(() =>
{
Room.RoomID.Value = 3;
SelectedRoom.Value = new Room { RoomID = { Value = 3 } };
Child = new MatchLeaderboard
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(550f, 450f),
Scope = MatchLeaderboardScope.Overall,
};
});
private class GetRoomScoresRequest : APIRequest<List<RoomScore>>
{
protected override string Target => "rooms/3/leaderboard";
}
private class RoomScore
{
[JsonProperty("user")]
public User User { get; set; }
[JsonProperty("accuracy")]
public double Accuracy { get; set; }
[JsonProperty("total_score")]
public int TotalScore { get; set; }
[JsonProperty("pp")]
public double PP { get; set; }
[JsonProperty("attempts")]
public int TotalAttempts { get; set; }
[JsonProperty("completed")]
public int CompletedAttempts { get; set; }
}
}
}

View File

@ -3,74 +3,40 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Framework.Timing;
using osu.Game.Database;
using osu.Game.Online.Spectator;
using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
using osu.Game.Screens.Play.HUD;
using osu.Game.Tests.Visual.Spectator;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiSpectatorLeaderboard : MultiplayerTestScene
{
[Cached(typeof(SpectatorClient))]
private TestSpectatorClient spectatorClient = new TestSpectatorClient();
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
protected override Container<Drawable> Content => content;
private readonly Container content;
private readonly Dictionary<int, ManualClock> clocks = new Dictionary<int, ManualClock>
{
{ PLAYER_1_ID, new ManualClock() },
{ PLAYER_2_ID, new ManualClock() }
};
public TestSceneMultiSpectatorLeaderboard()
{
base.Content.AddRange(new Drawable[]
{
spectatorClient,
lookupCache,
content = new Container { RelativeSizeAxes = Axes.Both }
});
}
private Dictionary<int, ManualClock> clocks;
private MultiSpectatorLeaderboard leaderboard;
[SetUpSteps]
public new void SetUpSteps()
{
MultiSpectatorLeaderboard leaderboard = null;
AddStep("reset", () =>
{
Clear();
foreach (var (userId, clock) in clocks)
clocks = new Dictionary<int, ManualClock>
{
spectatorClient.EndPlay(userId);
clock.CurrentTime = 0;
}
{ PLAYER_1_ID, new ManualClock() },
{ PLAYER_2_ID, new ManualClock() }
};
foreach (var (userId, _) in clocks)
SpectatorClient.StartPlay(userId, 0);
});
AddStep("create leaderboard", () =>
{
foreach (var (userId, _) in clocks)
spectatorClient.StartPlay(userId, 0);
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
var scoreProcessor = new OsuScoreProcessor();
scoreProcessor.ApplyBeatmap(playable);
@ -96,10 +62,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
// For player 2, send frames in sets of 10.
for (int i = 0; i < 100; i++)
{
spectatorClient.SendFrames(PLAYER_1_ID, i, 1);
SpectatorClient.SendFrames(PLAYER_1_ID, i, 1);
if (i % 10 == 0)
spectatorClient.SendFrames(PLAYER_2_ID, i, 10);
SpectatorClient.SendFrames(PLAYER_2_ID, i, 10);
}
});
@ -145,17 +111,5 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void assertCombo(int userId, int expectedCombo)
=> AddUntilStep($"player {userId} has {expectedCombo} combo", () => this.ChildrenOfType<GameplayLeaderboardScore>().Single(s => s.User?.Id == userId).Combo.Value == expectedCombo);
private class TestUserLookupCache : UserLookupCache
{
protected override Task<User> ComputeValueAsync(int lookup, CancellationToken token = default)
{
return Task.FromResult(new User
{
Id = lookup,
Username = $"User {lookup}"
});
}
}
}
}

View File

@ -3,31 +3,19 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Online.Spectator;
using osu.Game.Screens.OnlinePlay.Multiplayer.Spectate;
using osu.Game.Screens.Play;
using osu.Game.Tests.Beatmaps.IO;
using osu.Game.Tests.Visual.Spectator;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiSpectatorScreen : MultiplayerTestScene
{
[Cached(typeof(SpectatorClient))]
private TestSpectatorClient spectatorClient = new TestSpectatorClient();
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
[Resolved]
private OsuGameBase game { get; set; }
@ -51,25 +39,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedBeatmapId = importedBeatmap.OnlineBeatmapID ?? -1;
}
public override void SetUpSteps()
[SetUp]
public new void Setup() => Schedule(() =>
{
base.SetUpSteps();
AddStep("reset sent frames", () => nextFrame.Clear());
AddStep("add streaming client", () =>
{
Remove(spectatorClient);
Add(spectatorClient);
});
AddStep("finish previous gameplay", () =>
{
foreach (var id in playingUserIds)
spectatorClient.EndPlay(id);
playingUserIds.Clear();
});
}
nextFrame.Clear();
playingUserIds.Clear();
});
[Test]
public void TestDelayedStart()
@ -87,11 +62,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
loadSpectateScreen(false);
AddWaitStep("wait a bit", 10);
AddStep("load player first_player_id", () => spectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId));
AddStep("load player first_player_id", () => SpectatorClient.StartPlay(PLAYER_1_ID, importedBeatmapId));
AddUntilStep("one player added", () => spectatorScreen.ChildrenOfType<Player>().Count() == 1);
AddWaitStep("wait a bit", 10);
AddStep("load player second_player_id", () => spectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId));
AddStep("load player second_player_id", () => SpectatorClient.StartPlay(PLAYER_2_ID, importedBeatmapId));
AddUntilStep("two players added", () => spectatorScreen.ChildrenOfType<Player>().Count() == 2);
}
@ -242,8 +217,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for screen load", () => spectatorScreen.LoadState == LoadState.Loaded && (!waitForPlayerLoad || spectatorScreen.AllPlayersLoaded));
}
private void start(int userId, int? beatmapId = null) => start(new[] { userId }, beatmapId);
private void start(int[] userIds, int? beatmapId = null)
{
AddStep("start play", () =>
@ -251,23 +224,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
foreach (int id in userIds)
{
Client.CurrentMatchPlayingUserIds.Add(id);
spectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId);
SpectatorClient.StartPlay(id, beatmapId ?? importedBeatmapId);
playingUserIds.Add(id);
nextFrame[id] = 0;
}
});
}
private void finish(int userId)
{
AddStep("end play", () =>
{
spectatorClient.EndPlay(userId);
playingUserIds.Remove(userId);
nextFrame.Remove(userId);
});
}
private void sendFrames(int userId, int count = 10) => sendFrames(new[] { userId }, count);
private void sendFrames(int[] userIds, int count = 10)
@ -276,7 +239,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
foreach (int id in userIds)
{
spectatorClient.SendFrames(id, nextFrame[id], count);
SpectatorClient.SendFrames(id, nextFrame[id], count);
nextFrame[id] += count;
}
});
@ -297,17 +260,5 @@ namespace osu.Game.Tests.Visual.Multiplayer
private Player getPlayer(int userId) => getInstance(userId).ChildrenOfType<Player>().Single();
private PlayerArea getInstance(int userId) => spectatorScreen.ChildrenOfType<PlayerArea>().Single(p => p.UserId == userId);
internal class TestUserLookupCache : UserLookupCache
{
protected override Task<User> ComputeValueAsync(int lookup, CancellationToken token = default)
{
return Task.FromResult(new User
{
Id = lookup,
Username = $"User {lookup}"
});
}
}
}
}

View File

@ -18,6 +18,7 @@ using osu.Game.Overlays.Mods;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Screens.OnlinePlay.Multiplayer;
@ -30,14 +31,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiplayer : ScreenTestScene
{
private TestMultiplayer multiplayerScreen;
private BeatmapManager beatmaps;
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
private TestMultiplayerClient client => multiplayerScreen.Client;
private Room room => client.APIRoom;
private DependenciesScreen dependenciesScreen;
private TestMultiplayer multiplayerScreen;
private TestMultiplayerClient client;
public TestSceneMultiplayer()
{
@ -229,30 +229,43 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void loadMultiplayer()
{
AddStep("show", () =>
AddStep("create multiplayer screen", () => multiplayerScreen = new TestMultiplayer());
AddStep("load dependencies", () =>
{
multiplayerScreen = new TestMultiplayer();
client = new TestMultiplayerClient(multiplayerScreen.RoomManager);
// Needs to be added at a higher level since the multiplayer screen becomes non-current.
Child = multiplayerScreen.Client;
// The screen gets suspended so it stops receiving updates.
Child = client;
LoadScreen(multiplayerScreen);
LoadScreen(dependenciesScreen = new DependenciesScreen(client));
});
AddUntilStep("wait for loaded", () => multiplayerScreen.IsLoaded);
AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded);
AddStep("load multiplayer", () => LoadScreen(multiplayerScreen));
AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded);
}
private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer
/// <summary>
/// Used for the sole purpose of adding <see cref="TestMultiplayerClient"/> as a resolvable dependency.
/// </summary>
private class DependenciesScreen : OsuScreen
{
[Cached(typeof(MultiplayerClient))]
public readonly TestMultiplayerClient Client;
public TestMultiplayer()
public DependenciesScreen(TestMultiplayerClient client)
{
Client = new TestMultiplayerClient((TestMultiplayerRoomManager)RoomManager);
Client = client;
}
}
protected override RoomManager CreateRoomManager() => new TestMultiplayerRoomManager();
private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer
{
public new TestMultiplayerRoomManager RoomManager { get; private set; }
protected override RoomManager CreateRoomManager() => RoomManager = new TestMultiplayerRoomManager();
}
}
}

View File

@ -6,12 +6,11 @@ using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Online.API;
using osu.Game.Online.Spectator;
using osu.Game.Replays.Legacy;
@ -19,37 +18,20 @@ 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.Online;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Tests.Visual.Spectator;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiplayerGameplayLeaderboard : MultiplayerTestScene
{
private const int users = 16;
private static IEnumerable<int> users => Enumerable.Range(0, 16);
[Cached(typeof(SpectatorClient))]
private TestMultiplayerSpectatorClient spectatorClient = new TestMultiplayerSpectatorClient();
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestSceneCurrentlyPlayingDisplay.TestUserLookupCache();
public new TestMultiplayerSpectatorClient SpectatorClient => (TestMultiplayerSpectatorClient)OnlinePlayDependencies?.SpectatorClient;
private MultiplayerGameplayLeaderboard leaderboard;
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
private OsuConfigManager config;
public TestSceneMultiplayerGameplayLeaderboard()
{
base.Content.Children = new Drawable[]
{
spectatorClient,
lookupCache,
Content
};
}
[BackgroundDependencyLoader]
private void load()
{
@ -59,7 +41,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[SetUpSteps]
public override void SetUpSteps()
{
AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = lookupCache.GetUserAsync(1).Result);
AddStep("set local user", () => ((DummyAPIAccess)API).LocalUser.Value = LookupCache.GetUserAsync(1).Result);
AddStep("create leaderboard", () =>
{
@ -70,14 +52,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
var playable = Beatmap.Value.GetPlayableBeatmap(Ruleset.Value);
for (int i = 0; i < users; i++)
spectatorClient.StartPlay(i, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
foreach (var user in users)
SpectatorClient.StartPlay(user, Beatmap.Value.BeatmapInfo.OnlineBeatmapID ?? 0);
spectatorClient.Schedule(() =>
{
Client.CurrentMatchPlayingUserIds.Clear();
Client.CurrentMatchPlayingUserIds.AddRange(spectatorClient.PlayingUsers);
});
// Todo: This is REALLY bad.
Client.CurrentMatchPlayingUserIds.AddRange(users);
Children = new Drawable[]
{
@ -86,7 +65,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
scoreProcessor.ApplyBeatmap(playable);
LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, spectatorClient.PlayingUsers.ToArray())
LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(scoreProcessor, users.ToArray())
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@ -100,24 +79,32 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestScoreUpdates()
{
AddRepeatStep("update state", () => spectatorClient.RandomlyUpdateState(), 100);
AddRepeatStep("update state", () => SpectatorClient.RandomlyUpdateState(), 100);
AddToggleStep("switch compact mode", expanded => leaderboard.Expanded.Value = expanded);
}
[Test]
public void TestUserQuit()
{
AddRepeatStep("mark user quit", () => Client.CurrentMatchPlayingUserIds.RemoveAt(0), users);
foreach (var user in users)
AddStep($"mark user {user} quit", () => Client.RemoveUser(LookupCache.GetUserAsync(user).Result.AsNonNull()));
}
[Test]
public void TestChangeScoringMode()
{
AddRepeatStep("update state", () => spectatorClient.RandomlyUpdateState(), 5);
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<int, FrameHeader> lastHeaders = new Dictionary<int, FrameHeader>();

View File

@ -1,7 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
@ -10,18 +10,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiplayerMatchFooter : MultiplayerTestScene
{
[Cached]
private readonly OnlinePlayBeatmapAvailabilityTracker availablilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
[BackgroundDependencyLoader]
private void load()
[SetUp]
public new void Setup() => Schedule(() =>
{
SelectedRoom.Value = new Room();
Child = new MultiplayerMatchFooter
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Height = 50
};
}
});
}
}

View File

@ -29,7 +29,7 @@ using osu.Game.Screens.Select;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiplayerMatchSongSelect : RoomTestScene
public class TestSceneMultiplayerMatchSongSelect : MultiplayerTestScene
{
private BeatmapManager manager;
private RulesetStore rulesets;

View File

@ -49,13 +49,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
[SetUp]
public new void Setup() => Schedule(() =>
{
Room.Name.Value = "Test Room";
SelectedRoom.Value = new Room { Name = { Value = "Test Room" } };
});
[SetUpSteps]
public void SetupSteps()
{
AddStep("load match", () => LoadScreen(screen = new MultiplayerMatchSubScreen(Room)));
AddStep("load match", () => LoadScreen(screen = new MultiplayerMatchSubScreen(SelectedRoom.Value)));
AddUntilStep("wait for load", () => screen.IsCurrentScreen());
}
@ -66,7 +66,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set playlist", () =>
{
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo },
@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("set playlist", () =>
{
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo },
@ -102,7 +102,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("set playlist", () =>
{
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First()).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo },

View File

@ -22,8 +22,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestSceneMultiplayerParticipantsList : MultiplayerTestScene
{
[SetUp]
public new void Setup() => Schedule(createNewParticipantsList);
[SetUpSteps]
public void SetupSteps()
{
createNewParticipantsList();
}
[Test]
public void TestAddUser()
@ -88,7 +91,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public void TestCorrectInitialState()
{
AddStep("set to downloading map", () => Client.ChangeBeatmapAvailability(BeatmapAvailability.Downloading(0)));
AddStep("recreate list", createNewParticipantsList);
createNewParticipantsList();
checkProgressBarVisibility(true);
}
@ -233,7 +236,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createNewParticipantsList()
{
Child = new ParticipantsList { Anchor = Anchor.Centre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Y, Size = new Vector2(380, 0.7f) };
ParticipantsList participantsList = null;
AddStep("create new list", () => Child = participantsList = new ParticipantsList
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Y,
Size = new Vector2(380, 0.7f)
});
AddUntilStep("wait for list to load", () => participantsList.IsLoaded);
}
private void checkProgressBarVisibility(bool visible) =>

View File

@ -27,7 +27,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
public class TestSceneMultiplayerReadyButton : MultiplayerTestScene
{
private MultiplayerReadyButton button;
private OnlinePlayBeatmapAvailabilityTracker beatmapTracker;
private BeatmapSetInfo importedSet;
private readonly Bindable<PlaylistItem> selectedItem = new Bindable<PlaylistItem>();
@ -43,18 +42,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
Add(beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker
{
SelectedItem = { BindTarget = selectedItem }
});
Dependencies.Cache(beatmapTracker);
}
[SetUp]
public new void Setup() => Schedule(() =>
{
AvailabilityTracker.SelectedItem.BindTo(selectedItem);
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
selectedItem.Value = new PlaylistItem

View File

@ -3,37 +3,38 @@
using System;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Testing;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual.OnlinePlay;
namespace osu.Game.Tests.Visual.Multiplayer
{
[HeadlessTest]
public class TestSceneMultiplayerRoomManager : RoomTestScene
public class TestSceneMultiplayerRoomManager : MultiplayerTestScene
{
private TestMultiplayerRoomContainer roomContainer;
private TestMultiplayerRoomManager roomManager => roomContainer.RoomManager;
protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies();
public TestSceneMultiplayerRoomManager()
: base(false)
{
}
[Test]
public void TestPollsInitially()
{
AddStep("create room manager with a few rooms", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
roomManager.CreateRoom(createRoom(r => r.Name.Value = "1"));
roomManager.PartRoom();
roomManager.CreateRoom(createRoom(r => r.Name.Value = "2"));
roomManager.PartRoom();
roomManager.ClearRooms();
});
RoomManager.CreateRoom(createRoom(r => r.Name.Value = "1"));
RoomManager.PartRoom();
RoomManager.CreateRoom(createRoom(r => r.Name.Value = "2"));
RoomManager.PartRoom();
RoomManager.ClearRooms();
});
AddAssert("manager polled for rooms", () => ((RoomManager)roomManager).Rooms.Count == 2);
AddAssert("initial rooms received", () => roomManager.InitialRoomsReceived.Value);
AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2);
AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value);
}
[Test]
@ -41,19 +42,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create room manager with a few rooms", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
roomManager.CreateRoom(createRoom());
roomManager.PartRoom();
roomManager.CreateRoom(createRoom());
roomManager.PartRoom();
});
RoomManager.CreateRoom(createRoom());
RoomManager.PartRoom();
RoomManager.CreateRoom(createRoom());
RoomManager.PartRoom();
});
AddStep("disconnect", () => roomContainer.Client.Disconnect());
AddStep("disconnect", () => Client.Disconnect());
AddAssert("rooms cleared", () => ((RoomManager)roomManager).Rooms.Count == 0);
AddAssert("initial rooms not received", () => !roomManager.InitialRoomsReceived.Value);
AddAssert("rooms cleared", () => ((RoomManager)RoomManager).Rooms.Count == 0);
AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value);
}
[Test]
@ -61,20 +59,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create room manager with a few rooms", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
roomManager.CreateRoom(createRoom());
roomManager.PartRoom();
roomManager.CreateRoom(createRoom());
roomManager.PartRoom();
});
RoomManager.CreateRoom(createRoom());
RoomManager.PartRoom();
RoomManager.CreateRoom(createRoom());
RoomManager.PartRoom();
});
AddStep("disconnect", () => roomContainer.Client.Disconnect());
AddStep("connect", () => roomContainer.Client.Connect());
AddStep("disconnect", () => Client.Disconnect());
AddStep("connect", () => Client.Connect());
AddAssert("manager polled for rooms", () => ((RoomManager)roomManager).Rooms.Count == 2);
AddAssert("initial rooms received", () => roomManager.InitialRoomsReceived.Value);
AddAssert("manager polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 2);
AddAssert("initial rooms received", () => RoomManager.InitialRoomsReceived.Value);
}
[Test]
@ -82,15 +77,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create room manager with a room", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
roomManager.CreateRoom(createRoom());
roomManager.ClearRooms();
});
RoomManager.CreateRoom(createRoom());
RoomManager.ClearRooms();
});
AddAssert("manager not polled for rooms", () => ((RoomManager)roomManager).Rooms.Count == 0);
AddAssert("initial rooms not received", () => !roomManager.InitialRoomsReceived.Value);
AddAssert("manager not polled for rooms", () => ((RoomManager)RoomManager).Rooms.Count == 0);
AddAssert("initial rooms not received", () => !RoomManager.InitialRoomsReceived.Value);
}
[Test]
@ -98,13 +90,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create room manager with a room", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
roomManager.CreateRoom(createRoom());
});
RoomManager.CreateRoom(createRoom());
});
AddUntilStep("multiplayer room joined", () => roomContainer.Client.Room != null);
AddUntilStep("multiplayer room joined", () => Client.Room != null);
}
[Test]
@ -112,14 +101,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create room manager with a room", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
roomManager.CreateRoom(createRoom());
roomManager.PartRoom();
});
RoomManager.CreateRoom(createRoom());
RoomManager.PartRoom();
});
AddAssert("multiplayer room parted", () => roomContainer.Client.Room == null);
AddAssert("multiplayer room parted", () => Client.Room == null);
}
[Test]
@ -127,16 +113,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create room manager with a room", () =>
{
createRoomManager().With(d => d.OnLoadComplete += _ =>
{
var r = createRoom();
roomManager.CreateRoom(r);
roomManager.PartRoom();
roomManager.JoinRoom(r);
});
var r = createRoom();
RoomManager.CreateRoom(r);
RoomManager.PartRoom();
RoomManager.JoinRoom(r);
});
AddUntilStep("multiplayer room joined", () => roomContainer.Client.Room != null);
AddUntilStep("multiplayer room joined", () => Client.Room != null);
}
private Room createRoom(Action<Room> initFunc = null)
@ -161,18 +144,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
return room;
}
private TestMultiplayerRoomManager createRoomManager()
private class TestDependencies : MultiplayerTestSceneDependencies
{
Child = roomContainer = new TestMultiplayerRoomContainer
public TestDependencies()
{
RoomManager =
{
TimeBetweenListingPolls = { Value = 1 },
TimeBetweenSelectionPolls = { Value = 1 }
}
};
return roomManager;
// Need to set these values as early as possible.
RoomManager.TimeBetweenListingPolls.Value = 1;
RoomManager.TimeBetweenSelectionPolls.Value = 1;
}
}
}
}

View File

@ -37,40 +37,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
private IDisposable readyClickOperation;
protected override Container<Drawable> Content => content;
private readonly Container content;
public TestSceneMultiplayerSpectateButton()
{
base.Content.Add(content = new Container
{
RelativeSizeAxes = Axes.Both
});
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
var dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
return dependencies;
}
[BackgroundDependencyLoader]
private void load(GameHost host, AudioManager audio)
{
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
var beatmapTracker = new OnlinePlayBeatmapAvailabilityTracker { SelectedItem = { BindTarget = selectedItem } };
base.Content.Add(beatmapTracker);
Dependencies.Cache(beatmapTracker);
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
}
[SetUp]
public new void Setup() => Schedule(() =>
{
AvailabilityTracker.SelectedItem.BindTo(selectedItem);
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First());
selectedItem.Value = new PlaylistItem

View File

@ -14,16 +14,18 @@ using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Tests.Visual.OnlinePlay;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestScenePlaylistsSongSelect : RoomTestScene
public class TestScenePlaylistsSongSelect : OnlinePlayTestScene
{
[Resolved]
private BeatmapManager beatmapManager { get; set; }
@ -85,6 +87,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("reset", () =>
{
SelectedRoom.Value = new Room();
Ruleset.Value = new OsuRuleset().RulesetInfo;
Beatmap.SetDefault();
SelectedMods.Value = Array.Empty<Mod>();
@ -98,14 +101,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
public void TestItemAddedIfEmptyOnStart()
{
AddStep("finalise selection", () => songSelect.FinaliseSelection());
AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1);
AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1);
}
[Test]
public void TestItemAddedWhenCreateNewItemClicked()
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem());
AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1);
AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1);
}
[Test]
@ -113,7 +116,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem());
AddStep("finalise selection", () => songSelect.FinaliseSelection());
AddAssert("playlist has 1 item", () => Room.Playlist.Count == 1);
AddAssert("playlist has 1 item", () => SelectedRoom.Value.Playlist.Count == 1);
}
[Test]
@ -121,7 +124,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem());
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem());
AddAssert("playlist has 2 items", () => Room.Playlist.Count == 2);
AddAssert("playlist has 2 items", () => SelectedRoom.Value.Playlist.Count == 2);
}
[Test]
@ -131,13 +134,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem());
AddStep("rearrange", () =>
{
var item = Room.Playlist[0];
Room.Playlist.RemoveAt(0);
Room.Playlist.Add(item);
var item = SelectedRoom.Value.Playlist[0];
SelectedRoom.Value.Playlist.RemoveAt(0);
SelectedRoom.Value.Playlist.Add(item);
});
AddStep("create new item", () => songSelect.BeatmapDetails.CreateNewItem());
AddAssert("new item has id 2", () => Room.Playlist.Last().ID == 2);
AddAssert("new item has id 2", () => SelectedRoom.Value.Playlist.Last().ID == 2);
}
/// <summary>
@ -151,8 +154,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("change mod rate", () => ((OsuModDoubleTime)SelectedMods.Value[0]).SpeedChange.Value = 2);
AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem());
AddAssert("item 1 has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)Room.Playlist.First().RequiredMods[0]).SpeedChange.Value));
AddAssert("item 2 has rate 2", () => Precision.AlmostEquals(2, ((OsuModDoubleTime)Room.Playlist.Last().RequiredMods[0]).SpeedChange.Value));
AddAssert("item 1 has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0]).SpeedChange.Value));
AddAssert("item 2 has rate 2", () => Precision.AlmostEquals(2, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.Last().RequiredMods[0]).SpeedChange.Value));
}
/// <summary>
@ -174,7 +177,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("create item", () => songSelect.BeatmapDetails.CreateNewItem());
AddStep("change stored mod rate", () => mod.SpeedChange.Value = 2);
AddAssert("item has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)Room.Playlist.First().RequiredMods[0]).SpeedChange.Value));
AddAssert("item has rate 1.5", () => Precision.AlmostEquals(1.5, ((OsuModDoubleTime)SelectedRoom.Value.Playlist.First().RequiredMods[0]).SpeedChange.Value));
}
private class TestPlaylistsSongSelect : PlaylistsSongSelect

View File

@ -3,25 +3,21 @@
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Graphics.Containers;
using osu.Game.Screens.OnlinePlay.Lounge;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Tests.Visual.Multiplayer;
using osu.Game.Tests.Visual.OnlinePlay;
namespace osu.Game.Tests.Visual.Playlists
{
public class TestScenePlaylistsLoungeSubScreen : RoomManagerTestScene
public class TestScenePlaylistsLoungeSubScreen : OnlinePlayTestScene
{
private LoungeSubScreen loungeScreen;
protected new BasicTestRoomManager RoomManager => (BasicTestRoomManager)base.RoomManager;
[BackgroundDependencyLoader]
private void load()
{
}
private LoungeSubScreen loungeScreen;
public override void SetUpSteps()
{
@ -37,7 +33,7 @@ namespace osu.Game.Tests.Visual.Playlists
[Test]
public void TestScrollSelectedIntoView()
{
AddRooms(30);
AddStep("add rooms", () => RoomManager.AddRooms(30));
AddUntilStep("first room is not masked", () => checkRoomVisible(roomsContainer.Rooms.First()));

View File

@ -3,7 +3,6 @@
using System;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -12,26 +11,28 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Tests.Visual.OnlinePlay;
namespace osu.Game.Tests.Visual.Playlists
{
public class TestScenePlaylistsMatchSettingsOverlay : RoomTestScene
public class TestScenePlaylistsMatchSettingsOverlay : OnlinePlayTestScene
{
[Cached(Type = typeof(IRoomManager))]
private TestRoomManager roomManager = new TestRoomManager();
protected new TestRoomManager RoomManager => (TestRoomManager)base.RoomManager;
private TestRoomSettings settings;
protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new TestDependencies();
[SetUp]
public new void Setup() => Schedule(() =>
{
settings = new TestRoomSettings
SelectedRoom.Value = new Room();
Child = settings = new TestRoomSettings
{
RelativeSizeAxes = Axes.Both,
State = { Value = Visibility.Visible }
};
Child = settings;
});
[Test]
@ -39,19 +40,19 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("clear name and beatmap", () =>
{
Room.Name.Value = "";
Room.Playlist.Clear();
SelectedRoom.Value.Name.Value = "";
SelectedRoom.Value.Playlist.Clear();
});
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
AddStep("set name", () => Room.Name.Value = "Room name");
AddStep("set name", () => SelectedRoom.Value.Name.Value = "Room name");
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
AddStep("set beatmap", () => Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }));
AddStep("set beatmap", () => SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } }));
AddAssert("button enabled", () => settings.ApplyButton.Enabled.Value);
AddStep("clear name", () => Room.Name.Value = "");
AddStep("clear name", () => SelectedRoom.Value.Name.Value = "");
AddAssert("button disabled", () => !settings.ApplyButton.Enabled.Value);
}
@ -67,9 +68,9 @@ namespace osu.Game.Tests.Visual.Playlists
{
settings.NameField.Current.Value = expected_name;
settings.DurationField.Current.Value = expectedDuration;
Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
roomManager.CreateRequested = r =>
RoomManager.CreateRequested = r =>
{
createdRoom = r;
return true;
@ -88,11 +89,11 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("setup", () =>
{
Room.Name.Value = "Test Room";
Room.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
SelectedRoom.Value.Name.Value = "Test Room";
SelectedRoom.Value.Playlist.Add(new PlaylistItem { Beatmap = { Value = CreateBeatmap(Ruleset.Value).BeatmapInfo } });
fail = true;
roomManager.CreateRequested = _ => !fail;
RoomManager.CreateRequested = _ => !fail;
});
AddAssert("error not displayed", () => !settings.ErrorText.IsPresent);
@ -119,7 +120,12 @@ namespace osu.Game.Tests.Visual.Playlists
public OsuSpriteText ErrorText => ((MatchSettings)Settings).ErrorText;
}
private class TestRoomManager : IRoomManager
private class TestDependencies : OnlinePlayTestSceneDependencies
{
protected override IRoomManager CreateRoomManager() => new TestRoomManager();
}
protected class TestRoomManager : IRoomManager
{
public const string FAILED_TEXT = "failed";

View File

@ -3,21 +3,23 @@
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.Playlists
{
public class TestScenePlaylistsParticipantsList : RoomTestScene
public class TestScenePlaylistsParticipantsList : OnlinePlayTestScene
{
[SetUp]
public new void Setup() => Schedule(() =>
{
Room.RoomID.Value = 7;
SelectedRoom.Value = new Room { RoomID = { Value = 7 } };
for (int i = 0; i < 50; i++)
{
Room.RecentParticipants.Add(new User
SelectedRoom.Value.RecentParticipants.Add(new User
{
Username = "peppy",
Statistics = new UserStatistics { GlobalRank = 1234 },

View File

@ -15,20 +15,17 @@ using osu.Game.Online.API;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Playlists;
using osu.Game.Screens.Play;
using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Users;
using osuTK.Input;
namespace osu.Game.Tests.Visual.Playlists
{
public class TestScenePlaylistsRoomSubScreen : RoomTestScene
public class TestScenePlaylistsRoomSubScreen : OnlinePlayTestScene
{
[Cached(typeof(IRoomManager))]
private readonly TestRoomManager roomManager = new TestRoomManager();
private BeatmapManager manager;
private RulesetStore rulesets;
@ -56,8 +53,9 @@ namespace osu.Game.Tests.Visual.Playlists
[SetUpSteps]
public void SetupSteps()
{
AddStep("set room", () => SelectedRoom.Value = new Room());
AddStep("ensure has beatmap", () => manager.Import(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo.BeatmapSet).Wait());
AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(Room)));
AddStep("load match", () => LoadScreen(match = new TestPlaylistsRoomSubScreen(SelectedRoom.Value)));
AddUntilStep("wait for load", () => match.IsCurrentScreen());
}
@ -66,12 +64,12 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("set room properties", () =>
{
Room.RoomID.Value = 1;
Room.Name.Value = "my awesome room";
Room.Host.Value = new User { Id = 2, Username = "peppy" };
Room.RecentParticipants.Add(Room.Host.Value);
Room.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.RoomID.Value = 1;
SelectedRoom.Value.Name.Value = "my awesome room";
SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" };
SelectedRoom.Value.RecentParticipants.Add(SelectedRoom.Value.Host.Value);
SelectedRoom.Value.EndDate.Value = DateTimeOffset.Now.AddMinutes(5);
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo }
@ -87,9 +85,9 @@ namespace osu.Game.Tests.Visual.Playlists
{
AddStep("set room properties", () =>
{
Room.Name.Value = "my awesome room";
Room.Host.Value = new User { Id = 2, Username = "peppy" };
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.Name.Value = "my awesome room";
SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" };
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo },
Ruleset = { Value = new OsuRuleset().RulesetInfo }
@ -103,7 +101,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("click", () => InputManager.Click(MouseButton.Left));
AddAssert("first playlist item selected", () => match.SelectedItem.Value == Room.Playlist[0]);
AddAssert("first playlist item selected", () => match.SelectedItem.Value == SelectedRoom.Value.Playlist[0]);
}
[Test]
@ -138,9 +136,9 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("load room", () =>
{
Room.Name.Value = "my awesome room";
Room.Host.Value = new User { Id = 2, Username = "peppy" };
Room.Playlist.Add(new PlaylistItem
SelectedRoom.Value.Name.Value = "my awesome room";
SelectedRoom.Value.Host.Value = new User { Id = 2, Username = "peppy" };
SelectedRoom.Value.Playlist.Add(new PlaylistItem
{
Beatmap = { Value = importedSet.Beatmaps[0] },
Ruleset = { Value = new OsuRuleset().RulesetInfo }
@ -171,30 +169,5 @@ namespace osu.Game.Tests.Visual.Playlists
{
}
}
private class TestRoomManager : IRoomManager
{
public event Action RoomsUpdated
{
add => throw new NotImplementedException();
remove => throw new NotImplementedException();
}
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
public IBindableList<Room> Rooms { get; } = new BindableList<Room>();
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
{
room.RoomID.Value = 1;
onSuccess?.Invoke(room);
}
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => onSuccess?.Invoke(room);
public void PartRoom()
{
}
}
}
}

View File

@ -93,7 +93,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
bool matchingFilter = true;
matchingFilter &= r.Room.Playlist.Count == 0 || r.Room.Playlist.Any(i => i.Ruleset.Value.Equals(criteria.Ruleset));
matchingFilter &= r.Room.Playlist.Count == 0 || criteria.Ruleset == null || r.Room.Playlist.Any(i => i.Ruleset.Value.Equals(criteria.Ruleset));
if (!string.IsNullOrEmpty(criteria.SearchString))
matchingFilter &= r.FilterTerms.Any(term => term.Contains(criteria.SearchString, StringComparison.InvariantCultureIgnoreCase));

View File

@ -0,0 +1,37 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Database;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Tests.Visual.Spectator;
namespace osu.Game.Tests.Visual.Multiplayer
{
/// <summary>
/// Interface that defines the dependencies required for multiplayer test scenes.
/// </summary>
public interface IMultiplayerTestSceneDependencies : IOnlinePlayTestSceneDependencies
{
/// <summary>
/// The cached <see cref="MultiplayerClient"/>.
/// </summary>
TestMultiplayerClient Client { get; }
/// <summary>
/// The cached <see cref="IRoomManager"/>.
/// </summary>
new TestMultiplayerRoomManager RoomManager { get; }
/// <summary>
/// The cached <see cref="UserLookupCache"/>.
/// </summary>
TestUserLookupCache LookupCache { get; }
/// <summary>
/// The cached <see cref="osu.Game.Online.Spectator.SpectatorClient"/>.
/// </summary>
TestSpectatorClient SpectatorClient { get; }
}
}

View File

@ -2,66 +2,55 @@
// See the LICENCE file in the repository root for full licence text.
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Tests.Beatmaps;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Tests.Visual.Spectator;
namespace osu.Game.Tests.Visual.Multiplayer
{
public abstract class MultiplayerTestScene : RoomTestScene
/// <summary>
/// The base test scene for all multiplayer components and screens.
/// </summary>
public abstract class MultiplayerTestScene : OnlinePlayTestScene, IMultiplayerTestSceneDependencies
{
public const int PLAYER_1_ID = 55;
public const int PLAYER_2_ID = 56;
[Cached(typeof(MultiplayerClient))]
public TestMultiplayerClient Client { get; }
public TestMultiplayerClient Client => OnlinePlayDependencies.Client;
public new TestMultiplayerRoomManager RoomManager => OnlinePlayDependencies.RoomManager;
public TestUserLookupCache LookupCache => OnlinePlayDependencies?.LookupCache;
public TestSpectatorClient SpectatorClient => OnlinePlayDependencies?.SpectatorClient;
[Cached(typeof(IRoomManager))]
public TestMultiplayerRoomManager RoomManager { get; }
[Cached]
public Bindable<FilterCriteria> Filter { get; }
[Cached]
public OngoingOperationTracker OngoingOperationTracker { get; }
protected override Container<Drawable> Content => content;
private readonly TestMultiplayerRoomContainer content;
protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies;
private readonly bool joinRoom;
protected MultiplayerTestScene(bool joinRoom = true)
{
this.joinRoom = joinRoom;
base.Content.Add(content = new TestMultiplayerRoomContainer { RelativeSizeAxes = Axes.Both });
Client = content.Client;
RoomManager = content.RoomManager;
Filter = content.Filter;
OngoingOperationTracker = content.OngoingOperationTracker;
}
[SetUp]
public new void Setup() => Schedule(() =>
{
RoomManager.Schedule(() => RoomManager.PartRoom());
if (joinRoom)
{
Room.Name.Value = "test name";
Room.Playlist.Add(new PlaylistItem
var room = new Room
{
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
Ruleset = { Value = Ruleset.Value }
});
Name = { Value = "test name" },
Playlist =
{
new PlaylistItem
{
Beatmap = { Value = new TestBeatmap(Ruleset.Value).BeatmapInfo },
Ruleset = { Value = Ruleset.Value }
}
}
};
RoomManager.Schedule(() => RoomManager.CreateRoom(Room));
RoomManager.CreateRoom(room);
SelectedRoom.Value = room;
}
});
@ -72,5 +61,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
if (joinRoom)
AddUntilStep("wait for room join", () => Client.Room != null);
}
protected override OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new MultiplayerTestSceneDependencies();
}
}

View File

@ -0,0 +1,38 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Database;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Spectator;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Tests.Visual.OnlinePlay;
using osu.Game.Tests.Visual.Spectator;
namespace osu.Game.Tests.Visual.Multiplayer
{
/// <summary>
/// Contains the basic dependencies of multiplayer test scenes.
/// </summary>
public class MultiplayerTestSceneDependencies : OnlinePlayTestSceneDependencies, IMultiplayerTestSceneDependencies
{
public TestMultiplayerClient Client { get; }
public TestUserLookupCache LookupCache { get; }
public TestSpectatorClient SpectatorClient { get; }
public new TestMultiplayerRoomManager RoomManager => (TestMultiplayerRoomManager)base.RoomManager;
public MultiplayerTestSceneDependencies()
{
Client = new TestMultiplayerClient(RoomManager);
LookupCache = new TestUserLookupCache();
SpectatorClient = CreateSpectatorClient();
CacheAs<MultiplayerClient>(Client);
CacheAs<UserLookupCache>(LookupCache);
CacheAs<SpectatorClient>(SpectatorClient);
}
protected override IRoomManager CreateRoomManager() => new TestMultiplayerRoomManager();
protected virtual TestSpectatorClient CreateSpectatorClient() => new TestSpectatorClient();
}
}

View File

@ -20,6 +20,9 @@ using osu.Game.Users;
namespace osu.Game.Tests.Visual.Multiplayer
{
/// <summary>
/// A <see cref="MultiplayerClient"/> for use in multiplayer test scenes. Should generally not be used by itself outside of a <see cref="MultiplayerTestScene"/>.
/// </summary>
public class TestMultiplayerClient : MultiplayerClient
{
public override IBindable<bool> IsConnected => isConnected;

View File

@ -1,48 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Multiplayer;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
namespace osu.Game.Tests.Visual.Multiplayer
{
public class TestMultiplayerRoomContainer : Container
{
protected override Container<Drawable> Content => content;
private readonly Container content;
[Cached(typeof(MultiplayerClient))]
public readonly TestMultiplayerClient Client;
[Cached(typeof(IRoomManager))]
public readonly TestMultiplayerRoomManager RoomManager;
[Cached]
public readonly Bindable<FilterCriteria> Filter = new Bindable<FilterCriteria>(new FilterCriteria());
[Cached]
public readonly OngoingOperationTracker OngoingOperationTracker;
public TestMultiplayerRoomContainer()
{
RelativeSizeAxes = Axes.Both;
RoomManager = new TestMultiplayerRoomManager();
Client = new TestMultiplayerClient(RoomManager);
OngoingOperationTracker = new OngoingOperationTracker();
AddRangeInternal(new Drawable[]
{
Client,
RoomManager,
OngoingOperationTracker,
content = new Container { RelativeSizeAxes = Axes.Both }
});
}
}
}

View File

@ -11,11 +11,15 @@ using osu.Game.Online.API.Requests;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
using osu.Game.Screens.OnlinePlay.Multiplayer;
namespace osu.Game.Tests.Visual.Multiplayer
{
/// <summary>
/// A <see cref="RoomManager"/> for use in multiplayer test scenes. Should generally not be used by itself outside of a <see cref="MultiplayerTestScene"/>.
/// </summary>
public class TestMultiplayerRoomManager : MultiplayerRoomManager
{
[Resolved]
@ -29,10 +33,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
public new readonly List<Room> Rooms = new List<Room>();
protected override void LoadComplete()
[BackgroundDependencyLoader]
private void load()
{
base.LoadComplete();
int currentScoreId = 0;
int currentRoomId = 0;
int currentPlaylistItemId = 0;

View File

@ -0,0 +1,78 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Linq;
using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Online.Rooms;
using osu.Game.Rulesets;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Components;
using osu.Game.Users;
namespace osu.Game.Tests.Visual.OnlinePlay
{
/// <summary>
/// A very simple <see cref="RoomManager"/> for use in online play test scenes.
/// </summary>
public class BasicTestRoomManager : IRoomManager
{
public event Action RoomsUpdated
{
add { }
remove { }
}
public readonly BindableList<Room> Rooms = new BindableList<Room>();
public IBindable<bool> InitialRoomsReceived { get; } = new Bindable<bool>(true);
IBindableList<Room> IRoomManager.Rooms => Rooms;
public void CreateRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null)
{
room.RoomID.Value ??= Rooms.Select(r => r.RoomID.Value).Where(id => id != null).Select(id => id.Value).DefaultIfEmpty().Max() + 1;
Rooms.Add(room);
onSuccess?.Invoke(room);
}
public void JoinRoom(Room room, Action<Room> onSuccess = null, Action<string> onError = null) => onSuccess?.Invoke(room);
public void PartRoom()
{
}
public void AddRooms(int count, RulesetInfo ruleset = null)
{
for (int i = 0; i < count; i++)
{
var room = new Room
{
RoomID = { Value = i },
Name = { Value = $"Room {i}" },
Host = { Value = new User { Username = "Host" } },
EndDate = { Value = DateTimeOffset.Now + TimeSpan.FromSeconds(10) },
Category = { Value = i % 2 == 0 ? RoomCategory.Spotlight : RoomCategory.Normal }
};
if (ruleset != null)
{
room.Playlist.Add(new PlaylistItem
{
Ruleset = { Value = ruleset },
Beatmap =
{
Value = new BeatmapInfo
{
Metadata = new BeatmapMetadata()
}
}
});
}
CreateRoom(room);
}
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Bindables;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
namespace osu.Game.Tests.Visual.OnlinePlay
{
/// <summary>
/// Interface that defines the dependencies required for online play test scenes.
/// </summary>
public interface IOnlinePlayTestSceneDependencies
{
/// <summary>
/// The cached <see cref="Room"/>.
/// </summary>
Bindable<Room> SelectedRoom { get; }
/// <summary>
/// The cached <see cref="IRoomManager"/>
/// </summary>
IRoomManager RoomManager { get; }
/// <summary>
/// The cached <see cref="FilterCriteria"/>.
/// </summary>
Bindable<FilterCriteria> Filter { get; }
/// <summary>
/// The cached <see cref="OngoingOperationTracker"/>.
/// </summary>
OngoingOperationTracker OngoingOperationTracker { get; }
/// <summary>
/// The cached <see cref="OnlinePlayBeatmapAvailabilityTracker"/>.
/// </summary>
OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; }
}
}

View File

@ -0,0 +1,104 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
namespace osu.Game.Tests.Visual.OnlinePlay
{
/// <summary>
/// A base test scene for all online play components and screens.
/// </summary>
public abstract class OnlinePlayTestScene : ScreenTestScene, IOnlinePlayTestSceneDependencies
{
public Bindable<Room> SelectedRoom => OnlinePlayDependencies?.SelectedRoom;
public IRoomManager RoomManager => OnlinePlayDependencies?.RoomManager;
public Bindable<FilterCriteria> Filter => OnlinePlayDependencies?.Filter;
public OngoingOperationTracker OngoingOperationTracker => OnlinePlayDependencies?.OngoingOperationTracker;
public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker => OnlinePlayDependencies?.AvailabilityTracker;
/// <summary>
/// All dependencies required for online play components and screens.
/// </summary>
protected OnlinePlayTestSceneDependencies OnlinePlayDependencies => dependencies?.OnlinePlayDependencies;
private DelegatedDependencyContainer dependencies;
protected override Container<Drawable> Content => content;
private readonly Container content;
private readonly Container drawableDependenciesContainer;
protected OnlinePlayTestScene()
{
base.Content.AddRange(new Drawable[]
{
drawableDependenciesContainer = new Container { RelativeSizeAxes = Axes.Both },
content = new Container { RelativeSizeAxes = Axes.Both },
});
}
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
dependencies = new DelegatedDependencyContainer(base.CreateChildDependencies(parent));
return dependencies;
}
[SetUp]
public void Setup() => Schedule(() =>
{
// Reset the room dependencies to a fresh state.
drawableDependenciesContainer.Clear();
dependencies.OnlinePlayDependencies = CreateOnlinePlayDependencies();
drawableDependenciesContainer.AddRange(OnlinePlayDependencies.DrawableComponents);
});
/// <summary>
/// Creates the room dependencies. Called every <see cref="Setup"/>.
/// </summary>
/// <remarks>
/// Any custom dependencies required for online play sub-classes should be added here.
/// </remarks>
protected virtual OnlinePlayTestSceneDependencies CreateOnlinePlayDependencies() => new OnlinePlayTestSceneDependencies();
/// <summary>
/// A <see cref="IReadOnlyDependencyContainer"/> providing a mutable lookup source for online play dependencies.
/// </summary>
private class DelegatedDependencyContainer : IReadOnlyDependencyContainer
{
/// <summary>
/// The online play dependencies.
/// </summary>
public OnlinePlayTestSceneDependencies OnlinePlayDependencies { get; set; }
private readonly IReadOnlyDependencyContainer parent;
private readonly DependencyContainer injectableDependencies;
/// <summary>
/// Creates a new <see cref="DelegatedDependencyContainer"/>.
/// </summary>
/// <param name="parent">The fallback <see cref="IReadOnlyDependencyContainer"/> to use when <see cref="OnlinePlayDependencies"/> cannot satisfy a dependency.</param>
public DelegatedDependencyContainer(IReadOnlyDependencyContainer parent)
{
this.parent = parent;
injectableDependencies = new DependencyContainer(this);
}
public object Get(Type type)
=> OnlinePlayDependencies?.Get(type) ?? parent.Get(type);
public object Get(Type type, CacheInfo info)
=> OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info);
public void Inject<T>(T instance)
where T : class
=> injectableDependencies.Inject(instance);
}
}
}

View File

@ -0,0 +1,78 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Online.Rooms;
using osu.Game.Screens.OnlinePlay;
using osu.Game.Screens.OnlinePlay.Lounge.Components;
namespace osu.Game.Tests.Visual.OnlinePlay
{
/// <summary>
/// Contains the basic dependencies of online play test scenes.
/// </summary>
public class OnlinePlayTestSceneDependencies : IReadOnlyDependencyContainer, IOnlinePlayTestSceneDependencies
{
public Bindable<Room> SelectedRoom { get; }
public IRoomManager RoomManager { get; }
public Bindable<FilterCriteria> Filter { get; }
public OngoingOperationTracker OngoingOperationTracker { get; }
public OnlinePlayBeatmapAvailabilityTracker AvailabilityTracker { get; }
/// <summary>
/// All cached dependencies which are also <see cref="Drawable"/> components.
/// </summary>
public IReadOnlyList<Drawable> DrawableComponents => drawableComponents;
private readonly List<Drawable> drawableComponents = new List<Drawable>();
private readonly DependencyContainer dependencies;
public OnlinePlayTestSceneDependencies()
{
SelectedRoom = new Bindable<Room>();
RoomManager = CreateRoomManager();
Filter = new Bindable<FilterCriteria>(new FilterCriteria());
OngoingOperationTracker = new OngoingOperationTracker();
AvailabilityTracker = new OnlinePlayBeatmapAvailabilityTracker();
dependencies = new DependencyContainer(new CachedModelDependencyContainer<Room>(null) { Model = { BindTarget = SelectedRoom } });
CacheAs(SelectedRoom);
CacheAs(RoomManager);
CacheAs(Filter);
CacheAs(OngoingOperationTracker);
CacheAs(AvailabilityTracker);
}
public object Get(Type type)
=> dependencies.Get(type);
public object Get(Type type, CacheInfo info)
=> dependencies.Get(type, info);
public void Inject<T>(T instance)
where T : class
=> dependencies.Inject(instance);
protected void Cache(object instance)
{
dependencies.Cache(instance);
if (instance is Drawable drawable)
drawableComponents.Add(drawable);
}
protected void CacheAs<T>(T instance)
where T : class
{
dependencies.CacheAs(instance);
if (instance is Drawable drawable)
drawableComponents.Add(drawable);
}
protected virtual IRoomManager CreateRoomManager() => new BasicTestRoomManager();
}
}

View File

@ -1,33 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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.Bindables;
using osu.Game.Online.Rooms;
namespace osu.Game.Tests.Visual
{
public abstract class RoomTestScene : ScreenTestScene
{
[Cached]
private readonly Bindable<Room> currentRoom = new Bindable<Room>();
protected Room Room => currentRoom.Value;
private CachedModelDependencyContainer<Room> dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
{
dependencies = new CachedModelDependencyContainer<Room>(base.CreateChildDependencies(parent));
dependencies.Model.BindTo(currentRoom);
return dependencies;
}
[SetUp]
public void Setup() => Schedule(() =>
{
currentRoom.Value = new Room();
});
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Threading;
using System.Threading.Tasks;
using osu.Game.Database;
using osu.Game.Users;
namespace osu.Game.Tests.Visual
{
public class TestUserLookupCache : UserLookupCache
{
protected override Task<User> ComputeValueAsync(int lookup, CancellationToken token = default) => Task.FromResult(new User
{
Id = lookup,
Username = $"User {lookup}"
});
}
}