2020-01-03 12:49:24 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
2019-03-15 12:10:45 +00:00
|
|
|
using System.IO;
|
2020-01-03 12:49:24 +00:00
|
|
|
using System.Linq;
|
|
|
|
using FizzWare.NBuilder;
|
2019-03-15 12:10:45 +00:00
|
|
|
using FluentAssertions;
|
2023-12-06 17:25:18 +00:00
|
|
|
using Moq;
|
2020-01-03 12:49:24 +00:00
|
|
|
using NUnit.Framework;
|
|
|
|
using NzbDrone.Common.Disk;
|
|
|
|
using NzbDrone.Common.Extensions;
|
|
|
|
using NzbDrone.Core.Configuration;
|
2019-03-15 12:10:45 +00:00
|
|
|
using NzbDrone.Core.MediaFiles;
|
2023-12-06 17:25:18 +00:00
|
|
|
using NzbDrone.Core.MediaFiles.Events;
|
|
|
|
using NzbDrone.Core.Messaging.Events;
|
2019-03-15 12:10:45 +00:00
|
|
|
using NzbDrone.Core.Music;
|
|
|
|
using NzbDrone.Core.Test.Framework;
|
2019-03-19 13:38:42 +00:00
|
|
|
using NzbDrone.Test.Common;
|
2022-06-20 20:28:00 +00:00
|
|
|
using NzbDrone.Test.Common.AutoMoq;
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture
|
|
|
|
{
|
|
|
|
[TestFixture]
|
|
|
|
public class AudioTagServiceFixture : CoreTest<AudioTagService>
|
|
|
|
{
|
|
|
|
public static class TestCaseFactory
|
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
private static readonly string[] MediaFiles = new[] { "nin.mp2", "nin.mp3", "nin.flac", "nin.m4a", "nin.wma", "nin.ape", "nin.opus" };
|
2019-03-15 12:10:45 +00:00
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
private static readonly string[] SkipProperties = new[] { "IsValid", "Duration", "Quality", "MediaInfo", "ImageFile" };
|
|
|
|
private static readonly Dictionary<string, string[]> SkipPropertiesByFile = new Dictionary<string, string[]>
|
|
|
|
{
|
|
|
|
{ "nin.mp2", new[] { "OriginalReleaseDate" } }
|
2019-03-15 12:10:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
public static IEnumerable TestCases
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
foreach (var file in MediaFiles)
|
|
|
|
{
|
|
|
|
var toSkip = SkipProperties;
|
|
|
|
if (SkipPropertiesByFile.ContainsKey(file))
|
|
|
|
{
|
|
|
|
toSkip = toSkip.Union(SkipPropertiesByFile[file]).ToArray();
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-15 12:10:45 +00:00
|
|
|
yield return new TestCaseData(file, toSkip).SetName($"{{m}}_{file.Replace("nin.", "")}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
private readonly string _testdir = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media");
|
|
|
|
private string _copiedFile;
|
|
|
|
private AudioTag _testTags;
|
2019-07-19 12:41:17 +00:00
|
|
|
private IDiskProvider _diskProvider;
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-15 12:10:45 +00:00
|
|
|
[SetUp]
|
|
|
|
public void Setup()
|
|
|
|
{
|
2022-06-20 20:28:00 +00:00
|
|
|
_diskProvider = Mocker.Resolve<IDiskProvider>(FileSystemType.Actual);
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-15 12:10:45 +00:00
|
|
|
Mocker.GetMock<IConfigService>()
|
|
|
|
.Setup(x => x.WriteAudioTags)
|
|
|
|
.Returns(WriteAudioTagsType.Sync);
|
|
|
|
|
2024-02-04 20:26:15 +00:00
|
|
|
Mocker.GetMock<IConfigService>()
|
|
|
|
.Setup(x => x.EmbedCoverArt)
|
|
|
|
.Returns(true);
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
var imageFile = Path.Combine(_testdir, "nin.png");
|
2019-08-01 21:24:13 +00:00
|
|
|
var imageSize = _diskProvider.GetFileSize(imageFile);
|
|
|
|
|
2019-03-15 12:10:45 +00:00
|
|
|
// have to manually set the arrays of string parameters and integers to values > 1
|
2020-01-03 12:49:24 +00:00
|
|
|
_testTags = Builder<AudioTag>.CreateNew()
|
2019-03-15 12:10:45 +00:00
|
|
|
.With(x => x.Track = 2)
|
|
|
|
.With(x => x.TrackCount = 33)
|
|
|
|
.With(x => x.Disc = 44)
|
|
|
|
.With(x => x.DiscCount = 55)
|
|
|
|
.With(x => x.Date = new DateTime(2019, 3, 1))
|
|
|
|
.With(x => x.Year = 2019)
|
|
|
|
.With(x => x.OriginalReleaseDate = new DateTime(2009, 4, 1))
|
|
|
|
.With(x => x.OriginalYear = 2009)
|
2020-01-03 12:49:24 +00:00
|
|
|
.With(x => x.Performers = new[] { "Performer1" })
|
|
|
|
.With(x => x.AlbumArtists = new[] { "방탄소년단" })
|
|
|
|
.With(x => x.Genres = new[] { "Genre1", "Genre2" })
|
2019-08-01 21:24:13 +00:00
|
|
|
.With(x => x.ImageFile = imageFile)
|
|
|
|
.With(x => x.ImageSize = imageSize)
|
2019-03-15 12:10:45 +00:00
|
|
|
.Build();
|
|
|
|
}
|
|
|
|
|
|
|
|
[TearDown]
|
|
|
|
public void Cleanup()
|
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
if (File.Exists(_copiedFile))
|
2019-03-15 12:10:45 +00:00
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
File.Delete(_copiedFile);
|
2019-03-15 12:10:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GivenFileCopy(string filename)
|
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
var original = Path.Combine(_testdir, filename);
|
2019-03-15 12:10:45 +00:00
|
|
|
var tempname = $"temp_{Path.GetRandomFileName()}{Path.GetExtension(filename)}";
|
2020-01-03 12:49:24 +00:00
|
|
|
_copiedFile = Path.Combine(_testdir, tempname);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
File.Copy(original, _copiedFile);
|
2019-03-15 12:10:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void VerifyDifferent(AudioTag a, AudioTag b, string[] skipProperties)
|
|
|
|
{
|
|
|
|
foreach (var property in typeof(AudioTag).GetProperties())
|
|
|
|
{
|
|
|
|
if (skipProperties.Contains(property.Name))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-15 12:10:45 +00:00
|
|
|
if (property.CanRead)
|
|
|
|
{
|
|
|
|
if (property.PropertyType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEquatable<>)) ||
|
|
|
|
Nullable.GetUnderlyingType(property.PropertyType) != null)
|
|
|
|
{
|
|
|
|
var val1 = property.GetValue(a, null);
|
|
|
|
var val2 = property.GetValue(b, null);
|
|
|
|
val1.Should().NotBe(val2, $"{property.Name} should not be equal. Found {val1.NullSafe()} for both tags");
|
|
|
|
}
|
|
|
|
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
|
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
var val1 = (IEnumerable)property.GetValue(a, null);
|
|
|
|
var val2 = (IEnumerable)property.GetValue(b, null);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
if (val1 != null && val2 != null)
|
|
|
|
{
|
|
|
|
val1.Should().NotBeEquivalentTo(val2, $"{property.Name} should not be equal");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void VerifySame(AudioTag a, AudioTag b, string[] skipProperties)
|
|
|
|
{
|
|
|
|
foreach (var property in typeof(AudioTag).GetProperties())
|
|
|
|
{
|
|
|
|
if (skipProperties.Contains(property.Name))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (property.CanRead)
|
|
|
|
{
|
|
|
|
if (property.PropertyType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEquatable<>)) ||
|
|
|
|
Nullable.GetUnderlyingType(property.PropertyType) != null)
|
|
|
|
{
|
|
|
|
var val1 = property.GetValue(a, null);
|
|
|
|
var val2 = property.GetValue(b, null);
|
|
|
|
val1.Should().Be(val2, $"{property.Name} should be equal");
|
|
|
|
}
|
|
|
|
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
|
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
var val1 = (IEnumerable)property.GetValue(a, null);
|
|
|
|
var val2 = (IEnumerable)property.GetValue(b, null);
|
|
|
|
|
2019-03-19 13:38:42 +00:00
|
|
|
if (val1 != null || val2 != null)
|
|
|
|
{
|
|
|
|
val1.Should().BeEquivalentTo(val2, $"{property.Name} should be equal");
|
|
|
|
}
|
2019-03-15 12:10:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-15 12:10:45 +00:00
|
|
|
public void should_read_duration(string filename, string[] ignored)
|
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = Path.Combine(_testdir, filename);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
var tags = Subject.ReadTags(path);
|
|
|
|
|
|
|
|
tags.Duration.Should().BeCloseTo(new TimeSpan(0, 0, 1, 25, 130), 100);
|
|
|
|
}
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-15 12:10:45 +00:00
|
|
|
public void should_read_write_tags(string filename, string[] skipProperties)
|
|
|
|
{
|
|
|
|
GivenFileCopy(filename);
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = _copiedFile;
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
var initialtags = Subject.ReadAudioTag(path);
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
VerifyDifferent(initialtags, _testTags, skipProperties);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
_testTags.Write(path);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
var writtentags = Subject.ReadAudioTag(path);
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
VerifySame(writtentags, _testTags, skipProperties);
|
2019-03-15 12:10:45 +00:00
|
|
|
}
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-15 12:10:45 +00:00
|
|
|
public void should_remove_mb_tags(string filename, string[] skipProperties)
|
|
|
|
{
|
|
|
|
GivenFileCopy(filename);
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = _copiedFile;
|
2019-03-15 12:10:45 +00:00
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
var track = new TrackFile
|
|
|
|
{
|
2019-06-08 19:13:58 +00:00
|
|
|
Path = path
|
2019-03-15 12:10:45 +00:00
|
|
|
};
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
_testTags.Write(path);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
var withmb = Subject.ReadAudioTag(path);
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
VerifySame(withmb, _testTags, skipProperties);
|
2019-03-15 12:10:45 +00:00
|
|
|
|
|
|
|
Subject.RemoveMusicBrainzTags(track);
|
|
|
|
|
|
|
|
var tag = Subject.ReadAudioTag(path);
|
|
|
|
|
|
|
|
tag.MusicBrainzReleaseCountry.Should().BeNull();
|
|
|
|
tag.MusicBrainzReleaseStatus.Should().BeNull();
|
|
|
|
tag.MusicBrainzReleaseType.Should().BeNull();
|
|
|
|
tag.MusicBrainzReleaseId.Should().BeNull();
|
|
|
|
tag.MusicBrainzArtistId.Should().BeNull();
|
|
|
|
tag.MusicBrainzReleaseArtistId.Should().BeNull();
|
|
|
|
tag.MusicBrainzReleaseGroupId.Should().BeNull();
|
|
|
|
tag.MusicBrainzTrackId.Should().BeNull();
|
|
|
|
tag.MusicBrainzAlbumComment.Should().BeNull();
|
|
|
|
tag.MusicBrainzReleaseTrackId.Should().BeNull();
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-19 13:38:42 +00:00
|
|
|
public void should_read_audiotag_from_file_with_no_tags(string filename, string[] skipProperties)
|
|
|
|
{
|
|
|
|
GivenFileCopy(filename);
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = _copiedFile;
|
2019-03-19 13:38:42 +00:00
|
|
|
|
|
|
|
Subject.RemoveAllTags(path);
|
|
|
|
|
|
|
|
var tag = Subject.ReadAudioTag(path);
|
2020-01-03 12:49:24 +00:00
|
|
|
var expected = new AudioTag()
|
|
|
|
{
|
2023-04-12 02:31:27 +00:00
|
|
|
Performers = Array.Empty<string>(),
|
|
|
|
AlbumArtists = Array.Empty<string>(),
|
|
|
|
Genres = Array.Empty<string>()
|
2019-03-19 13:38:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
VerifySame(tag, expected, skipProperties);
|
|
|
|
tag.Quality.Should().NotBeNull();
|
|
|
|
tag.MediaInfo.Should().NotBeNull();
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-19 13:38:42 +00:00
|
|
|
public void should_read_parsedtrackinfo_from_file_with_no_tags(string filename, string[] skipProperties)
|
|
|
|
{
|
|
|
|
GivenFileCopy(filename);
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = _copiedFile;
|
2019-03-19 13:38:42 +00:00
|
|
|
|
|
|
|
Subject.RemoveAllTags(path);
|
|
|
|
|
|
|
|
var tag = Subject.ReadTags(path);
|
|
|
|
|
|
|
|
tag.Quality.Should().NotBeNull();
|
|
|
|
tag.MediaInfo.Should().NotBeNull();
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-19 13:38:42 +00:00
|
|
|
public void should_set_quality_and_mediainfo_for_corrupt_file(string filename, string[] skipProperties)
|
|
|
|
{
|
|
|
|
// use missing to simulate corrupt
|
|
|
|
var tag = Subject.ReadAudioTag(filename.Replace("nin", "missing"));
|
|
|
|
var expected = new AudioTag();
|
|
|
|
|
|
|
|
VerifySame(tag, expected, skipProperties);
|
|
|
|
tag.Quality.Should().NotBeNull();
|
|
|
|
tag.MediaInfo.Should().NotBeNull();
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-19 13:38:42 +00:00
|
|
|
ExceptionVerification.ExpectedErrors(1);
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-19 13:38:42 +00:00
|
|
|
public void should_read_file_with_only_title_tag(string filename, string[] ignored)
|
|
|
|
{
|
|
|
|
GivenFileCopy(filename);
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = _copiedFile;
|
2019-03-19 13:38:42 +00:00
|
|
|
|
|
|
|
Subject.RemoveAllTags(path);
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-19 13:38:42 +00:00
|
|
|
var nametag = new AudioTag();
|
|
|
|
nametag.Title = "test";
|
|
|
|
nametag.Write(path);
|
|
|
|
|
|
|
|
var tag = Subject.ReadTags(path);
|
|
|
|
tag.Title.Should().Be("test");
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-19 13:38:42 +00:00
|
|
|
tag.Quality.Should().NotBeNull();
|
|
|
|
tag.MediaInfo.Should().NotBeNull();
|
|
|
|
}
|
2020-01-03 12:49:24 +00:00
|
|
|
|
|
|
|
[Test]
|
2023-12-06 17:25:18 +00:00
|
|
|
[TestCaseSource(typeof(TestCaseFactory), nameof(TestCaseFactory.TestCases))]
|
2019-03-27 22:08:14 +00:00
|
|
|
public void should_remove_date_from_tags_when_not_in_metadata(string filename, string[] ignored)
|
|
|
|
{
|
|
|
|
GivenFileCopy(filename);
|
2020-01-03 12:49:24 +00:00
|
|
|
var path = _copiedFile;
|
|
|
|
|
|
|
|
_testTags.Write(path);
|
|
|
|
|
|
|
|
_testTags.Date = null;
|
|
|
|
_testTags.OriginalReleaseDate = null;
|
|
|
|
|
|
|
|
_testTags.Write(path);
|
|
|
|
|
2019-03-27 22:08:14 +00:00
|
|
|
var onDisk = Subject.ReadAudioTag(path);
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-27 22:08:14 +00:00
|
|
|
onDisk.Date.HasValue.Should().BeFalse();
|
|
|
|
onDisk.OriginalReleaseDate.HasValue.Should().BeFalse();
|
|
|
|
}
|
2019-03-27 22:31:15 +00:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void should_ignore_non_parsable_id3v23_date()
|
|
|
|
{
|
2024-02-12 20:11:25 +00:00
|
|
|
GivenFileCopy("nin.mp2");
|
2019-03-27 22:31:15 +00:00
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
using (var file = TagLib.File.Create(_copiedFile))
|
2019-03-27 22:31:15 +00:00
|
|
|
{
|
2020-01-03 12:49:24 +00:00
|
|
|
var id3tag = (TagLib.Id3v2.Tag)file.GetTag(TagLib.TagTypes.Id3v2);
|
2019-03-27 22:31:15 +00:00
|
|
|
id3tag.SetTextFrame("TORY", "0");
|
|
|
|
file.Save();
|
|
|
|
}
|
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
var tag = Subject.ReadAudioTag(_copiedFile);
|
2019-03-27 22:31:15 +00:00
|
|
|
tag.OriginalReleaseDate.HasValue.Should().BeFalse();
|
|
|
|
}
|
|
|
|
|
2019-09-04 20:57:11 +00:00
|
|
|
private TrackFile GivenPopulatedTrackfile(int mediumOffset)
|
2019-03-27 07:49:32 +00:00
|
|
|
{
|
|
|
|
var meta = Builder<ArtistMetadata>.CreateNew().Build();
|
|
|
|
var artist = Builder<Artist>.CreateNew()
|
|
|
|
.With(x => x.Metadata = meta)
|
|
|
|
.Build();
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-27 07:49:32 +00:00
|
|
|
var album = Builder<Album>.CreateNew()
|
|
|
|
.With(x => x.Artist = artist)
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
var media = Builder<Medium>.CreateListOfSize(2).Build() as List<Medium>;
|
2019-09-04 20:57:11 +00:00
|
|
|
media.ForEach(x => x.Number += mediumOffset);
|
|
|
|
|
2019-03-27 07:49:32 +00:00
|
|
|
var release = Builder<AlbumRelease>.CreateNew()
|
|
|
|
.With(x => x.Album = album)
|
|
|
|
.With(x => x.Media = media)
|
|
|
|
.With(x => x.Country = new List<string>())
|
|
|
|
.With(x => x.Label = new List<string>())
|
|
|
|
.Build();
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-27 07:49:32 +00:00
|
|
|
var tracks = Builder<Track>.CreateListOfSize(10)
|
|
|
|
.All()
|
|
|
|
.With(x => x.AlbumRelease = release)
|
|
|
|
.With(x => x.ArtistMetadata = meta)
|
|
|
|
.TheFirst(5)
|
2019-09-04 20:57:11 +00:00
|
|
|
.With(x => x.MediumNumber = 1 + mediumOffset)
|
2019-03-27 07:49:32 +00:00
|
|
|
.TheNext(5)
|
2019-09-04 20:57:11 +00:00
|
|
|
.With(x => x.MediumNumber = 2 + mediumOffset)
|
2019-03-27 07:49:32 +00:00
|
|
|
.Build() as List<Track>;
|
|
|
|
release.Tracks = tracks;
|
|
|
|
|
|
|
|
var file = Builder<TrackFile>.CreateNew()
|
|
|
|
.With(x => x.Tracks = new List<Track> { tracks[0] })
|
2019-07-19 12:41:17 +00:00
|
|
|
.With(x => x.Artist = artist)
|
2019-03-27 07:49:32 +00:00
|
|
|
.Build();
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void get_metadata_should_not_fail_with_missing_country()
|
|
|
|
{
|
2019-09-04 20:57:11 +00:00
|
|
|
var file = GivenPopulatedTrackfile(0);
|
2019-03-27 07:49:32 +00:00
|
|
|
var tag = Subject.GetTrackMetadata(file);
|
2020-01-03 12:49:24 +00:00
|
|
|
|
2019-03-27 07:49:32 +00:00
|
|
|
tag.MusicBrainzReleaseCountry.Should().BeNull();
|
|
|
|
}
|
2019-07-19 12:41:17 +00:00
|
|
|
|
2019-09-04 20:57:11 +00:00
|
|
|
[Test]
|
|
|
|
public void should_not_fail_if_media_has_been_omitted()
|
|
|
|
{
|
|
|
|
// make sure that we aren't relying on index of items in
|
|
|
|
// Media being the same as the medium number
|
|
|
|
var file = GivenPopulatedTrackfile(100);
|
|
|
|
var tag = Subject.GetTrackMetadata(file);
|
|
|
|
|
|
|
|
tag.Media.Should().NotBeNull();
|
|
|
|
}
|
|
|
|
|
2019-07-19 12:41:17 +00:00
|
|
|
[TestCase("nin.mp3")]
|
|
|
|
public void write_tags_should_update_trackfile_size_and_modified(string filename)
|
|
|
|
{
|
|
|
|
Mocker.GetMock<IConfigService>()
|
|
|
|
.Setup(x => x.ScrubAudioTags)
|
|
|
|
.Returns(true);
|
|
|
|
|
|
|
|
GivenFileCopy(filename);
|
|
|
|
|
2019-09-04 20:57:11 +00:00
|
|
|
var file = GivenPopulatedTrackfile(0);
|
2019-07-19 12:41:17 +00:00
|
|
|
|
2020-01-03 12:49:24 +00:00
|
|
|
file.Path = _copiedFile;
|
2019-07-19 12:41:17 +00:00
|
|
|
Subject.WriteTags(file, false, true);
|
|
|
|
|
|
|
|
var fileInfo = _diskProvider.GetFileInfo(file.Path);
|
|
|
|
file.Modified.Should().Be(fileInfo.LastWriteTimeUtc);
|
|
|
|
file.Size.Should().Be(fileInfo.Length);
|
2023-12-06 17:25:18 +00:00
|
|
|
|
|
|
|
Mocker.GetMock<IEventAggregator>()
|
|
|
|
.Verify(v => v.PublishEvent(It.IsAny<TrackFileRetaggedEvent>()), Times.Once());
|
|
|
|
}
|
|
|
|
|
|
|
|
[TestCase("nin.mp3")]
|
|
|
|
public void write_tags_should_not_update_tags_if_already_updated(string filename)
|
|
|
|
{
|
|
|
|
Mocker.GetMock<IConfigService>()
|
|
|
|
.Setup(x => x.ScrubAudioTags)
|
|
|
|
.Returns(true);
|
|
|
|
|
|
|
|
GivenFileCopy(filename);
|
|
|
|
|
|
|
|
var file = GivenPopulatedTrackfile(0);
|
|
|
|
|
|
|
|
file.Path = _copiedFile;
|
|
|
|
Subject.WriteTags(file, false, true);
|
|
|
|
Subject.WriteTags(file, false, true);
|
|
|
|
Subject.WriteTags(file, false, true);
|
|
|
|
|
|
|
|
Mocker.GetMock<IEventAggregator>()
|
|
|
|
.Verify(v => v.PublishEvent(It.IsAny<TrackFileRetaggedEvent>()), Times.Once());
|
2019-07-19 12:41:17 +00:00
|
|
|
}
|
2019-03-15 12:10:45 +00:00
|
|
|
}
|
|
|
|
}
|