Merge branch 'master' into fix-multi-cache-dependencies

This commit is contained in:
Dean Herbert
2022-02-16 09:44:37 +09:00
42 changed files with 423 additions and 144 deletions

View File

@ -6,15 +6,23 @@ using System.IO;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Database;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Edit.Setup;
using osu.Game.Storyboards;
using osu.Game.Tests.Resources;
using osuTK;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
@ -92,12 +100,27 @@ namespace osu.Game.Tests.Visual.Editing
}
[Test]
public void TestCreateNewDifficulty()
public void TestCreateNewDifficulty([Values] bool sameRuleset)
{
string firstDifficultyName = Guid.NewGuid().ToString();
string secondDifficultyName = Guid.NewGuid().ToString();
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = firstDifficultyName);
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[]
{
new HitCircle
{
Position = new Vector2(0),
StartTime = 0
},
new HitCircle
{
Position = OsuPlayfield.BASE_SIZE,
StartTime = 1000
}
}));
AddStep("save beatmap", () => Editor.Save());
AddAssert("new beatmap persisted", () =>
{
@ -111,13 +134,27 @@ namespace osu.Game.Tests.Visual.Editing
});
AddAssert("can save again", () => Editor.Save());
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(sameRuleset ? new OsuRuleset().RulesetInfo : new CatchRuleset().RulesetInfo));
if (sameRuleset)
{
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
AddStep("confirm creation with no objects", () => DialogOverlay.CurrentDialog.PerformOkAction());
}
AddUntilStep("wait for created", () =>
{
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
return difficultyName != null && difficultyName != firstDifficultyName;
});
AddAssert("created difficulty has timing point", () =>
{
var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single();
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
});
AddAssert("created difficulty has no objects", () => EditorBeatmap.HitObjects.Count == 0);
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = secondDifficultyName);
AddStep("save beatmap", () => Editor.Save());
AddAssert("new beatmap persisted", () =>
@ -132,6 +169,105 @@ namespace osu.Game.Tests.Visual.Editing
});
}
[Test]
public void TestCopyDifficulty()
{
string originalDifficultyName = Guid.NewGuid().ToString();
string copyDifficultyName = $"{originalDifficultyName} (copy)";
AddStep("set unique difficulty name", () => EditorBeatmap.BeatmapInfo.DifficultyName = originalDifficultyName);
AddStep("add timing point", () => EditorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint { BeatLength = 1000 }));
AddStep("add hitobjects", () => EditorBeatmap.AddRange(new[]
{
new HitCircle
{
Position = new Vector2(0),
StartTime = 0
},
new HitCircle
{
Position = OsuPlayfield.BASE_SIZE,
StartTime = 1000
}
}));
AddStep("set approach rate", () => EditorBeatmap.Difficulty.ApproachRate = 4);
AddStep("set combo colours", () =>
{
var beatmapSkin = EditorBeatmap.BeatmapSkin.AsNonNull();
beatmapSkin.ComboColours.Clear();
beatmapSkin.ComboColours.AddRange(new[]
{
new Colour4(255, 0, 0, 255),
new Colour4(0, 0, 255, 255)
});
});
AddStep("set status & online ID", () =>
{
EditorBeatmap.BeatmapInfo.OnlineID = 123456;
EditorBeatmap.BeatmapInfo.Status = BeatmapOnlineStatus.WIP;
});
AddStep("save beatmap", () => Editor.Save());
AddAssert("new beatmap persisted", () =>
{
var beatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == originalDifficultyName);
var set = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID);
return beatmap != null
&& beatmap.DifficultyName == originalDifficultyName
&& set != null
&& set.PerformRead(s => s.Beatmaps.Single().ID == beatmap.ID);
});
AddAssert("can save again", () => Editor.Save());
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
AddStep("confirm creation as a copy", () => DialogOverlay.CurrentDialog.Buttons.ElementAt(1).TriggerClick());
AddUntilStep("wait for created", () =>
{
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;
return difficultyName != null && difficultyName != originalDifficultyName;
});
AddAssert("created difficulty has copy suffix in name", () => EditorBeatmap.BeatmapInfo.DifficultyName == copyDifficultyName);
AddAssert("created difficulty has timing point", () =>
{
var timingPoint = EditorBeatmap.ControlPointInfo.TimingPoints.Single();
return timingPoint.Time == 0 && timingPoint.BeatLength == 1000;
});
AddAssert("created difficulty has objects", () => EditorBeatmap.HitObjects.Count == 2);
AddAssert("approach rate correctly copied", () => EditorBeatmap.Difficulty.ApproachRate == 4);
AddAssert("combo colours correctly copied", () => EditorBeatmap.BeatmapSkin.AsNonNull().ComboColours.Count == 2);
AddAssert("status not copied", () => EditorBeatmap.BeatmapInfo.Status == BeatmapOnlineStatus.None);
AddAssert("online ID not copied", () => EditorBeatmap.BeatmapInfo.OnlineID == -1);
AddStep("save beatmap", () => Editor.Save());
BeatmapInfo refetchedBeatmap = null;
Live<BeatmapSetInfo> refetchedBeatmapSet = null;
AddStep("refetch from database", () =>
{
refetchedBeatmap = beatmapManager.QueryBeatmap(b => b.DifficultyName == copyDifficultyName);
refetchedBeatmapSet = beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID);
});
AddAssert("new beatmap persisted", () =>
{
return refetchedBeatmap != null
&& refetchedBeatmap.DifficultyName == copyDifficultyName
&& refetchedBeatmapSet != null
&& refetchedBeatmapSet.PerformRead(s =>
s.Beatmaps.Count == 2
&& s.Beatmaps.Any(b => b.DifficultyName == originalDifficultyName)
&& s.Beatmaps.Any(b => b.DifficultyName == copyDifficultyName));
});
AddAssert("old beatmap file not deleted", () => refetchedBeatmapSet.AsNonNull().PerformRead(s => s.Files.Count == 2));
}
[Test]
public void TestCreateNewBeatmapFailsWithBlankNamedDifficulties()
{
@ -154,7 +290,7 @@ namespace osu.Game.Tests.Visual.Editing
}
[Test]
public void TestCreateNewBeatmapFailsWithSameNamedDifficulties()
public void TestCreateNewBeatmapFailsWithSameNamedDifficulties([Values] bool sameRuleset)
{
Guid setId = Guid.Empty;
const string duplicate_difficulty_name = "duplicate";
@ -168,7 +304,14 @@ namespace osu.Game.Tests.Visual.Editing
return set != null && set.PerformRead(s => s.Beatmaps.Count == 1 && s.Files.Count == 1);
});
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(new OsuRuleset().RulesetInfo));
AddStep("create new difficulty", () => Editor.CreateNewDifficulty(sameRuleset ? new OsuRuleset().RulesetInfo : new CatchRuleset().RulesetInfo));
if (sameRuleset)
{
AddUntilStep("wait for dialog", () => DialogOverlay.CurrentDialog is CreateNewDifficultyDialog);
AddStep("confirm creation with no objects", () => DialogOverlay.CurrentDialog.PerformOkAction());
}
AddUntilStep("wait for created", () =>
{
string difficultyName = Editor.ChildrenOfType<EditorBeatmap>().SingleOrDefault()?.BeatmapInfo.DifficultyName;

View File

@ -4,6 +4,7 @@
using System;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Online.Multiplayer;
@ -71,7 +72,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("change queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings
{
QueueMode = QueueMode.AllPlayers
}));
}).WaitSafely());
AddUntilStep("api room updated", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
}

