using System.Text;
using Halo.Core.Library;
using Microsoft.Extensions.Logging.Abstractions;
namespace Halo.Media.Tests;
/// Was wirklich auf der Platte landet.
public class SidecarWriterTests
{
private string _ordner = "";
private string _film = "";
[SetUp]
public void Anlegen()
{
_ordner = Directory.CreateDirectory(Path.Combine(
Path.GetTempPath(), "halo-beiwerk-" + Guid.CreateVersion7().ToString("N"),
"Der Untergang (2004)")).FullName;
_film = Path.Combine(_ordner, "Der Untergang (2004).mkv");
File.WriteAllBytes(_film, new byte[2048]);
}
[TearDown]
public void Aufraeumen()
{
try { Directory.Delete(Path.GetDirectoryName(_ordner)!, recursive: true); } catch (IOException) { }
}
private static SidecarWriter Schreiber(bool an = true) =>
new(new SidecarOptions(an), NullLogger.Instance);
[Test]
public async Task Eine_NFO_landet_neben_dem_Film()
{
await Schreiber().WriteTextAsync(_film, SidecarNames.MovieNfo, "613");
var ziel = Path.Combine(_ordner, "movie.nfo");
Assert.That(File.Exists(ziel), Is.True);
Assert.That(await File.ReadAllTextAsync(ziel), Does.Contain("613"));
}
[Test]
public async Task Ein_Bild_landet_neben_dem_Film()
{
using var inhalt = new MemoryStream(Encoding.UTF8.GetBytes("ein plakat"));
await Schreiber().WriteStreamAsync(_film, SidecarNames.MoviePoster, inhalt);
Assert.That(File.Exists(Path.Combine(_ordner, "poster.jpg")), Is.True);
}
/// Die Prüfung, an der der Schutz des Bestands hängt.
///
///
/// Es muss laut scheitern, nicht still übergehen. Käme hier ein
/// Name durch, der nicht auf der Liste steht, wäre der gesamte Bestand
/// offen — und ein stilles Übergehen verstecke den Fehler, bis jemand
/// seine Filme vermisst.
///
[TestCase("film.mkv")]
[TestCase("../anderswo.nfo")]
[TestCase("/etc/passwd")]
[TestCase("unterordner/poster.jpg")]
[TestCase("beliebig.txt")]
public void Was_nicht_auf_der_Liste_steht_wird_laut_abgelehnt(string versuch)
{
var fehler = Assert.ThrowsAsync(
() => Schreiber().WriteTextAsync(_film, versuch, "egal"));
Assert.That(fehler!.Message, Does.Contain("Liste"));
}
/// Die Mediendatei bleibt unberührt — auch beim Versuch.
[Test]
public void Die_Mediendatei_wird_nie_angefasst()
{
var vorher = new FileInfo(_film).Length;
Assert.ThrowsAsync(
() => Schreiber().WriteTextAsync(_film, "Der Untergang (2004).mkv", "kaputt"));
Assert.That(new FileInfo(_film).Length, Is.EqualTo(vorher));
Assert.That(File.ReadAllBytes(_film).All(b => b == 0), Is.True);
}
/// Abgeschaltet heisst abgeschaltet.
[Test]
public async Task Ohne_Erlaubnis_wird_nichts_geschrieben()
{
await Schreiber(an: false).WriteTextAsync(_film, SidecarNames.MovieNfo, "");
Assert.That(File.Exists(Path.Combine(_ordner, "movie.nfo")), Is.False);
Assert.That(Schreiber(an: false).Enabled, Is.False);
}
/// Gelesen wird trotzdem.
///
///
/// Eine vorhandene NFO ist eine Zuordnung, die jemand getroffen hat. Sie
/// zu übergehen, bloss weil Halo selbst nicht schreiben darf, wäre
/// verkehrt herum.
///
[Test]
public async Task Gelesen_wird_auch_ohne_Schreiberlaubnis()
{
await File.WriteAllTextAsync(Path.Combine(_ordner, "movie.nfo"), "613");
var gelesen = await Schreiber(an: false).ReadTextAsync(_film, SidecarNames.MovieNfo);
Assert.That(Nfo.ReadIds(gelesen!).Tmdb, Is.EqualTo(613));
}
[Test]
public async Task Eine_fehlende_Datei_ergibt_null()
{
Assert.That(await Schreiber().ReadTextAsync(_film, SidecarNames.MovieNfo), Is.Null);
}
[Test]
public async Task Ein_zweites_Schreiben_ersetzt_das_erste()
{
await Schreiber().WriteTextAsync(_film, SidecarNames.MovieNfo, "alt");
await Schreiber().WriteTextAsync(_film, SidecarNames.MovieNfo, "neu");
Assert.That(await File.ReadAllTextAsync(Path.Combine(_ordner, "movie.nfo")), Is.EqualTo("neu"));
Assert.That(Directory.GetFiles(_ordner, "*.halo-tmp"), Is.Empty, "Keine Reste vom Umbenennen");
}
[Test]
public void Ein_Film_allein_im_Ordner_wird_erkannt()
{
Assert.That(Schreiber().IsAloneInFolder(_film), Is.True);
File.WriteAllBytes(Path.Combine(_ordner, "Noch ein Film (2005).mkv"), new byte[10]);
Assert.That(Schreiber().IsAloneInFolder(_film), Is.False);
}
/// Beiwerk zählt nicht als zweiter Film.
[Test]
public async Task Das_eigene_Beiwerk_macht_den_Film_nicht_unselbstaendig()
{
await Schreiber().WriteTextAsync(_film, SidecarNames.MovieNfo, "");
using var bild = new MemoryStream([1, 2, 3]);
await Schreiber().WriteStreamAsync(_film, SidecarNames.MoviePoster, bild);
Assert.That(Schreiber().IsAloneInFolder(_film), Is.True);
}
}