using Flaro.Core.Library; namespace Flaro.Core.Tests; public class LibraryWalkerTests { private string _wurzel = ""; [SetUp] public void Anlegen() => _wurzel = Directory.CreateDirectory( Path.Combine(Path.GetTempPath(), "flaro-bestand-" + Guid.CreateVersion7().ToString("N"))).FullName; [TearDown] public void Aufraeumen() { // Ein Test sperrt absichtlich einen Ordner; ohne Zurücksetzen liesse // er sich nicht mehr löschen. if (!OperatingSystem.IsWindows()) { foreach (var d in Directory.EnumerateDirectories(_wurzel, "*", SearchOption.AllDirectories)) File.SetUnixFileMode(d, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute); } try { Directory.Delete(_wurzel, recursive: true); } catch (IOException) { } } private void Datei(string relativ, int bytes = 1024) { var voll = Path.Combine(_wurzel, relativ); Directory.CreateDirectory(Path.GetDirectoryName(voll)!); File.WriteAllBytes(voll, new byte[bytes]); } private string[] GefundeneNamen(WalkResult ergebnis) => ergebnis.Files.Select(f => Path.GetFileName(f.Path)).Order().ToArray(); [Test] public void Videodateien_werden_gefunden_Beiwerk_nicht() { Datei("Filme/The Matrix (1999).mkv"); Datei("Filme/The Matrix (1999).srt"); Datei("Filme/poster.jpg"); Datei("Filme/The Matrix (1999).nfo"); Assert.That(GefundeneNamen(LibraryWalker.Walk(_wurzel)), Is.EqualTo(new[] { "The Matrix (1999).mkv" })); } [Test] public void Auch_tief_verschachtelt_wird_gefunden() { Datei("Serien/Dark/Staffel 1/Dark - S01E01.mkv"); Datei("Serien/Dark/Staffel 2/Dark - S02E01.mkv"); Assert.That(LibraryWalker.Walk(_wurzel).Files, Has.Count.EqualTo(2)); } /// Der Fund, der eine Mediathek sonst verdoppelt. /// /// /// @eaDir ist Synologys Vorschauablage und enthält eine Kopie jeder /// Datei. Mit SearchOption.AllDirectories — der bequemen /// Fassung — liefe der Scan hinein und fände jeden Film zweimal, einmal /// davon als unbrauchbare Kopie. Genau deshalb steigt der Walker von Hand /// ab. /// [Test] public void Vorschauablagen_und_Papierkoerbe_werden_uebersprungen() { Datei("Filme/The Matrix (1999).mkv"); Datei("Filme/@eaDir/The Matrix (1999).mkv/SYNOPHOTO_THUMB.mkv"); Datei("Filme/#recycle/Alter Film (2001).mkv"); Datei("Filme/.versteckt/Noch einer (2002).mkv"); Datei("Filme/Extras/Making Of.mkv"); Assert.That(GefundeneNamen(LibraryWalker.Walk(_wurzel)), Is.EqualTo(new[] { "The Matrix (1999).mkv" })); } [Test] public void Groesse_und_Aenderungszeit_kommen_mit() { Datei("Filme/Film (2000).mkv", bytes: 4096); var gefunden = LibraryWalker.Walk(_wurzel).Files.Single(); Assert.That(gefunden.SizeBytes, Is.EqualTo(4096)); Assert.That(gefunden.ModifiedAt, Is.GreaterThan(DateTimeOffset.UtcNow.AddMinutes(-5))); } /// Ein gesperrter Ordner darf nicht den ganzen Lauf verderben. /// /// /// Sonst entschiede ein einzelner falsch gesetzter Unterordner darüber, ob /// überhaupt etwas gefunden wird — und die Mediathek bliebe leer, ohne dass /// jemand sagen könnte, warum. /// [Test] public void Ein_gesperrter_Ordner_wird_vermerkt_und_uebersprungen() { if (OperatingSystem.IsWindows()) Assert.Ignore("Dateirechte verhalten sich dort anders."); Datei("Filme/Erreichbar (2000).mkv"); var gesperrt = Directory.CreateDirectory(Path.Combine(_wurzel, "Filme", "gesperrt")).FullName; File.WriteAllBytes(Path.Combine(gesperrt, "Versteckt (2001).mkv"), new byte[10]); if (OperatingSystem.IsWindows()) return; File.SetUnixFileMode(gesperrt, UnixFileMode.None); var ergebnis = LibraryWalker.Walk(_wurzel); Assert.That(GefundeneNamen(ergebnis), Is.EqualTo(new[] { "Erreichbar (2000).mkv" })); Assert.That(ergebnis.Problems, Has.Count.EqualTo(1)); Assert.That(ergebnis.Problems[0].Path, Is.EqualTo(gesperrt)); } [Test] public void Ein_Verzeichnis_das_es_nicht_gibt_wird_gemeldet_statt_zu_werfen() { var ergebnis = LibraryWalker.Walk(Path.Combine(_wurzel, "gibtesnicht")); Assert.That(ergebnis.Files, Is.Empty); Assert.That(ergebnis.Problems, Has.Count.EqualTo(1)); } [Test] public void Ein_leerer_Bestand_ist_kein_Fehler() { var ergebnis = LibraryWalker.Walk(_wurzel); Assert.That(ergebnis.Files, Is.Empty); Assert.That(ergebnis.Problems, Is.Empty); } } public class SortTitleTests { [TestCase("Der Untergang", "Untergang")] [TestCase("Die Welle", "Welle")] [TestCase("Das Boot", "Boot")] [TestCase("The Matrix", "Matrix")] [TestCase("A Quiet Place", "Quiet Place")] [TestCase("An American Werewolf", "American Werewolf")] [TestCase("Blade Runner", "Blade Runner")] [TestCase("Theater", "Theater")] public void Der_Artikel_faellt_fuers_Sortieren_weg(string titel, string erwartet) { Assert.That(SortTitle.For(titel), Is.EqualTo(erwartet)); } /// Ein Titel, der nur aus einem Artikel besteht, bleibt stehen. [TestCase("Die")] [TestCase("The")] public void Ein_blosser_Artikel_bleibt_als_Titel_erhalten(string titel) { Assert.That(SortTitle.For(titel), Is.EqualTo(titel)); } }