Fix extras naming and version assignment
This commit is contained in:
@@ -443,4 +443,68 @@ public class BaseItemTests
|
||||
Assert.Equal(1982, trailer.ProductionYear);
|
||||
Assert.Equal(new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc), trailer.PremiereDate);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
// An extra named after a version belongs to that version, not to the primary whose name it
|
||||
// also starts with
|
||||
[InlineData("/Movies/Movie/Movie - 4K-trailer.mkv", 2)]
|
||||
[InlineData("/Movies/Movie/Movie - 1080p-behindthescenes.mkv", 1)]
|
||||
// Named after the movie rather than one of its versions
|
||||
[InlineData("/Movies/Movie/Movie-trailer.mkv", 0)]
|
||||
// In an extras folder, so named after nothing in particular
|
||||
[InlineData("/Movies/Movie/trailers/Official.mkv", 0)]
|
||||
// A version name is only a match when it is followed by the extra's own suffix
|
||||
[InlineData("/Movies/Movie/Movie - 4Kish-trailer.mkv", 0)]
|
||||
public void GetOwnerIdForExtra_AssignsExtraToItsVersion(string extraPath, int expectedVersion)
|
||||
{
|
||||
var (primary, alt1, alt2) = SetupVersionGroup();
|
||||
var expectedId = expectedVersion switch
|
||||
{
|
||||
1 => alt1.Id,
|
||||
2 => alt2.Id,
|
||||
_ => primary.Id
|
||||
};
|
||||
|
||||
var method = typeof(Video).GetMethod("GetOwnerIdForExtra", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Assert.NotNull(method);
|
||||
|
||||
var ownerId = (Guid)method!.Invoke(primary, [new Video { Id = Guid.NewGuid(), Path = extraPath }])!;
|
||||
|
||||
Assert.Equal(expectedId, ownerId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetExtraOwnerIds_FromAnyVersion_CoversEveryVersion()
|
||||
{
|
||||
var (primary, alt1, alt2) = SetupVersionGroup();
|
||||
|
||||
var method = typeof(Video).GetMethod("GetExtraOwnerIds", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Assert.NotNull(method);
|
||||
|
||||
// An extra is owned by the one version it is named after, and the extras of the movie as a
|
||||
// whole are owned by the primary, so every version has to read all of them back
|
||||
foreach (var version in new[] { primary, alt1, alt2 })
|
||||
{
|
||||
var ids = (Guid[])method!.Invoke(version, null)!;
|
||||
|
||||
Assert.Equal(3, ids.Length);
|
||||
Assert.Contains(primary.Id, ids);
|
||||
Assert.Contains(alt1.Id, ids);
|
||||
Assert.Contains(alt2.Id, ids);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOwnedVersionIds_CoversEveryLocalVersion()
|
||||
{
|
||||
var (primary, alt1, alt2) = SetupVersionGroup();
|
||||
|
||||
var method = typeof(Video).GetMethod("GetOwnedVersionIds", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Assert.NotNull(method);
|
||||
|
||||
// The extras of all versions are maintained together, so all of them have to be read back
|
||||
var ids = (Guid[])method!.Invoke(primary, null)!;
|
||||
|
||||
Assert.Equal([primary.Id, alt1.Id, alt2.Id], ids);
|
||||
}
|
||||
}
|
||||
|
||||
+231
-19
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using Emby.Naming.Common;
|
||||
@@ -17,6 +18,7 @@ using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.IO;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
@@ -38,9 +40,15 @@ public class FindExtrasTests
|
||||
itemRepository.Setup(i => i.RetrieveItem(It.IsAny<Guid>())).Returns<BaseItem>(null);
|
||||
_fileSystemMock = fixture.Freeze<Mock<IFileSystem>>();
|
||||
_fileSystemMock.Setup(f => f.GetFileInfo(It.IsAny<string>())).Returns<string>(path => new FileSystemMetadata { FullName = path });
|
||||
|
||||
var strings = LoadCoreStrings();
|
||||
fixture.Freeze<Mock<ILocalizationManager>>()
|
||||
.Setup(l => l.GetServerLocalizedString(It.IsAny<string>()))
|
||||
.Returns<string>(key => strings.TryGetValue(key, out var value) ? value : key);
|
||||
|
||||
_libraryManager = fixture.Build<Emby.Server.Implementations.Library.LibraryManager>().Do(s => s.AddParts(
|
||||
fixture.Create<IEnumerable<IResolverIgnoreRule>>(),
|
||||
new List<IItemResolver> { new AudioResolver(fixture.Create<NamingOptions>()) },
|
||||
[new AudioResolver(fixture.Create<NamingOptions>())],
|
||||
fixture.Create<IEnumerable<IIntroProvider>>(),
|
||||
fixture.Create<IEnumerable<IBaseItemComparer>>(),
|
||||
fixture.Create<IEnumerable<ILibraryPostScanTask>>()))
|
||||
@@ -51,6 +59,16 @@ public class FindExtrasTests
|
||||
BaseItem.MediaSourceManager ??= fixture.Create<IMediaSourceManager>();
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> LoadCoreStrings()
|
||||
{
|
||||
using var stream = typeof(Emby.Server.Implementations.Library.LibraryManager).Assembly
|
||||
.GetManifestResourceStream("Emby.Server.Implementations.Localization.Core.en-US.json")
|
||||
?? throw new InvalidOperationException("Core localization resource is missing");
|
||||
|
||||
return JsonSerializer.Deserialize<Dictionary<string, string>>(stream)
|
||||
?? throw new InvalidOperationException("Core localization resource is empty");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_SeparateMovieFolder_FindsCorrectExtras()
|
||||
{
|
||||
@@ -132,60 +150,60 @@ public class FindExtrasTests
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(new List<FileSystemMetadata>
|
||||
{
|
||||
.Returns(
|
||||
[
|
||||
new()
|
||||
{
|
||||
FullName = "/movies/Up/trailers/some trailer.mkv",
|
||||
Name = "some trailer.mkv",
|
||||
IsDirectory = false
|
||||
}
|
||||
}).Verifiable();
|
||||
]).Verifiable();
|
||||
|
||||
_fileSystemMock.Setup(f => f.GetFiles(
|
||||
"/movies/Up/behind the scenes",
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(new List<FileSystemMetadata>
|
||||
{
|
||||
.Returns(
|
||||
[
|
||||
new()
|
||||
{
|
||||
FullName = "/movies/Up/behind the scenes/the making of Up.mkv",
|
||||
Name = "the making of Up.mkv",
|
||||
IsDirectory = false
|
||||
}
|
||||
}).Verifiable();
|
||||
]).Verifiable();
|
||||
|
||||
_fileSystemMock.Setup(f => f.GetFiles(
|
||||
"/movies/Up/theme-music",
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(new List<FileSystemMetadata>
|
||||
{
|
||||
.Returns(
|
||||
[
|
||||
new()
|
||||
{
|
||||
FullName = "/movies/Up/theme-music/theme2.mp3",
|
||||
Name = "theme2.mp3",
|
||||
IsDirectory = false
|
||||
}
|
||||
}).Verifiable();
|
||||
]).Verifiable();
|
||||
|
||||
_fileSystemMock.Setup(f => f.GetFiles(
|
||||
"/movies/Up/extras",
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(new List<FileSystemMetadata>
|
||||
{
|
||||
.Returns(
|
||||
[
|
||||
new()
|
||||
{
|
||||
FullName = "/movies/Up/extras/Honest Trailer.mkv",
|
||||
Name = "Honest Trailer.mkv",
|
||||
IsDirectory = false
|
||||
}
|
||||
}).Verifiable();
|
||||
]).Verifiable();
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
@@ -289,15 +307,15 @@ public class FindExtrasTests
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(new List<FileSystemMetadata>
|
||||
{
|
||||
.Returns(
|
||||
[
|
||||
new()
|
||||
{
|
||||
FullName = "/movies/Up/trailers/trailer.jpg",
|
||||
Name = "trailer.jpg",
|
||||
IsDirectory = false
|
||||
}
|
||||
}).Verifiable();
|
||||
]).Verifiable();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
@@ -320,15 +338,15 @@ public class FindExtrasTests
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(new List<FileSystemMetadata>
|
||||
{
|
||||
.Returns(
|
||||
[
|
||||
new()
|
||||
{
|
||||
FullName = "/movies/Up/trailers/Trailer 1 (2013).mkv",
|
||||
Name = "Trailer 1 (2013).mkv",
|
||||
IsDirectory = false
|
||||
}
|
||||
}).Verifiable();
|
||||
]).Verifiable();
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
@@ -372,4 +390,198 @@ public class FindExtrasTests
|
||||
Assert.Equal("/series/Dexter/trailer.mkv", extras[0].Path);
|
||||
Assert.Equal("/series/Dexter/trailers/trailer2.mkv", extras[1].Path);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_SameExtraInSeveralContainers_ReturnsEach()
|
||||
{
|
||||
var owner = new Movie { Name = "Skyscraper", Path = "/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC].mkv" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC].mkv",
|
||||
"/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-trailer.mkv",
|
||||
"/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-trailer.mp4",
|
||||
"/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-behindthescenes.mkv",
|
||||
"/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-behindthescenes.mp4"
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
IsDirectory = false
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object))
|
||||
.ToDictionary(e => e.Path, e => e.Name, StringComparer.Ordinal);
|
||||
|
||||
// A container is a separate file that plays on its own, so it is a separate extra
|
||||
Assert.Equal(4, extras.Count);
|
||||
Assert.Equal("Behind The Scenes", extras["/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-behindthescenes.mkv"]);
|
||||
Assert.Equal("Behind The Scenes 2", extras["/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-behindthescenes.mp4"]);
|
||||
Assert.Equal("Trailer", extras["/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-trailer.mkv"]);
|
||||
Assert.Equal("Trailer 2", extras["/movies/Skyscraper (2018)/Skyscraper (2018) - [1080p HEVC]-trailer.mp4"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_SameExtraInSeveralResolutions_ReturnsEach()
|
||||
{
|
||||
var owner = new Movie { Name = "Dragon 2", Path = "/movies/Dragon 2 (2014)/Dragon 2 (2014) - [2160p].mkv" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/movies/Dragon 2 (2014)/Dragon 2 (2014) - [2160p].mkv",
|
||||
"/movies/Dragon 2 (2014)/Dragon 2 (2014) - [1080p]-trailer.mkv",
|
||||
"/movies/Dragon 2 (2014)/Dragon 2 (2014) - [2160p]-trailer.mkv"
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
IsDirectory = false
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object))
|
||||
.ToDictionary(e => e.Path, e => e.Name, StringComparer.Ordinal);
|
||||
|
||||
Assert.Equal(2, extras.Count);
|
||||
Assert.Equal("Trailer", extras["/movies/Dragon 2 (2014)/Dragon 2 (2014) - [1080p]-trailer.mkv"]);
|
||||
Assert.Equal("Trailer 2", extras["/movies/Dragon 2 (2014)/Dragon 2 (2014) - [2160p]-trailer.mkv"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_NumberedExtras_AreKeptApart()
|
||||
{
|
||||
var owner = new Movie { Name = "Up", Path = "/movies/Up (2009)/Up (2009).mkv" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/movies/Up (2009)/Up (2009).mkv",
|
||||
"/movies/Up (2009)/Up (2009)-trailer.mkv",
|
||||
"/movies/Up (2009)/Up (2009)-trailer2.mkv",
|
||||
"/movies/Up (2009)/Up (2009)-trailer2.mp4",
|
||||
"/movies/Up (2009)/Up (2009)-trailer3.mkv"
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
IsDirectory = false
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.Path, StringComparer.Ordinal).ToList();
|
||||
|
||||
Assert.Equal(4, extras.Count);
|
||||
Assert.Equal("/movies/Up (2009)/Up (2009)-trailer.mkv", extras[0].Path);
|
||||
Assert.Equal("/movies/Up (2009)/Up (2009)-trailer2.mkv", extras[1].Path);
|
||||
Assert.Equal("/movies/Up (2009)/Up (2009)-trailer2.mp4", extras[2].Path);
|
||||
Assert.Equal("/movies/Up (2009)/Up (2009)-trailer3.mkv", extras[3].Path);
|
||||
|
||||
// The index in the file name is not the number the extra is given, which counts the
|
||||
// extras of a type as they are found
|
||||
Assert.Equal("Trailer", extras[0].Name);
|
||||
Assert.Equal("Trailer 2", extras[1].Name);
|
||||
Assert.Equal("Trailer 3", extras[2].Name);
|
||||
Assert.Equal("Trailer 4", extras[3].Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_ExtraWithOwnTitleBesideOwner_KeepsTitle()
|
||||
{
|
||||
var owner = new Movie { Name = "Up", Path = "/movies/Up (2009)/Up (2009).mkv" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/movies/Up (2009)/Up (2009).mkv",
|
||||
"/movies/Up (2009)/Up (2009)-trailer.mkv",
|
||||
"/movies/Up (2009)/Recording the audio-behindthescenes.mkv",
|
||||
"/movies/Up (2009)/Up (2009)-behindthescenes.mkv"
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
IsDirectory = false
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object))
|
||||
.ToDictionary(e => e.Path, e => e.Name, StringComparer.Ordinal);
|
||||
|
||||
Assert.Equal(3, extras.Count);
|
||||
Assert.Equal("Trailer", extras["/movies/Up (2009)/Up (2009)-trailer.mkv"]);
|
||||
|
||||
// A descriptive file name is a real title and survives, and does not consume a number
|
||||
Assert.Equal("Recording the audio", extras["/movies/Up (2009)/Recording the audio-behindthescenes.mkv"]);
|
||||
Assert.Equal("Behind The Scenes", extras["/movies/Up (2009)/Up (2009)-behindthescenes.mkv"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_ExtraInOwnFolder_IsNamedAfterItsFile()
|
||||
{
|
||||
var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/movies/Up/Up.mkv",
|
||||
"/movies/Up/trailers"
|
||||
};
|
||||
|
||||
_fileSystemMock.Setup(f => f.GetFiles(
|
||||
"/movies/Up/trailers",
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(
|
||||
[
|
||||
new() { FullName = "/movies/Up/trailers/Teaser.mkv", Name = "Teaser.mkv", IsDirectory = false },
|
||||
new() { FullName = "/movies/Up/trailers/Comic-Con Reel.mkv", Name = "Comic-Con Reel.mkv", IsDirectory = false }
|
||||
]).Verifiable();
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
Name = Path.GetFileName(p),
|
||||
IsDirectory = !Path.HasExtension(p)
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object))
|
||||
.ToDictionary(e => e.Path, e => e.Name, StringComparer.Ordinal);
|
||||
|
||||
_fileSystemMock.Verify();
|
||||
Assert.Equal(2, extras.Count);
|
||||
Assert.Equal("Teaser", extras["/movies/Up/trailers/Teaser.mkv"]);
|
||||
Assert.Equal("Comic-Con Reel", extras["/movies/Up/trailers/Comic-Con Reel.mkv"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_DistinctExtrasInSameFolder_AreKeptApart()
|
||||
{
|
||||
var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/movies/Up/Up.mkv",
|
||||
"/movies/Up/trailers"
|
||||
};
|
||||
|
||||
_fileSystemMock.Setup(f => f.GetFiles(
|
||||
"/movies/Up/trailers",
|
||||
It.IsAny<string[]>(),
|
||||
false,
|
||||
false))
|
||||
.Returns(
|
||||
[
|
||||
new() { FullName = "/movies/Up/trailers/Teaser.mkv", Name = "Teaser.mkv", IsDirectory = false },
|
||||
new() { FullName = "/movies/Up/trailers/Official.mkv", Name = "Official.mkv", IsDirectory = false },
|
||||
new() { FullName = "/movies/Up/trailers/Official.mp4", Name = "Official.mp4", IsDirectory = false }
|
||||
]).Verifiable();
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
Name = Path.GetFileName(p),
|
||||
IsDirectory = !Path.HasExtension(p)
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.Path, StringComparer.Ordinal).ToList();
|
||||
|
||||
_fileSystemMock.Verify();
|
||||
Assert.Equal(3, extras.Count);
|
||||
Assert.Equal("/movies/Up/trailers/Official.mkv", extras[0].Path);
|
||||
Assert.Equal("/movies/Up/trailers/Official.mp4", extras[1].Path);
|
||||
Assert.Equal("/movies/Up/trailers/Teaser.mkv", extras[2].Path);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user