diff --git a/osu.Game.Tests/Database/BeatmapImporterUpdateTests.cs b/osu.Game.Tests/Database/BeatmapImporterUpdateTests.cs
index a82386fd51..90648c616e 100644
--- a/osu.Game.Tests/Database/BeatmapImporterUpdateTests.cs
+++ b/osu.Game.Tests/Database/BeatmapImporterUpdateTests.cs
@@ -9,6 +9,7 @@ using System.Linq.Expressions;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Game.Beatmaps;
+using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Models;
using osu.Game.Overlays.Notifications;
@@ -400,6 +401,122 @@ namespace osu.Game.Tests.Database
});
}
+ ///
+ /// If all difficulties in the original beatmap set are in a collection, presume the user also wants new difficulties added.
+ ///
+ [TestCase(false)]
+ [TestCase(true)]
+ public void TestCollectionTransferNewBeatmap(bool allOriginalBeatmapsInCollection)
+ {
+ RunTestWithRealmAsync(async (realm, storage) =>
+ {
+ var importer = new BeatmapImporter(storage, realm);
+ using var rulesets = new RealmRulesetStore(realm, storage);
+
+ using var __ = getBeatmapArchive(out string pathOriginal);
+ using var _ = getBeatmapArchiveWithModifications(out string pathMissingOneBeatmap, directory =>
+ {
+ // remove one difficulty before first import
+ directory.GetFiles("*.osu").First().Delete();
+ });
+
+ var importBeforeUpdate = await importer.Import(new ImportTask(pathMissingOneBeatmap));
+
+ Assert.That(importBeforeUpdate, Is.Not.Null);
+ Debug.Assert(importBeforeUpdate != null);
+
+ int beatmapsToAddToCollection = 0;
+
+ importBeforeUpdate.PerformWrite(s =>
+ {
+ var beatmapCollection = s.Realm.Add(new BeatmapCollection("test collection"));
+ beatmapsToAddToCollection = s.Beatmaps.Count - (allOriginalBeatmapsInCollection ? 0 : 1);
+
+ for (int i = 0; i < beatmapsToAddToCollection; i++)
+ beatmapCollection.BeatmapMD5Hashes.Add(s.Beatmaps[i].MD5Hash);
+ });
+
+ // Second import matches first but contains one extra .osu file.
+ var importAfterUpdate = await importer.ImportAsUpdate(new ProgressNotification(), new ImportTask(pathOriginal), importBeforeUpdate.Value);
+
+ Assert.That(importAfterUpdate, Is.Not.Null);
+ Debug.Assert(importAfterUpdate != null);
+
+ importAfterUpdate.PerformRead(updated =>
+ {
+ string[] hashes = updated.Realm.All().Single().BeatmapMD5Hashes.ToArray();
+
+ if (allOriginalBeatmapsInCollection)
+ {
+ Assert.That(updated.Beatmaps.Count, Is.EqualTo(beatmapsToAddToCollection + 1));
+ Assert.That(hashes, Has.Length.EqualTo(updated.Beatmaps.Count));
+ }
+ else
+ {
+ // Collection contains one less than the original beatmap, and two less after update (new difficulty included).
+ Assert.That(updated.Beatmaps.Count, Is.EqualTo(beatmapsToAddToCollection + 2));
+ Assert.That(hashes, Has.Length.EqualTo(beatmapsToAddToCollection));
+ }
+ });
+ });
+ }
+
+ ///
+ /// If a difficulty in the original beatmap set is modified, the updated version should remain in any collections it was in.
+ ///
+ [Test]
+ public void TestCollectionTransferModifiedBeatmap()
+ {
+ RunTestWithRealmAsync(async (realm, storage) =>
+ {
+ var importer = new BeatmapImporter(storage, realm);
+ using var rulesets = new RealmRulesetStore(realm, storage);
+
+ using var __ = getBeatmapArchive(out string pathOriginal);
+ using var _ = getBeatmapArchiveWithModifications(out string pathModified, directory =>
+ {
+ // Modify one .osu file with different content.
+ var firstOsuFile = directory.GetFiles("*[Hard]*.osu").First();
+
+ string existingContent = File.ReadAllText(firstOsuFile.FullName);
+
+ File.WriteAllText(firstOsuFile.FullName, existingContent + "\n# I am new content");
+ });
+
+ var importBeforeUpdate = await importer.Import(new ImportTask(pathOriginal));
+
+ Assert.That(importBeforeUpdate, Is.Not.Null);
+ Debug.Assert(importBeforeUpdate != null);
+
+ string originalHash = string.Empty;
+
+ importBeforeUpdate.PerformWrite(s =>
+ {
+ var beatmapCollection = s.Realm.Add(new BeatmapCollection("test collection"));
+ originalHash = s.Beatmaps.Single(b => b.DifficultyName == "Hard").MD5Hash;
+
+ beatmapCollection.BeatmapMD5Hashes.Add(originalHash);
+ });
+
+ // Second import matches first but contains one extra .osu file.
+ var importAfterUpdate = await importer.ImportAsUpdate(new ProgressNotification(), new ImportTask(pathModified), importBeforeUpdate.Value);
+
+ Assert.That(importAfterUpdate, Is.Not.Null);
+ Debug.Assert(importAfterUpdate != null);
+
+ importAfterUpdate.PerformRead(updated =>
+ {
+ string[] hashes = updated.Realm.All().Single().BeatmapMD5Hashes.ToArray();
+ string updatedHash = updated.Beatmaps.Single(b => b.DifficultyName == "Hard").MD5Hash;
+
+ Assert.That(hashes, Has.Length.EqualTo(1));
+ Assert.That(hashes.First(), Is.EqualTo(updatedHash));
+
+ Assert.That(updatedHash, Is.Not.EqualTo(originalHash));
+ });
+ });
+ }
+
private static void checkCount(RealmAccess realm, int expected, Expression>? condition = null) where T : RealmObject
{
var query = realm.Realm.All();