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; 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; 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(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.GetMock().Setup(x => x.Exists(It.IsAny())).Returns(true); _artistService = Mocker.Resolve(); Mocker.SetConstant(_artistService); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); _addArtistService = Mocker.Resolve(); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); Mocker.SetConstant(Mocker.Resolve()); _refreshArtistService = Mocker.Resolve(); Mocker.GetMock().Setup(x => x.Validate(It.IsAny())).Returns(new ValidationResult()); Mocker.SetConstant(Mocker.Resolve()); // set up the augmenters List> aggregators = new List> { Mocker.Resolve() }; Mocker.SetConstant>>(aggregators); Mocker.SetConstant(Mocker.Resolve()); Subject = Mocker.Resolve(); } private void GivenMetadataProfile(MetadataProfile profile) { Mocker.GetMock().Setup(x => x.Get(profile.Id)).Returns(profile); } private List GivenArtists(List artists) { var outp = new List(); 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; } private Artist GivenArtist(string foreignArtistId, int metadataProfileId) { var artist = _addArtistService.AddArtist(new Artist { Metadata = new ArtistMetadata { ForeignArtistId = foreignArtistId }, Path = @"c:\test".AsOsAgnostic(), MetadataProfileId = metadataProfileId }); var command = new RefreshArtistCommand{ ArtistId = artist.Id, Trigger = CommandTrigger.Unspecified }; _refreshArtistService.Execute(command); return _artistService.FindById(foreignArtistId); } private void GivenFingerprints(List fingerprints) { Mocker.GetMock().Setup(x => x.AllowFingerprinting).Returns(AllowFingerprinting.AllFiles); Mocker.GetMock().Setup(x => x.IsSetup()).Returns(true); Mocker.GetMock() .Setup(x => x.Lookup(It.IsAny>(), It.IsAny())) .Callback((List track, double thres) => { track.ForEach(x => x.AcoustIdResults = fingerprints.SingleOrDefault(f => f.Path == x.Path).AcoustIdResults); }); } 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", "PenalizeUnknownMedia.json", "CorruptFile.json", "FilesWithoutTags.json" }; 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(File.ReadAllText(path)); var artists = GivenArtists(testcase.LibraryArtists); var specifiedArtist = artists.SingleOrDefault(x => x.Metadata.Value.ForeignArtistId == testcase.Artist); var tracks = testcase.Tracks.Select(x => new LocalTrack { Path = x.Path.AsOsAgnostic(), FileTrackInfo = x.FileTrackInfo }).ToList(); if (testcase.Fingerprints != null) { GivenFingerprints(testcase.Fingerprints); } var result = Subject.Identify(tracks, specifiedArtist, null, null, testcase.NewDownload, testcase.SingleRelease, false); TestLogger.Debug($"Found releases:\n{result.Where(x => x.AlbumRelease != null).Select(x => x.AlbumRelease?.ForeignReleaseId).ToJson()}"); result.Should().HaveCount(testcase.ExpectedMusicBrainzReleaseIds.Count); result.Where(x => x.AlbumRelease != null).Select(x => x.AlbumRelease.ForeignReleaseId).Should().BeEquivalentTo(testcase.ExpectedMusicBrainzReleaseIds); } } }