Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -299,15 +299,41 @@ public void should_keep_image_extra_file_tracking_but_disable_overwrites_when_ex
});
}

private static MetadataService CreateSubject(TestDisk disk)
[Test]
public void should_track_metadata_already_carried_by_an_audiobook_folder_move()
{
var disk = new TestDisk();
disk.TextFiles["/library/A Author/A Book/metadata.json"] = "moved with the folder";
var consumer = new TestMetadataConsumer();
disk.TrackedMetadata.Add(new MetadataFile
{
Id = 70,
AuthorId = 10,
BookId = 20,
Consumer = consumer.GetType().Name,
Type = MetadataType.BookMetadata,
RelativePath = "Old Book/metadata.json"
});
var subject = CreateSubject(disk, consumer);

subject.MoveFilesAfterRename(BuildAuthor(), new List<BookFile> { BuildBookFile() });

Assert.Multiple(() =>
{
Assert.That(disk.MovedFiles, Is.Empty);
Assert.That(disk.UpsertedMetadata.Single().RelativePath, Is.EqualTo("A Book/metadata.json"));
});
}

private static MetadataService CreateSubject(TestDisk disk, IMetadata consumer = null)
{
return new MetadataService(
configService: null,
diskProvider: disk.DiskProvider,
diskTransferService: null,
recycleBinProvider: null,
otherExtraFileRenamer: NoOp<IOtherExtraFileRenamer>(),
metadataFactory: null,
metadataFactory: consumer == null ? null : MetadataFactoryProxy.Create(consumer),
cleanMetadataService: null,
httpClient: Throwing<IHttpClient>(),
mediaFileAttributeService: NoOp<IMediaFileAttributeService>(),
Expand Down Expand Up @@ -398,6 +424,8 @@ private class TestDisk
public Dictionary<string, byte[]> BinaryFiles { get; } = new();
public List<int> DeletedMetadataIds { get; } = new();
public List<MetadataFile> UpsertedMetadata { get; } = new();
public List<MetadataFile> TrackedMetadata { get; } = new();
public List<string> MovedFiles { get; } = new();

public IDiskProvider DiskProvider
{
Expand Down Expand Up @@ -460,6 +488,12 @@ protected override object Invoke(MethodInfo targetMethod, object[] args)
return File.OpenRead(tempPath);
}

if (targetMethod?.Name == nameof(IDiskProvider.MoveFile))
{
Disk.MovedFiles.Add(TestDisk.NormalizePath((string)args[0]));
return null;
}

if (targetMethod?.Name == nameof(IDiskProvider.CopyFile))
{
var source = TestDisk.NormalizePath((string)args[0]);
Expand All @@ -484,6 +518,11 @@ private class MetadataFileServiceProxy : DispatchProxy

protected override object Invoke(MethodInfo targetMethod, object[] args)
{
if (targetMethod?.Name == nameof(IMetadataFileService.GetFilesByAuthor))
{
return Disk.TrackedMetadata;
}

if (targetMethod?.Name == nameof(IMetadataFileService.Delete))
{
Disk.DeletedMetadataIds.Add((int)args[0]);
Expand All @@ -508,6 +547,28 @@ protected override object Invoke(MethodInfo targetMethod, object[] args)
}
}

private class MetadataFactoryProxy : DispatchProxy
{
private IMetadata _consumer;

public static IMetadataFactory Create(IMetadata consumer)
{
var proxy = DispatchProxy.Create<IMetadataFactory, MetadataFactoryProxy>();
((MetadataFactoryProxy)(object)proxy)._consumer = consumer;
return proxy;
}

protected override object Invoke(MethodInfo targetMethod, object[] args)
{
if (targetMethod?.Name == nameof(IMetadataFactory.GetAvailableProviders))
{
return new List<IMetadata> { _consumer };
}

throw new NotImplementedException($"Test proxy does not implement IMetadataFactory.{targetMethod?.Name}");
}
}

private class NoOpProxy<T> : DispatchProxy
{
protected override object Invoke(MethodInfo targetMethod, object[] args)
Expand Down Expand Up @@ -556,7 +617,7 @@ public string GetFilenameAfterMove(Author author, BookFile bookFile, MetadataFil

public string GetFilenameAfterMove(Author author, string bookPath, MetadataFile metadataFile)
{
throw new NotImplementedException();
return Path.Combine(bookPath, Path.GetFileName(metadataFile.RelativePath));
}

public MetadataFile FindMetadataFile(Author author, string path)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NLog;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Books;
using NzbDrone.Core.Extras.Others;
using NzbDrone.Core.MediaFiles;

namespace Chaptarr.Core.Test.Extras.Others
{
[TestFixture]
public class OtherExtraServiceRenameFixture
{
private const string AuthorFolder = "/library/Zogarth";
private const string NewBookFolder = AuthorFolder + "/The Primal Hunter/01 - Primal Hunter 1";

[Test]
public void should_rename_an_extra_that_a_folder_move_carried_under_its_old_name()
{
var disk = new FakeDisk();
disk.Files.Add(NewBookFolder + "/Primal Hunter 1.jpg");
disk.Files.Add(NewBookFolder + "/Primal Hunter 1 - Tome 1.m4b");
var extraFiles = new FakeOtherExtraFileService();
extraFiles.Files.Add(new OtherExtraFile
{
Id = 5,
AuthorId = 1,
BookFileId = 40,
RelativePath = "Primal Hunter/Primal Hunter 1 - Tome1/Primal Hunter 1.jpg",
Extension = ".jpg"
});
var subject = new OtherExtraService(null, disk.Proxy, null, extraFiles.Proxy, null, LogManager.GetCurrentClassLogger());
var author = new Author { Id = 1, Name = "Zogarth", Path = AuthorFolder, AudiobookPath = AuthorFolder };
var bookFile = new BookFile { Id = 40, Path = NewBookFolder + "/Primal Hunter 1 - Tome 1.m4b" };

subject.MoveFilesAfterRename(author, new List<BookFile> { bookFile });

Assert.Multiple(() =>
{
Assert.That(disk.Moves, Is.EqualTo(new[] { $"{NewBookFolder}/Primal Hunter 1.jpg -> {NewBookFolder}/Primal Hunter 1 - Tome 1.jpg" }));
Assert.That(extraFiles.Upserted.Single().RelativePath, Is.EqualTo("The Primal Hunter/01 - Primal Hunter 1/Primal Hunter 1 - Tome 1.jpg"));
});
}

private sealed class FakeDisk
{
public HashSet<string> Files { get; } = new();
public List<string> Moves { get; } = new();

public IDiskProvider Proxy
{
get
{
var proxy = DispatchProxy.Create<IDiskProvider, DiskProxy>();
((DiskProxy)(object)proxy).Disk = this;
return proxy;
}
}
}

private class DiskProxy : DispatchProxy
{
public FakeDisk Disk { get; set; }

protected override object Invoke(MethodInfo targetMethod, object[] args)
{
switch (targetMethod?.Name)
{
case nameof(IDiskProvider.FileExists):
return Disk.Files.Contains((string)args[0]);
case nameof(IDiskProvider.MoveFile):
var source = (string)args[0];
if (!Disk.Files.Remove(source))
{
throw new System.IO.FileNotFoundException("File doesn't exist: " + source);
}

Disk.Files.Add((string)args[1]);
Disk.Moves.Add($"{source} -> {args[1]}");
return null;
default:
throw new NotImplementedException($"Test proxy does not implement IDiskProvider.{targetMethod?.Name}");
}
}
}

private sealed class FakeOtherExtraFileService
{
public List<OtherExtraFile> Files { get; } = new();
public List<OtherExtraFile> Upserted { get; } = new();

public IOtherExtraFileService Proxy
{
get
{
var proxy = DispatchProxy.Create<IOtherExtraFileService, ExtraFileServiceProxy>();
((ExtraFileServiceProxy)(object)proxy).Service = this;
return proxy;
}
}
}

private class ExtraFileServiceProxy : DispatchProxy
{
public FakeOtherExtraFileService Service { get; set; }

protected override object Invoke(MethodInfo targetMethod, object[] args)
{
switch (targetMethod?.Name)
{
case nameof(IOtherExtraFileService.GetFilesByAuthor):
return Service.Files;
case nameof(IOtherExtraFileService.Upsert) when args[0] is List<OtherExtraFile> files:
Service.Upserted.AddRange(files);
return null;
default:
throw new NotImplementedException($"Test proxy does not implement IOtherExtraFileService.{targetMethod?.Name}");
}
}
}
}
}
Loading