diff --git a/NzbDrone.Core.Test/DiskScanProviderTest.cs b/NzbDrone.Core.Test/DiskScanProviderTest.cs new file mode 100644 index 000000000..944399e47 --- /dev/null +++ b/NzbDrone.Core.Test/DiskScanProviderTest.cs @@ -0,0 +1,387 @@ +using System; +using System.Collections.Generic; +using AutoMoq; +using FizzWare.NBuilder; +using FluentAssertions; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Core; +using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; +using NzbDrone.Core.Test.Framework; +using PetaPoco; + +namespace NzbDrone.Core.Test +{ + // ReSharper disable InconsistentNaming + public class DiskScanProviderTest : TestBase + { + [Test] + public void import_new_file() + { + //Arrange + ///////////////////////////////////////// + + //Constants + const string fileName = @"WEEDS.S03E01.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; + const int seasonNumber = 3; + const int episodeNumner = 1; + const int size = 12345; + + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + var fakeEpisode = Builder.CreateNew() + .With(c => c.SeriesId = fakeSeries.SeriesId) + .With(c => c.SeasonNumber = seasonNumber) + .Build(); + + //Mocks + var mocker = new AutoMoqer(); + + mocker.GetMock() + .Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable(); + + var database = mocker.GetMock(MockBehavior.Strict); + database.Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); + database.Setup(r => r.Insert(It.IsAny())).Returns(1).Verifiable(); + + + mocker.GetMock() + .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + Assert.IsNotNull(result); + mocker.GetMock().Verify(r => r.Insert(result), Times.Once()); + mocker.VerifyAllMocks(); + + result.SeasonNumber.Should().Be(fakeEpisode.SeasonNumber); + + Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId); + Assert.AreEqual(QualityTypes.DVD, result.Quality); + Assert.AreEqual(Parser.NormalizePath(fileName), result.Path); + Assert.AreEqual(size, result.Size); + Assert.AreEqual(false, result.Proper); + Assert.AreNotEqual(new DateTime(), result.DateAdded); + } + + [TestCase(QualityTypes.SDTV, true)] + [TestCase(QualityTypes.HDTV, true)] + public void import_new_file_with_better_quality(QualityTypes currentFileQuality, bool currentFileProper) + { + const string fileName = @"WEEDS.S03E01.DUAL.1080p.-HELLYWOOD.mkv"; + const int seasonNumber = 3; + const int episodeNumner = 1; + const int size = 12345; + + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + var fakeEpisode = Builder.CreateNew() + .With(c => c.SeriesId = fakeSeries.SeriesId) + .With(c => c.SeasonNumber = seasonNumber) + .With(e => e.EpisodeFile = Builder.CreateNew() + .With(g => g.Quality = (QualityTypes)currentFileQuality) + .And(g => g.Proper = currentFileProper).Build() + ) + .Build(); + + //Mocks + var mocker = new AutoMoqer(); + + mocker.GetMock() + .Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable(); + + var database = mocker.GetMock(MockBehavior.Strict); + database.Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); + database.Setup(r => r.Insert(It.IsAny())).Returns(1).Verifiable(); + + + mocker.GetMock() + .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + Assert.IsNotNull(result); + mocker.GetMock().Verify(r => r.Insert(result), Times.Once()); + mocker.VerifyAllMocks(); + + result.SeasonNumber.Should().Be(fakeEpisode.SeasonNumber); + + Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId); + Assert.AreEqual(QualityTypes.SDTV, result.Quality); + Assert.AreEqual(Parser.NormalizePath(fileName), result.Path); + Assert.AreEqual(size, result.Size); + Assert.AreEqual(false, result.Proper); + Assert.AreNotEqual(new DateTime(), result.DateAdded); + } + + + [TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")] + [TestCase("WEEDS.S03E01.DUAL.SDTV.XviD.AC3.-HELLYWOOD.avi")] + public void import_new_file_skip_if_episode_has_same_or_better_quality(string fileName) + { + const int seasonNumber = 3; + const int episodeNumner = 1; + + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + var fakeEpisode = Builder.CreateNew() + .With(c => c.SeriesId = fakeSeries.SeriesId) + .With(c => c.SeasonNumber = seasonNumber) + .With(c => c.EpisodeFile = Builder.CreateNew() + .With(e => e.Quality = QualityTypes.Bluray720p).Build() + ) + .Build(); + + //Mocks + var mocker = new AutoMoqer(); + + mocker.GetMock() + .Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable(); + + var database = mocker.GetMock(MockBehavior.Strict); + database.Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); + + mocker.GetMock() + .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + result.Should().BeNull(); + mocker.GetMock().Verify(r => r.Insert(result), Times.Never()); + mocker.VerifyAllMocks(); + } + + + [Test] + public void import_new_daily_file() + { + //Arrange + ///////////////////////////////////////// + + //Constants + const string fileName = @"2011.01.10 - Denis Leary - HD TV.mkv"; + var airDate = new DateTime(2011, 01, 10); + const int size = 12345; + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + var fakeEpisode = Builder.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build(); + + //Mocks + var mocker = new AutoMoqer(); + + var database = mocker.GetMock(MockBehavior.Strict); + database.Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); + database.Setup(r => r.Insert(It.IsAny())).Returns(1).Verifiable(); + + mocker.GetMock() + .Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode). + Verifiable(); + + mocker.GetMock() + .Setup(e => e.GetSize(fileName)).Returns(size).Verifiable(); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + Assert.IsNotNull(result); + mocker.GetMock().VerifyAll(); + mocker.GetMock().Verify(r => r.Insert(result), Times.Once()); + mocker.GetMock().VerifyAll(); + mocker.GetMock().VerifyAll(); + + //Currently can't verify this since the list of episodes are loaded + //Dynamically by SubSonic + //Assert.AreEqual(fakeEpisode, result.EpisodeNumbers[0]); + + Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId); + Assert.AreEqual(QualityTypes.HDTV, result.Quality); + Assert.AreEqual(Parser.NormalizePath(fileName), result.Path); + Assert.AreEqual(size, result.Size); + Assert.AreEqual(false, result.Proper); + Assert.AreNotEqual(new DateTime(), result.DateAdded); + } + + [Test] + public void import_existing_season_file_should_skip() + { + //Arrange + ///////////////////////////////////////// + + //Constants + const string fileName = @"WEEDS.S03E01.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; + + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + + //Mocks + var mocker = new AutoMoqer(); + + mocker.GetMock(MockBehavior.Strict) + .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(true).Verifiable(); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + mocker.VerifyAllMocks(); + result.Should().BeNull(); + } + + [Test] + public void import_unparsable_file() + { + //Arrange + ///////////////////////////////////////// + + //Constants + const string fileName = @"WEEDS.avi"; + const int size = 12345; + + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + + //Mocks + var mocker = new AutoMoqer(); + + mocker.GetMock(MockBehavior.Strict) + .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); + + mocker.GetMock() + .Setup(e => e.GetSize(fileName)).Returns(size).Verifiable(); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + mocker.VerifyAllMocks(); + Assert.IsNull(result); + ExceptionVerification.ExcpectedWarns(1); + } + + [Test] + public void import_sample_file() + { + //Arrange + ///////////////////////////////////////// + + //Constants + const string fileName = @"2011.01.10 - Denis Leary - sample - HD TV.mkv"; + var airDate = new DateTime(2011, 01, 10); + const int size = 12345; + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + var fakeEpisode = Builder.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build(); + + //Mocks + var mocker = new AutoMoqer(); + + mocker.GetMock() + .Setup(r => r.Exists(It.IsAny())).Returns(false).Verifiable(); + mocker.GetMock() + .Setup(r => r.Insert(It.IsAny())).Returns(0).Verifiable(); + + mocker.GetMock() + .Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode). + Verifiable(); + + mocker.GetMock() + .Setup(e => e.GetSize(fileName)).Returns(size).Verifiable(); + + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + Assert.IsNull(result); + } + + [Test] + public void import_existing_file() + { + const string fileName = "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; + + var fakeSeries = Builder.CreateNew().Build(); + + var mocker = new AutoMoqer(); + mocker.GetMock(MockBehavior.Strict) + .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(true).Verifiable(); + + mocker.GetMock(MockBehavior.Strict); + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + result.Should().BeNull(); + mocker.GetMock().Verify(r => r.Insert(result), Times.Never()); + mocker.VerifyAllMocks(); + } + + [Test] + public void import_file_with_no_episode_in_db_should_return_null() + { + + //Constants + const string fileName = "WEEDS.S03E01.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; + const int seasonNumber = 3; + const int episodeNumner = 01; + + //Fakes + var fakeSeries = Builder.CreateNew().Build(); + + //Mocks + var mocker = new AutoMoqer(); + mocker.GetMock(MockBehavior.Strict) + .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); + + mocker.GetMock(MockBehavior.Strict) + .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(null). + Verifiable(); + + mocker.GetMock(MockBehavior.Strict) + .Setup(e => e.GetSize(fileName)).Returns(90000000000); + + + //Act + var result = mocker.Resolve().ImportFile(fakeSeries, fileName); + + //Assert + mocker.VerifyAllMocks(); + result.Should().BeNull(); + mocker.GetMock().Verify(r => r.Insert(result), Times.Never()); + ExceptionVerification.ExcpectedWarns(1); + } + + [Test] + public void scan_series_should_update_last_scan_date() + { + + var mocker = new AutoMoqer(); + mocker.GetMock() + .Setup(c => c.UpdateSeries(It.Is(s => s.LastDiskSync != null))).Verifiable(); + + mocker.GetMock() + .Setup(c => c.GetEpisodeBySeries(It.IsAny())) + .Returns(new List { new Episode() }); + + + mocker.GetMock() + .Setup(c => c.GetSeriesFiles(It.IsAny())) + .Returns(new List()); + + mocker.Resolve().Scan(new Series()); + + mocker.VerifyAllMocks(); + + } + } +} diff --git a/NzbDrone.Core.Test/EpisodeProviderTest.cs b/NzbDrone.Core.Test/EpisodeProviderTest.cs index 16e1c9658..02c40742c 100644 --- a/NzbDrone.Core.Test/EpisodeProviderTest.cs +++ b/NzbDrone.Core.Test/EpisodeProviderTest.cs @@ -8,7 +8,9 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Providers; +using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; +using NzbDrone.Core.Repository.Quality; using NzbDrone.Core.Test.Framework; using PetaPoco; using TvdbLib.Data; @@ -81,7 +83,7 @@ namespace NzbDrone.Core.Test var db = MockLib.GetEmptyDatabase(); mocker.SetConstant(db); - + //Act var episode = mocker.Resolve().GetEpisode(1, 1, 1); @@ -101,7 +103,7 @@ namespace NzbDrone.Core.Test var fakeFile = Builder.CreateNew().With(f => f.EpisodeFileId).Build(); var fakeEpisodes = Builder.CreateListOfSize(5) .WhereAll().Have(e => e.SeriesId = 1).WhereTheFirst(1).Have(e => e.EpisodeFileId = 1).Have(e => e.EpisodeFile = fakeFile).Build(); - + db.InsertMany(fakeEpisodes); db.Insert(fakeFile); @@ -562,13 +564,21 @@ namespace NzbDrone.Core.Test public void Add_daily_show_episodes() { var mocker = new AutoMoqer(); - mocker.SetConstant(MockLib.GetEmptyDatabase()); + var db = MockLib.GetEmptyDatabase(); + mocker.SetConstant(db); mocker.Resolve(); + + mocker.GetMock() + .Setup(e => e.DefaultQualityProfile).Returns(1); + + db.Insert(Builder.CreateNew().Build()); + + const int tvDbSeriesId = 71256; //act var seriesProvider = mocker.Resolve(); - seriesProvider.AddSeries("c:\\test\\", tvDbSeriesId, 0); + seriesProvider.AddSeries("c:\\test\\", tvDbSeriesId, 1); var episodeProvider = mocker.Resolve(); episodeProvider.RefreshEpisodeInfo(seriesProvider.GetSeries(tvDbSeriesId)); @@ -606,6 +616,8 @@ namespace NzbDrone.Core.Test episode.EpisodeFile.Should().NotBeNull(); } + + [Test] public void GetEpisode_by_Season_Episode_without_EpisodeFile() { diff --git a/NzbDrone.Core.Test/MediaFileProviderTests.cs b/NzbDrone.Core.Test/MediaFileProviderTests.cs index 95877762b..999359d97 100644 --- a/NzbDrone.Core.Test/MediaFileProviderTests.cs +++ b/NzbDrone.Core.Test/MediaFileProviderTests.cs @@ -25,282 +25,7 @@ namespace NzbDrone.Core.Test // ReSharper disable InconsistentNaming public class MediaFileProviderTests : TestBase { - [Test] - [Description("Verifies that a new file imported properly")] - public void import_new_file() - { - //Arrange - ///////////////////////////////////////// - //Constants - const string fileName = @"WEEDS.S03E01.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; - const int seasonNumber = 3; - const int episodeNumner = 1; - const int size = 12345; - - //Fakes - var fakeSeries = Builder.CreateNew().Build(); - var fakeEpisode = Builder.CreateNew() - .With(c => c.SeriesId = fakeSeries.SeriesId) - .With(c => c.SeasonNumber = seasonNumber) - .Build(); - - //Mocks - var mocker = new AutoMoqer(); - - mocker.GetMock() - .Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable(); - - var database = mocker.GetMock(MockBehavior.Strict); - database.Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); - database.Setup(r => r.Insert(It.IsAny())).Returns(1).Verifiable(); - - - mocker.GetMock() - .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode); - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - Assert.IsNotNull(result); - mocker.GetMock().Verify(r => r.Insert(result), Times.Once()); - mocker.VerifyAllMocks(); - - result.SeasonNumber.Should().Be(fakeEpisode.SeasonNumber); - - Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId); - Assert.AreEqual(QualityTypes.DVD, result.Quality); - Assert.AreEqual(Parser.NormalizePath(fileName), result.Path); - Assert.AreEqual(size, result.Size); - Assert.AreEqual(false, result.Proper); - Assert.AreNotEqual(new DateTime(), result.DateAdded); - } - - [Test] - [Description("Verifies that a new file imported properly")] - public void import_new_daily_file() - { - //Arrange - ///////////////////////////////////////// - - //Constants - const string fileName = @"2011.01.10 - Denis Leary - HD TV.mkv"; - var airDate = new DateTime(2011, 01, 10); - const int size = 12345; - //Fakes - var fakeSeries = Builder.CreateNew().Build(); - var fakeEpisode = Builder.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build(); - - //Mocks - var mocker = new AutoMoqer(); - - var database = mocker.GetMock(MockBehavior.Strict); - database.Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); - database.Setup(r => r.Insert(It.IsAny())).Returns(1).Verifiable(); - - mocker.GetMock() - .Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode). - Verifiable(); - - mocker.GetMock() - .Setup(e => e.GetSize(fileName)).Returns(size).Verifiable(); - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - Assert.IsNotNull(result); - mocker.GetMock().VerifyAll(); - mocker.GetMock().Verify(r => r.Insert(result), Times.Once()); - mocker.GetMock().VerifyAll(); - mocker.GetMock().VerifyAll(); - - //Currently can't verify this since the list of episodes are loaded - //Dynamically by SubSonic - //Assert.AreEqual(fakeEpisode, result.EpisodeNumbers[0]); - - Assert.AreEqual(fakeEpisode.SeriesId, result.SeriesId); - Assert.AreEqual(QualityTypes.HDTV, result.Quality); - Assert.AreEqual(Parser.NormalizePath(fileName), result.Path); - Assert.AreEqual(size, result.Size); - Assert.AreEqual(false, result.Proper); - Assert.AreNotEqual(new DateTime(), result.DateAdded); - } - - [Test] - public void import_existing_season_file_should_skip() - { - //Arrange - ///////////////////////////////////////// - - //Constants - const string fileName = @"WEEDS.S03E01.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; - - //Fakes - var fakeSeries = Builder.CreateNew().Build(); - - //Mocks - var mocker = new AutoMoqer(); - - mocker.GetMock(MockBehavior.Strict) - .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(true).Verifiable(); - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - mocker.VerifyAllMocks(); - result.Should().BeNull(); - } - - [Test] - [Description("Verifies that a un-parsable file isn't imported")] - public void import_unparsable_file() - { - //Arrange - ///////////////////////////////////////// - - //Constants - const string fileName = @"WEEDS.avi"; - const int size = 12345; - - //Fakes - var fakeSeries = Builder.CreateNew().Build(); - - //Mocks - var mocker = new AutoMoqer(); - - mocker.GetMock(MockBehavior.Strict) - .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); - - mocker.GetMock() - .Setup(e => e.GetSize(fileName)).Returns(size).Verifiable(); - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - mocker.VerifyAllMocks(); - Assert.IsNull(result); - ExceptionVerification.ExcpectedWarns(1); - } - - [Test] - [Description("Verifies that a new file imported properly")] - public void import_sample_file() - { - //Arrange - ///////////////////////////////////////// - - //Constants - const string fileName = @"2011.01.10 - Denis Leary - sample - HD TV.mkv"; - var airDate = new DateTime(2011, 01, 10); - const int size = 12345; - //Fakes - var fakeSeries = Builder.CreateNew().Build(); - var fakeEpisode = Builder.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build(); - - //Mocks - var mocker = new AutoMoqer(); - - mocker.GetMock() - .Setup(r => r.Exists(It.IsAny())).Returns(false).Verifiable(); - mocker.GetMock() - .Setup(r => r.Insert(It.IsAny())).Returns(0).Verifiable(); - - mocker.GetMock() - .Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode). - Verifiable(); - - mocker.GetMock() - .Setup(e => e.GetSize(fileName)).Returns(size).Verifiable(); - - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - Assert.IsNull(result); - } - - [Test] - public void import_existing_file() - { - const string fileName = "WEEDS.S03E01-06.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; - - var fakeSeries = Builder.CreateNew().Build(); - - var mocker = new AutoMoqer(); - mocker.GetMock(MockBehavior.Strict) - .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(true).Verifiable(); - - mocker.GetMock(MockBehavior.Strict); - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - result.Should().BeNull(); - mocker.GetMock().Verify(r => r.Insert(result), Times.Never()); - mocker.VerifyAllMocks(); - } - - [Test] - [Description("Verifies that a file with no episode is skipped")] - public void import_file_with_no_episode() - { - //Arrange - ///////////////////////////////////////// - - //Constants - const string fileName = "WEEDS.S03E01.DUAL.BDRip.XviD.AC3.-HELLYWOOD.avi"; - const int seasonNumber = 3; - const int episodeNumner = 01; - - //Fakes - var fakeSeries = Builder.CreateNew().Build(); - - //Mocks - var mocker = new AutoMoqer(); - mocker.GetMock(MockBehavior.Strict) - .Setup(r => r.Exists(It.IsAny(), It.IsAny())).Returns(false).Verifiable(); - - mocker.GetMock(MockBehavior.Strict) - .Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(null). - Verifiable(); - - mocker.GetMock(MockBehavior.Strict) - .Setup(e => e.GetSize(fileName)).Returns(90000000000); - - - //Act - var result = mocker.Resolve().ImportFile(fakeSeries, fileName); - - //Assert - mocker.VerifyAllMocks(); - result.Should().BeNull(); - mocker.GetMock().Verify(r => r.Insert(result), Times.Never()); - ExceptionVerification.ExcpectedWarns(1); - } - - [Test] - public void scan_series_should_update_last_scan_date() - { - - var mocker = new AutoMoqer(); - mocker.GetMock() - .Setup(c => c.UpdateSeries(It.Is(s => s.LastDiskSync != null))).Verifiable(); - - mocker.GetMock() - .Setup(c => c.GetEpisodeBySeries(It.IsAny())) - .Returns(new List { new Episode() }); - - mocker.Resolve().Scan(new Series()); - - mocker.VerifyAllMocks(); - - } [Test] @@ -334,10 +59,17 @@ namespace NzbDrone.Core.Test public void Scan_series_should_skip_series_with_no_episodes() { var mocker = new AutoMoqer(MockBehavior.Strict); + mocker.GetMock() .Setup(c => c.GetEpisodeBySeries(12)) .Returns(new List()); + mocker.GetMock() + .Setup(e => e.RepairLinks()).Returns(0); + mocker.GetMock() + .Setup(e => e.DeleteOrphaned()).Returns(0); + + var series = Builder.CreateNew() .With(s => s.SeriesId = 12).Build(); @@ -372,12 +104,14 @@ namespace NzbDrone.Core.Test database.InsertMany(episodes); //Act - mocker.Resolve().CleanEpisodesWithNonExistantFiles(); + var removedLinks = mocker.Resolve().RepairLinks(); var result = database.Fetch(); //Assert result.Should().HaveSameCount(episodes); result.Should().OnlyContain(e => e.EpisodeFileId == 0); + removedLinks.Should().Be(10); + ExceptionVerification.ExcpectedWarns(1); } [Test] @@ -394,12 +128,13 @@ namespace NzbDrone.Core.Test database.InsertMany(episodeFiles); //Act - mocker.Resolve().DeleteOrphanedEpisodeFiles(); + mocker.Resolve().DeleteOrphaned(); var result = database.Fetch(); //Assert result.Should().HaveCount(5); result.Should().OnlyContain(e => e.EpisodeFileId > 0); + ExceptionVerification.ExcpectedWarns(1); } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index ff97e5004..ed54b6fe2 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -76,6 +76,7 @@ ..\Libraries\System.Data.SQLite.dll False + @@ -84,6 +85,7 @@ + diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 785b24271..648df1730 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -147,6 +147,7 @@ False ..\Libraries\System.Data.SQLite.dll + diff --git a/NzbDrone.Core/Providers/Core/DiskProvider.cs b/NzbDrone.Core/Providers/Core/DiskProvider.cs index bb3c191dd..a8574c5cb 100644 --- a/NzbDrone.Core/Providers/Core/DiskProvider.cs +++ b/NzbDrone.Core/Providers/Core/DiskProvider.cs @@ -48,11 +48,6 @@ namespace NzbDrone.Core.Providers.Core File.Move(sourcePath, destinationPath); } - public virtual string GetExtension(string path) - { - return Path.GetExtension(path); - } - public virtual void DeleteFolder(string path, bool recursive) { Directory.Delete(path, recursive); diff --git a/NzbDrone.Core/Providers/DiskScanProvider.cs b/NzbDrone.Core/Providers/DiskScanProvider.cs index 4db01ffd9..7783c376b 100644 --- a/NzbDrone.Core/Providers/DiskScanProvider.cs +++ b/NzbDrone.Core/Providers/DiskScanProvider.cs @@ -13,7 +13,7 @@ namespace NzbDrone.Core.Providers public class DiskScanProvider { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - private static readonly string[] MediaExtentions = new[] {".mkv", ".avi", ".wmv", ".mp4"}; + private static readonly string[] MediaExtentions = new[] { ".mkv", ".avi", ".wmv", ".mp4" }; private readonly IDatabase _database; private readonly DiskProvider _diskProvider; private readonly EpisodeProvider _episodeProvider; @@ -53,26 +53,32 @@ namespace NzbDrone.Core.Providers /// Path to scan public virtual List Scan(Series series, string path) { + _mediaFileProvider.DeleteOrphaned(); + _mediaFileProvider.RepairLinks(); + if (_episodeProvider.GetEpisodeBySeries(series.SeriesId).Count == 0) { Logger.Debug("Series {0} has no episodes. skipping", series.Title); return new List(); } + var seriesFile = _mediaFileProvider.GetSeriesFiles(series.SeriesId); + CleanUp(seriesFile); + var mediaFileList = GetVideoFiles(path); - var fileList = new List(); + var importedFiles = new List(); foreach (var filePath in mediaFileList) { var file = ImportFile(series, filePath); if (file != null) - fileList.Add(file); + importedFiles.Add(file); } series.LastDiskSync = DateTime.Now; _seriesProvider.UpdateSeries(series); - return fileList; + return importedFiles; } @@ -88,7 +94,7 @@ namespace NzbDrone.Core.Providers long size = _diskProvider.GetSize(filePath); - //If Size is less than 50MB and contains sample. Check for Size to ensure its not an episode with sample in the title + //If Size is less than 40MB and contains sample. Check for Size to ensure its not an episode with sample in the title if (size < 40000000 && filePath.ToLower().Contains("sample")) { Logger.Trace("[{0}] appears to be a sample. skipping.", filePath); @@ -141,6 +147,13 @@ namespace NzbDrone.Core.Providers if (episodes.Count <= 0) return null; + + if (episodes.Any(e => e.EpisodeFile != null && e.EpisodeFile.QualityWrapper > parseResult.Quality)) + { + Logger.Info("File with better quality is already attached. skipping {0}", filePath); + return null; + } + var episodeFile = new EpisodeFile(); episodeFile.DateAdded = DateTime.Now; episodeFile.SeriesId = series.SeriesId; @@ -172,20 +185,18 @@ namespace NzbDrone.Core.Providers throw new ArgumentNullException("episodeFile"); var series = _seriesProvider.GetSeries(episodeFile.SeriesId); - string ext = _diskProvider.GetExtension(episodeFile.Path); var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId); string newFileName = _mediaFileProvider.GetNewFilename(episodes, series.Title, episodeFile.Quality); - - var newFile = _mediaFileProvider.CalculateFilePath(series, episodes.First().SeasonNumber, newFileName, ext); + var newFile = _mediaFileProvider.CalculateFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); //Do the rename + Logger.Trace("Attempting to rename {0} to {1}", episodeFile.Path, newFile.FullName); _diskProvider.RenameFile(episodeFile.Path, newFile.FullName); //Update the filename in the DB episodeFile.Path = newFile.FullName; _mediaFileProvider.Update(episodeFile); - return true; } @@ -194,11 +205,8 @@ namespace NzbDrone.Core.Providers /// Removes files that no longer exist on disk from the database /// /// list of files to verify - public virtual void CleanUp(List files) + public virtual void CleanUp(IList files) { - _mediaFileProvider.CleanEpisodesWithNonExistantFiles(); - _mediaFileProvider.DeleteOrphanedEpisodeFiles(); - foreach (var episodeFile in files) { if (!_diskProvider.FileExists(episodeFile.Path)) diff --git a/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs b/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs index 599dad96b..e48119aa0 100644 --- a/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs +++ b/NzbDrone.Core/Providers/Jobs/PostDownloadScanJob.cs @@ -44,9 +44,9 @@ namespace NzbDrone.Core.Providers.Jobs Logger.Debug("Starting New Download Scan Job"); var dropFolder = _configProvider.SabDropDirectory; - if (String.IsNullOrEmpty(dropFolder)) + if (String.IsNullOrWhiteSpace(dropFolder)) { - Logger.Warn("Unable to Scan for New Downloads - Folder Name is Empty"); + Logger.Debug("Skipping drop folder scan. No drop folder is defined."); return; } @@ -56,26 +56,24 @@ namespace NzbDrone.Core.Providers.Jobs return; } - var subfolders = _diskProvider.GetDirectories(dropFolder); - - foreach (var subfolder in subfolders) + foreach (var subfolder in _diskProvider.GetDirectories(dropFolder)) { - var di = new DirectoryInfo(subfolder); + var subfolderInfo = new DirectoryInfo(subfolder); - if (di.Name.StartsWith("_UNPACK_")) + if (subfolderInfo.Name.StartsWith("_UNPACK_", StringComparison.CurrentCultureIgnoreCase)) { - Logger.Info("Folder [{0}] is still being unpacked", subfolder); + Logger.Info("Folder [{0}] is still being unpacked. skipping.", subfolder); continue; } - if (di.Name.StartsWith("_FAILED_")) + if (subfolderInfo.Name.StartsWith("_FAILED_", StringComparison.CurrentCultureIgnoreCase)) { - Logger.Info("Folder [{0}] is marked as failed", subfolder); + Logger.Info("Folder [{0}] is marked as failed. skipping.", subfolder); continue; } //Parse the Folder name - var seriesName = Parser.ParseSeriesName(di.Name); + var seriesName = Parser.ParseSeriesName(subfolderInfo.Name); var series = _seriesProvider.FindSeries(seriesName); if (series == null) @@ -84,8 +82,10 @@ namespace NzbDrone.Core.Providers.Jobs return; } - _diskScanProvider.Scan(series, subfolder); + var importedFiles = _diskScanProvider.Scan(series, subfolder); + importedFiles.ForEach(file => _diskScanProvider.RenameEpisodeFile(file)); } + Logger.Debug("New Download Scan Job completed successfully"); } } diff --git a/NzbDrone.Core/Providers/MediaFileProvider.cs b/NzbDrone.Core/Providers/MediaFileProvider.cs index 9d56da9fe..d9e4271ec 100644 --- a/NzbDrone.Core/Providers/MediaFileProvider.cs +++ b/NzbDrone.Core/Providers/MediaFileProvider.cs @@ -74,24 +74,41 @@ namespace NzbDrone.Core.Providers return new FileInfo(path); } - public virtual void CleanEpisodesWithNonExistantFiles() + public virtual int RepairLinks() { - _database.Execute(@"UPDATE Episodes SET EpisodeFileId = 0 + Logger.Debug("Verifying Episode>Episode file relationships."); + var updated = _database.Execute(@"UPDATE Episodes SET EpisodeFileId = 0 WHERE EpisodeFileId IN (SELECT Episodes.EpisodeFileId FROM Episodes LEFT OUTER JOIN EpisodeFiles ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId WHERE Episodes.EpisodeFileId > 0 AND EpisodeFiles.EpisodeFileId IS null)"); + + if (updated > 0) + { + Logger.Warn("Removed {0} invalid links to episode files.", updated); + } + + return updated; } - public virtual void DeleteOrphanedEpisodeFiles() + public virtual int DeleteOrphaned() { - _database.Execute(@"DELETE FROM EpisodeFiles + Logger.Debug("Deleting orphaned files."); + + var updated = _database.Execute(@"DELETE FROM EpisodeFiles WHERE EpisodeFileId IN (SELECT EpisodeFiles.EpisodeFileId FROM EpisodeFiles LEFT OUTER JOIN Episodes ON EpisodeFiles.EpisodeFileId = Episodes.EpisodeFileId WHERE Episodes.EpisodeFileId IS null)"); + + if (updated > 0) + { + Logger.Warn("Removed {0} orphaned files.", updated); + } + + return updated; } public virtual string GetNewFilename(IList episodes, string seriesTitle, QualityTypes quality) diff --git a/NzbDrone.Core/Providers/TvDbProvider.cs b/NzbDrone.Core/Providers/TvDbProvider.cs index 9225a9c69..0b9d121df 100644 --- a/NzbDrone.Core/Providers/TvDbProvider.cs +++ b/NzbDrone.Core/Providers/TvDbProvider.cs @@ -43,8 +43,7 @@ namespace NzbDrone.Core.Providers lock (_handler) { Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); - var result = _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, false, false); - + var result = _handler.GetSeries(id, TvdbLanguage.DefaultLanguage, loadEpisodes, false, true, true); //Fix American Dad's scene gongshow if (result != null && result.Id == 73141) diff --git a/NzbDrone.Core/Repository/EpisodeFile.cs b/NzbDrone.Core/Repository/EpisodeFile.cs index 0202aba66..0647c82e0 100644 --- a/NzbDrone.Core/Repository/EpisodeFile.cs +++ b/NzbDrone.Core/Repository/EpisodeFile.cs @@ -24,5 +24,19 @@ namespace NzbDrone.Core.Repository [Ignore] public Series Series { get; set; } + + [Ignore] + public Model.Quality QualityWrapper + { + get + { + return new Model.Quality(Quality, Proper); + } + set + { + Quality = value.QualityType; + Proper = value.Proper; + } + } } } \ No newline at end of file