2019-02-16 14:49:24 +00:00
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Collections;
|
|
|
|
using FluentAssertions;
|
|
|
|
using FluentValidation.Results;
|
|
|
|
using Moq;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using NUnit.Framework;
|
|
|
|
using NzbDrone.Core.Configuration;
|
|
|
|
using NzbDrone.Core.MediaFiles.TrackImport.Identification;
|
|
|
|
using NzbDrone.Core.Messaging.Commands;
|
|
|
|
using NzbDrone.Core.MetadataSource;
|
|
|
|
using NzbDrone.Core.MetadataSource.SkyHook;
|
|
|
|
using NzbDrone.Core.Music;
|
|
|
|
using NzbDrone.Core.Music.Commands;
|
|
|
|
using NzbDrone.Core.Parser.Model;
|
|
|
|
using NzbDrone.Core.Profiles.Metadata;
|
|
|
|
using NzbDrone.Core.Test.Framework;
|
|
|
|
using NzbDrone.Test.Common;
|
2019-02-20 01:16:09 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using NzbDrone.Common.Serializer;
|
|
|
|
using NzbDrone.Core.Parser;
|
|
|
|
using NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators;
|
|
|
|
using NzbDrone.Core.MediaFiles.TrackImport.Aggregation;
|
2019-02-16 14:49:24 +00:00
|
|
|
|
|
|
|
namespace NzbDrone.Core.Test.MediaFiles.TrackImport.Identification
|
|
|
|
{
|
|
|
|
[TestFixture]
|
|
|
|
public class IdentificationServiceFixture : DbTest
|
|
|
|
{
|
|
|
|
private ArtistService _artistService;
|
|
|
|
private AddArtistService _addArtistService;
|
|
|
|
private RefreshArtistService _refreshArtistService;
|
|
|
|
|
|
|
|
private IdentificationService Subject;
|
|
|
|
|
|
|
|
[SetUp]
|
|
|
|
public void SetUp()
|
|
|
|
{
|
|
|
|
UseRealHttp();
|
|
|
|
|
|
|
|
// Resolve all the parts we need
|
|
|
|
Mocker.SetConstant<IArtistRepository>(Mocker.Resolve<ArtistRepository>());
|
|
|
|
Mocker.SetConstant<IArtistMetadataRepository>(Mocker.Resolve<ArtistMetadataRepository>());
|
|
|
|
Mocker.SetConstant<IAlbumRepository>(Mocker.Resolve<AlbumRepository>());
|
|
|
|
Mocker.SetConstant<IReleaseRepository>(Mocker.Resolve<ReleaseRepository>());
|
|
|
|
Mocker.SetConstant<ITrackRepository>(Mocker.Resolve<TrackRepository>());
|
|
|
|
|
|
|
|
Mocker.GetMock<IMetadataProfileService>().Setup(x => x.Exists(It.IsAny<int>())).Returns(true);
|
|
|
|
|
|
|
|
_artistService = Mocker.Resolve<ArtistService>();
|
|
|
|
Mocker.SetConstant<IArtistService>(_artistService);
|
|
|
|
Mocker.SetConstant<IAlbumService>(Mocker.Resolve<AlbumService>());
|
|
|
|
Mocker.SetConstant<IReleaseService>(Mocker.Resolve<ReleaseService>());
|
|
|
|
Mocker.SetConstant<ITrackService>(Mocker.Resolve<TrackService>());
|
|
|
|
|
|
|
|
Mocker.SetConstant<IConfigService>(Mocker.Resolve<IConfigService>());
|
|
|
|
Mocker.SetConstant<IProvideArtistInfo>(Mocker.Resolve<SkyHookProxy>());
|
|
|
|
Mocker.SetConstant<IProvideAlbumInfo>(Mocker.Resolve<SkyHookProxy>());
|
|
|
|
|
|
|
|
_addArtistService = Mocker.Resolve<AddArtistService>();
|
|
|
|
|
|
|
|
Mocker.SetConstant<IRefreshTrackService>(Mocker.Resolve<RefreshTrackService>());
|
2019-07-09 20:14:05 +00:00
|
|
|
Mocker.SetConstant<IRefreshAlbumReleaseService>(Mocker.Resolve<RefreshAlbumReleaseService>());
|
|
|
|
Mocker.SetConstant<IRefreshAlbumService>(Mocker.Resolve<RefreshAlbumService>());
|
2019-02-16 14:49:24 +00:00
|
|
|
_refreshArtistService = Mocker.Resolve<RefreshArtistService>();
|
|
|
|
|
|
|
|
Mocker.GetMock<IAddArtistValidator>().Setup(x => x.Validate(It.IsAny<Artist>())).Returns(new ValidationResult());
|
|
|
|
|
|
|
|
Mocker.SetConstant<ITrackGroupingService>(Mocker.Resolve<TrackGroupingService>());
|
2019-02-20 01:16:09 +00:00
|
|
|
|
|
|
|
// set up the augmenters
|
|
|
|
List<IAggregate<LocalAlbumRelease>> aggregators = new List<IAggregate<LocalAlbumRelease>> {
|
|
|
|
Mocker.Resolve<AggregateFilenameInfo>()
|
|
|
|
};
|
|
|
|
Mocker.SetConstant<IEnumerable<IAggregate<LocalAlbumRelease>>>(aggregators);
|
|
|
|
Mocker.SetConstant<IAugmentingService>(Mocker.Resolve<AugmentingService>());
|
|
|
|
|
2019-02-16 14:49:24 +00:00
|
|
|
Subject = Mocker.Resolve<IdentificationService>();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GivenMetadataProfile(MetadataProfile profile)
|
|
|
|
{
|
2019-02-20 01:16:09 +00:00
|
|
|
Mocker.GetMock<IMetadataProfileService>().Setup(x => x.Get(profile.Id)).Returns(profile);
|
|
|
|
}
|
|
|
|
|
|
|
|
private List<Artist> GivenArtists(List<ArtistTestCase> artists)
|
|
|
|
{
|
|
|
|
var outp = new List<Artist>();
|
|
|
|
for (int i = 0; i < artists.Count; i++)
|
|
|
|
{
|
|
|
|
var meta = artists[i].MetadataProfile;
|
|
|
|
meta.Id = i + 1;
|
|
|
|
GivenMetadataProfile(meta);
|
|
|
|
outp.Add(GivenArtist(artists[i].Artist, meta.Id));
|
|
|
|
}
|
|
|
|
|
|
|
|
return outp;
|
2019-02-16 14:49:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-20 01:16:09 +00:00
|
|
|
private Artist GivenArtist(string foreignArtistId, int metadataProfileId)
|
2019-02-16 14:49:24 +00:00
|
|
|
{
|
|
|
|
var artist = _addArtistService.AddArtist(new Artist {
|
|
|
|
Metadata = new ArtistMetadata {
|
|
|
|
ForeignArtistId = foreignArtistId
|
|
|
|
},
|
|
|
|
Path = @"c:\test".AsOsAgnostic(),
|
2019-02-20 01:16:09 +00:00
|
|
|
MetadataProfileId = metadataProfileId
|
2019-02-16 14:49:24 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
var command = new RefreshArtistCommand{
|
|
|
|
ArtistId = artist.Id,
|
|
|
|
Trigger = CommandTrigger.Unspecified
|
|
|
|
};
|
|
|
|
|
|
|
|
_refreshArtistService.Execute(command);
|
|
|
|
|
|
|
|
return _artistService.FindById(foreignArtistId);
|
|
|
|
}
|
|
|
|
|
2019-02-20 01:16:09 +00:00
|
|
|
private void GivenFingerprints(List<AcoustIdTestCase> fingerprints)
|
|
|
|
{
|
|
|
|
Mocker.GetMock<IConfigService>().Setup(x => x.AllowFingerprinting).Returns(AllowFingerprinting.AllFiles);
|
|
|
|
Mocker.GetMock<IFingerprintingService>().Setup(x => x.IsSetup()).Returns(true);
|
|
|
|
|
|
|
|
Mocker.GetMock<IFingerprintingService>()
|
|
|
|
.Setup(x => x.Lookup(It.IsAny<List<LocalTrack>>(), It.IsAny<double>()))
|
|
|
|
.Callback((List<LocalTrack> track, double thres) => {
|
|
|
|
track.ForEach(x => x.AcoustIdResults = fingerprints.SingleOrDefault(f => f.Path == x.Path).AcoustIdResults);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-02-16 14:49:24 +00:00
|
|
|
public static class IdTestCaseFactory
|
|
|
|
{
|
|
|
|
// for some reason using Directory.GetFiles causes nUnit to error
|
|
|
|
private static string[] files = {
|
|
|
|
"FilesWithMBIds.json",
|
|
|
|
"PreferMissingToBadMatch.json",
|
|
|
|
"InconsistentTyposInAlbum.json",
|
|
|
|
"SucceedWhenManyAlbumsHaveSameTitle.json",
|
2019-02-20 01:16:09 +00:00
|
|
|
"PenalizeUnknownMedia.json",
|
|
|
|
"CorruptFile.json",
|
|
|
|
"FilesWithoutTags.json"
|
2019-02-16 14:49:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
public static IEnumerable TestCases
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
foreach (var file in files)
|
|
|
|
{
|
|
|
|
yield return new TestCaseData(file).SetName($"should_match_tracks_{file.Replace(".json", "")}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// these are slow to run so only do so manually
|
|
|
|
[Explicit]
|
|
|
|
[Test, TestCaseSource(typeof(IdTestCaseFactory), "TestCases")]
|
|
|
|
public void should_match_tracks(string file)
|
|
|
|
{
|
|
|
|
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Identification", file);
|
|
|
|
var testcase = JsonConvert.DeserializeObject<IdTestCase>(File.ReadAllText(path));
|
|
|
|
|
2019-02-20 01:16:09 +00:00
|
|
|
var artists = GivenArtists(testcase.LibraryArtists);
|
|
|
|
var specifiedArtist = artists.SingleOrDefault(x => x.Metadata.Value.ForeignArtistId == testcase.Artist);
|
2019-02-16 14:49:24 +00:00
|
|
|
|
|
|
|
var tracks = testcase.Tracks.Select(x => new LocalTrack {
|
|
|
|
Path = x.Path.AsOsAgnostic(),
|
|
|
|
FileTrackInfo = x.FileTrackInfo
|
|
|
|
}).ToList();
|
|
|
|
|
2019-02-20 01:16:09 +00:00
|
|
|
if (testcase.Fingerprints != null)
|
|
|
|
{
|
|
|
|
GivenFingerprints(testcase.Fingerprints);
|
|
|
|
}
|
|
|
|
|
2019-04-04 08:20:47 +00:00
|
|
|
var result = Subject.Identify(tracks, specifiedArtist, null, null, testcase.NewDownload, testcase.SingleRelease, false);
|
2019-02-20 01:16:09 +00:00
|
|
|
|
|
|
|
TestLogger.Debug($"Found releases:\n{result.Where(x => x.AlbumRelease != null).Select(x => x.AlbumRelease?.ForeignReleaseId).ToJson()}");
|
2019-02-16 14:49:24 +00:00
|
|
|
|
|
|
|
result.Should().HaveCount(testcase.ExpectedMusicBrainzReleaseIds.Count);
|
2019-02-20 01:16:09 +00:00
|
|
|
result.Where(x => x.AlbumRelease != null).Select(x => x.AlbumRelease.ForeignReleaseId).ShouldBeEquivalentTo(testcase.ExpectedMusicBrainzReleaseIds);
|
2019-02-16 14:49:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|