View File

@ -826,7 +826,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem
{
BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID
})));
})).WaitSafely());
AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2);
@ -857,11 +857,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("add item as other user", () => client.AddUserPlaylistItem(1234, new MultiplayerPlaylistItem(new PlaylistItem
{
BeatmapID = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0)).BeatmapInfo.OnlineID
})));
})).WaitSafely());
AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2);
AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2));
AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2).WaitSafely());
AddUntilStep("item removed from playlist", () => client.Room?.Playlist.Count == 1);
AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());

View File

@ -60,7 +60,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
});
AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
}
[Test]
@ -97,19 +97,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
addItemStep();
addItemStep();
AddStep("finish current item", () => Client.FinishCurrentItem());
AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely());
assertItemInHistoryListStep(1, 0);
assertItemInQueueListStep(2, 0);
assertItemInQueueListStep(3, 1);
AddStep("finish current item", () => Client.FinishCurrentItem());
AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely());
assertItemInHistoryListStep(2, 0);
assertItemInHistoryListStep(1, 1);
assertItemInQueueListStep(3, 0);
AddStep("finish current item", () => Client.FinishCurrentItem());
AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely());
assertItemInHistoryListStep(3, 0);
assertItemInHistoryListStep(2, 1);
@ -120,7 +120,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
public void TestListsClearedWhenRoomLeft()
{
addItemStep();
AddStep("finish current item", () => Client.FinishCurrentItem());
AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely());
AddStep("leave room", () => RoomManager.PartRoom());
AddUntilStep("wait for room part", () => !RoomJoined);

View File

@ -61,13 +61,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedBeatmap = importedSet.Beatmaps.First(b => b.Ruleset.OnlineID == 0);
});
AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
AddStep("change to all players mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
}
[Test]
public void TestDeleteButtonAlwaysVisibleForHost()
{
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
@ -79,7 +79,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestDeleteButtonOnlyVisibleForItemOwnerIfNotHost()
{
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
AddStep("join other user", () => Client.AddUser(new APIUser { Id = 1234 }));
@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
[Test]
public void TestCurrentItemDoesNotHaveDeleteButton()
{
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }));
AddStep("set all players queue mode", () => Client.ChangeSettings(new MultiplayerRoomSettings { QueueMode = QueueMode.AllPlayers }).WaitSafely());
AddUntilStep("wait for queue mode change", () => Client.APIRoom?.QueueMode.Value == QueueMode.AllPlayers);
addPlaylistItem(() => API.LocalUser.Value.OnlineID);
@ -106,7 +106,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
assertDeleteButtonVisibility(0, false);
assertDeleteButtonVisibility(1, true);
AddStep("finish current item", () => Client.FinishCurrentItem());
AddStep("finish current item", () => Client.FinishCurrentItem().WaitSafely());
AddUntilStep("wait for next item to be selected", () => Client.Room?.Settings.PlaylistItemId == 2);
AddUntilStep("wait for two items in playlist", () => playlist.ChildrenOfType<DrawableRoomPlaylistItem>().Count() == 2);
@ -126,7 +126,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
BeatmapID = importedBeatmap.OnlineID,
});
Client.AddUserPlaylistItem(userId(), item);
Client.AddUserPlaylistItem(userId(), item).WaitSafely();
itemId = item.ID;
});

View File

@ -139,7 +139,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("change match type", () => client.ChangeSettings(new MultiplayerRoomSettings
{
MatchType = MatchType.TeamVersus
}));
}).WaitSafely());
AddUntilStep("api room updated to team versus", () => client.APIRoom?.Type.Value == MatchType.TeamVersus);
}