1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-09 12:32:31 +01:00

Merge branch 'master' of git://github.com/kayone/NzbDrone

This commit is contained in:
Mark McDowall 2011-06-21 00:02:32 -07:00
commit 950e600964
11 changed files with 487 additions and 317 deletions

View File

@ -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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(c => c.SeriesId = fakeSeries.SeriesId)
.With(c => c.SeasonNumber = seasonNumber)
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
var database = mocker.GetMock<IDatabase>(MockBehavior.Strict);
database.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
database.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(1).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
Assert.IsNotNull(result);
mocker.GetMock<IDatabase>().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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(c => c.SeriesId = fakeSeries.SeriesId)
.With(c => c.SeasonNumber = seasonNumber)
.With(e => e.EpisodeFile = Builder<EpisodeFile>.CreateNew()
.With(g => g.Quality = (QualityTypes)currentFileQuality)
.And(g => g.Proper = currentFileProper).Build()
)
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
var database = mocker.GetMock<IDatabase>(MockBehavior.Strict);
database.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
database.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(1).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
Assert.IsNotNull(result);
mocker.GetMock<IDatabase>().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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(c => c.SeriesId = fakeSeries.SeriesId)
.With(c => c.SeasonNumber = seasonNumber)
.With(c => c.EpisodeFile = Builder<EpisodeFile>.CreateNew()
.With(e => e.Quality = QualityTypes.Bluray720p).Build()
)
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
var database = mocker.GetMock<IDatabase>(MockBehavior.Strict);
database.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
result.Should().BeNull();
mocker.GetMock<IDatabase>().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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build();
//Mocks
var mocker = new AutoMoqer();
var database = mocker.GetMock<IDatabase>(MockBehavior.Strict);
database.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
database.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(1).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode).
Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
Assert.IsNotNull(result);
mocker.GetMock<IDatabase>().VerifyAll();
mocker.GetMock<IDatabase>().Verify(r => r.Insert(result), Times.Once());
mocker.GetMock<EpisodeProvider>().VerifyAll();
mocker.GetMock<DiskProvider>().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<Series>.CreateNew().Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(true).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().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<Series>.CreateNew().Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>()
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>())).Returns(false).Verifiable();
mocker.GetMock<IDatabase>()
.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(0).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode).
Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().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<Series>.CreateNew().Build();
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(true).Verifiable();
mocker.GetMock<EpisodeProvider>(MockBehavior.Strict);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
result.Should().BeNull();
mocker.GetMock<IDatabase>().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<Series>.CreateNew().Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
mocker.GetMock<EpisodeProvider>(MockBehavior.Strict)
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns<Episode>(null).
Verifiable();
mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(e => e.GetSize(fileName)).Returns(90000000000);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
mocker.VerifyAllMocks();
result.Should().BeNull();
mocker.GetMock<IDatabase>().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<SeriesProvider>()
.Setup(c => c.UpdateSeries(It.Is<Series>(s => s.LastDiskSync != null))).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisodeBySeries(It.IsAny<long>()))
.Returns(new List<Episode> { new Episode() });
mocker.GetMock<MediaFileProvider>()
.Setup(c => c.GetSeriesFiles(It.IsAny<int>()))
.Returns(new List<EpisodeFile>());
mocker.Resolve<DiskScanProvider>().Scan(new Series());
mocker.VerifyAllMocks();
}
}
}

View File

@ -8,7 +8,9 @@
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Providers; using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository; using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using PetaPoco; using PetaPoco;
using TvdbLib.Data; using TvdbLib.Data;
@ -81,7 +83,7 @@ public void GetEpisodes_by_season_episode_doesnt_exists()
var db = MockLib.GetEmptyDatabase(); var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db); mocker.SetConstant(db);
//Act //Act
var episode = mocker.Resolve<EpisodeProvider>().GetEpisode(1, 1, 1); var episode = mocker.Resolve<EpisodeProvider>().GetEpisode(1, 1, 1);
@ -101,7 +103,7 @@ public void GetEpisode_with_EpisodeFile()
var fakeFile = Builder<EpisodeFile>.CreateNew().With(f => f.EpisodeFileId).Build(); var fakeFile = Builder<EpisodeFile>.CreateNew().With(f => f.EpisodeFileId).Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(5) var fakeEpisodes = Builder<Episode>.CreateListOfSize(5)
.WhereAll().Have(e => e.SeriesId = 1).WhereTheFirst(1).Have(e => e.EpisodeFileId = 1).Have(e => e.EpisodeFile = fakeFile).Build(); .WhereAll().Have(e => e.SeriesId = 1).WhereTheFirst(1).Have(e => e.EpisodeFileId = 1).Have(e => e.EpisodeFile = fakeFile).Build();
db.InsertMany(fakeEpisodes); db.InsertMany(fakeEpisodes);
db.Insert(fakeFile); db.Insert(fakeFile);
@ -562,13 +564,21 @@ public void IsSeasonIgnored_should_return_true_if_invalid_series()
public void Add_daily_show_episodes() public void Add_daily_show_episodes()
{ {
var mocker = new AutoMoqer(); var mocker = new AutoMoqer();
mocker.SetConstant(MockLib.GetEmptyDatabase()); var db = MockLib.GetEmptyDatabase();
mocker.SetConstant(db);
mocker.Resolve<TvDbProvider>(); mocker.Resolve<TvDbProvider>();
mocker.GetMock<ConfigProvider>()
.Setup(e => e.DefaultQualityProfile).Returns(1);
db.Insert(Builder<QualityProfile>.CreateNew().Build());
const int tvDbSeriesId = 71256; const int tvDbSeriesId = 71256;
//act //act
var seriesProvider = mocker.Resolve<SeriesProvider>(); var seriesProvider = mocker.Resolve<SeriesProvider>();
seriesProvider.AddSeries("c:\\test\\", tvDbSeriesId, 0); seriesProvider.AddSeries("c:\\test\\", tvDbSeriesId, 1);
var episodeProvider = mocker.Resolve<EpisodeProvider>(); var episodeProvider = mocker.Resolve<EpisodeProvider>();
episodeProvider.RefreshEpisodeInfo(seriesProvider.GetSeries(tvDbSeriesId)); episodeProvider.RefreshEpisodeInfo(seriesProvider.GetSeries(tvDbSeriesId));
@ -606,6 +616,8 @@ public void GetEpisode_by_Season_Episode_with_EpisodeFile()
episode.EpisodeFile.Should().NotBeNull(); episode.EpisodeFile.Should().NotBeNull();
} }
[Test] [Test]
public void GetEpisode_by_Season_Episode_without_EpisodeFile() public void GetEpisode_by_Season_Episode_without_EpisodeFile()
{ {

View File

@ -25,282 +25,7 @@ namespace NzbDrone.Core.Test
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
public class MediaFileProviderTests : TestBase 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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(c => c.SeriesId = fakeSeries.SeriesId)
.With(c => c.SeasonNumber = seasonNumber)
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
var database = mocker.GetMock<IDatabase>(MockBehavior.Strict);
database.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
database.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(1).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns(fakeEpisode);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
Assert.IsNotNull(result);
mocker.GetMock<IDatabase>().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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build();
//Mocks
var mocker = new AutoMoqer();
var database = mocker.GetMock<IDatabase>(MockBehavior.Strict);
database.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
database.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(1).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode).
Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
Assert.IsNotNull(result);
mocker.GetMock<IDatabase>().VerifyAll();
mocker.GetMock<IDatabase>().Verify(r => r.Insert(result), Times.Once());
mocker.GetMock<EpisodeProvider>().VerifyAll();
mocker.GetMock<DiskProvider>().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<Series>.CreateNew().Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(true).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().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<Series>.CreateNew().Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().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<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew().With(c => c.SeriesId = fakeSeries.SeriesId).Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>()
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>())).Returns(false).Verifiable();
mocker.GetMock<IDatabase>()
.Setup(r => r.Insert(It.IsAny<EpisodeFile>())).Returns(0).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, airDate)).Returns(fakeEpisode).
Verifiable();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(size).Verifiable();
//Act
var result = mocker.Resolve<DiskScanProvider>().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<Series>.CreateNew().Build();
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(true).Verifiable();
mocker.GetMock<EpisodeProvider>(MockBehavior.Strict);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
result.Should().BeNull();
mocker.GetMock<IDatabase>().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<Series>.CreateNew().Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<IDatabase>(MockBehavior.Strict)
.Setup(r => r.Exists<EpisodeFile>(It.IsAny<string>(), It.IsAny<object>())).Returns(false).Verifiable();
mocker.GetMock<EpisodeProvider>(MockBehavior.Strict)
.Setup(e => e.GetEpisode(fakeSeries.SeriesId, seasonNumber, episodeNumner)).Returns<Episode>(null).
Verifiable();
mocker.GetMock<DiskProvider>(MockBehavior.Strict)
.Setup(e => e.GetSize(fileName)).Returns(90000000000);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
mocker.VerifyAllMocks();
result.Should().BeNull();
mocker.GetMock<IDatabase>().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<SeriesProvider>()
.Setup(c => c.UpdateSeries(It.Is<Series>(s => s.LastDiskSync != null))).Verifiable();
mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisodeBySeries(It.IsAny<long>()))
.Returns(new List<Episode> { new Episode() });
mocker.Resolve<DiskScanProvider>().Scan(new Series());
mocker.VerifyAllMocks();
}
[Test] [Test]
@ -334,10 +59,17 @@ public void get_series_files()
public void Scan_series_should_skip_series_with_no_episodes() public void Scan_series_should_skip_series_with_no_episodes()
{ {
var mocker = new AutoMoqer(MockBehavior.Strict); var mocker = new AutoMoqer(MockBehavior.Strict);
mocker.GetMock<EpisodeProvider>() mocker.GetMock<EpisodeProvider>()
.Setup(c => c.GetEpisodeBySeries(12)) .Setup(c => c.GetEpisodeBySeries(12))
.Returns(new List<Episode>()); .Returns(new List<Episode>());
mocker.GetMock<MediaFileProvider>()
.Setup(e => e.RepairLinks()).Returns(0);
mocker.GetMock<MediaFileProvider>()
.Setup(e => e.DeleteOrphaned()).Returns(0);
var series = Builder<Series>.CreateNew() var series = Builder<Series>.CreateNew()
.With(s => s.SeriesId = 12).Build(); .With(s => s.SeriesId = 12).Build();
@ -372,12 +104,14 @@ public void CleanEpisodesWithNonExistantFiles()
database.InsertMany(episodes); database.InsertMany(episodes);
//Act //Act
mocker.Resolve<MediaFileProvider>().CleanEpisodesWithNonExistantFiles(); var removedLinks = mocker.Resolve<MediaFileProvider>().RepairLinks();
var result = database.Fetch<Episode>(); var result = database.Fetch<Episode>();
//Assert //Assert
result.Should().HaveSameCount(episodes); result.Should().HaveSameCount(episodes);
result.Should().OnlyContain(e => e.EpisodeFileId == 0); result.Should().OnlyContain(e => e.EpisodeFileId == 0);
removedLinks.Should().Be(10);
ExceptionVerification.ExcpectedWarns(1);
} }
[Test] [Test]
@ -394,12 +128,13 @@ public void DeleteOrphanedEpisodeFiles()
database.InsertMany(episodeFiles); database.InsertMany(episodeFiles);
//Act //Act
mocker.Resolve<MediaFileProvider>().DeleteOrphanedEpisodeFiles(); mocker.Resolve<MediaFileProvider>().DeleteOrphaned();
var result = database.Fetch<EpisodeFile>(); var result = database.Fetch<EpisodeFile>();
//Assert //Assert
result.Should().HaveCount(5); result.Should().HaveCount(5);
result.Should().OnlyContain(e => e.EpisodeFileId > 0); result.Should().OnlyContain(e => e.EpisodeFileId > 0);
ExceptionVerification.ExcpectedWarns(1);
} }
} }
} }

View File

@ -76,6 +76,7 @@
<HintPath>..\Libraries\System.Data.SQLite.dll</HintPath> <HintPath>..\Libraries\System.Data.SQLite.dll</HintPath>
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
</Reference> </Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceModel" /> <Reference Include="System.ServiceModel" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="TvdbLib, Version=0.8.8.0, Culture=neutral, processorArchitecture=MSIL">
@ -84,6 +85,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="DiskScanProviderTest.cs" />
<Compile Include="FluentTest.cs" /> <Compile Include="FluentTest.cs" />
<Compile Include="LogProviderTest.cs" /> <Compile Include="LogProviderTest.cs" />
<Compile Include="UpcomingEpisodesProviderTest.cs" /> <Compile Include="UpcomingEpisodesProviderTest.cs" />

View File

@ -147,6 +147,7 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\Libraries\System.Data.SQLite.dll</HintPath> <HintPath>..\Libraries\System.Data.SQLite.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Runtime.Serialization" />
<Reference Include="System.ServiceModel" /> <Reference Include="System.ServiceModel" />
<Reference Include="System.Web" /> <Reference Include="System.Web" />

View File

@ -48,11 +48,6 @@ public virtual void RenameFile(string sourcePath, string destinationPath)
File.Move(sourcePath, destinationPath); File.Move(sourcePath, destinationPath);
} }
public virtual string GetExtension(string path)
{
return Path.GetExtension(path);
}
public virtual void DeleteFolder(string path, bool recursive) public virtual void DeleteFolder(string path, bool recursive)
{ {
Directory.Delete(path, recursive); Directory.Delete(path, recursive);

View File

@ -13,7 +13,7 @@ namespace NzbDrone.Core.Providers
public class DiskScanProvider public class DiskScanProvider
{ {
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); 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 IDatabase _database;
private readonly DiskProvider _diskProvider; private readonly DiskProvider _diskProvider;
private readonly EpisodeProvider _episodeProvider; private readonly EpisodeProvider _episodeProvider;
@ -53,26 +53,32 @@ public virtual List<EpisodeFile> Scan(Series series)
/// <param name="path">Path to scan</param> /// <param name="path">Path to scan</param>
public virtual List<EpisodeFile> Scan(Series series, string path) public virtual List<EpisodeFile> Scan(Series series, string path)
{ {
_mediaFileProvider.DeleteOrphaned();
_mediaFileProvider.RepairLinks();
if (_episodeProvider.GetEpisodeBySeries(series.SeriesId).Count == 0) if (_episodeProvider.GetEpisodeBySeries(series.SeriesId).Count == 0)
{ {
Logger.Debug("Series {0} has no episodes. skipping", series.Title); Logger.Debug("Series {0} has no episodes. skipping", series.Title);
return new List<EpisodeFile>(); return new List<EpisodeFile>();
} }
var seriesFile = _mediaFileProvider.GetSeriesFiles(series.SeriesId);
CleanUp(seriesFile);
var mediaFileList = GetVideoFiles(path); var mediaFileList = GetVideoFiles(path);
var fileList = new List<EpisodeFile>(); var importedFiles = new List<EpisodeFile>();
foreach (var filePath in mediaFileList) foreach (var filePath in mediaFileList)
{ {
var file = ImportFile(series, filePath); var file = ImportFile(series, filePath);
if (file != null) if (file != null)
fileList.Add(file); importedFiles.Add(file);
} }
series.LastDiskSync = DateTime.Now; series.LastDiskSync = DateTime.Now;
_seriesProvider.UpdateSeries(series); _seriesProvider.UpdateSeries(series);
return fileList; return importedFiles;
} }
@ -88,7 +94,7 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
long size = _diskProvider.GetSize(filePath); 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")) if (size < 40000000 && filePath.ToLower().Contains("sample"))
{ {
Logger.Trace("[{0}] appears to be a sample. skipping.", filePath); Logger.Trace("[{0}] appears to be a sample. skipping.", filePath);
@ -141,6 +147,13 @@ public virtual EpisodeFile ImportFile(Series series, string filePath)
if (episodes.Count <= 0) if (episodes.Count <= 0)
return null; 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(); var episodeFile = new EpisodeFile();
episodeFile.DateAdded = DateTime.Now; episodeFile.DateAdded = DateTime.Now;
episodeFile.SeriesId = series.SeriesId; episodeFile.SeriesId = series.SeriesId;
@ -172,20 +185,18 @@ public virtual bool RenameEpisodeFile(EpisodeFile episodeFile)
throw new ArgumentNullException("episodeFile"); throw new ArgumentNullException("episodeFile");
var series = _seriesProvider.GetSeries(episodeFile.SeriesId); var series = _seriesProvider.GetSeries(episodeFile.SeriesId);
string ext = _diskProvider.GetExtension(episodeFile.Path);
var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId); var episodes = _episodeProvider.GetEpisodesByFileId(episodeFile.EpisodeFileId);
string newFileName = _mediaFileProvider.GetNewFilename(episodes, series.Title, episodeFile.Quality); string newFileName = _mediaFileProvider.GetNewFilename(episodes, series.Title, episodeFile.Quality);
var newFile = _mediaFileProvider.CalculateFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path));
var newFile = _mediaFileProvider.CalculateFilePath(series, episodes.First().SeasonNumber, newFileName, ext);
//Do the rename //Do the rename
Logger.Trace("Attempting to rename {0} to {1}", episodeFile.Path, newFile.FullName);
_diskProvider.RenameFile(episodeFile.Path, newFile.FullName); _diskProvider.RenameFile(episodeFile.Path, newFile.FullName);
//Update the filename in the DB //Update the filename in the DB
episodeFile.Path = newFile.FullName; episodeFile.Path = newFile.FullName;
_mediaFileProvider.Update(episodeFile); _mediaFileProvider.Update(episodeFile);
return true; return true;
} }
@ -194,11 +205,8 @@ public virtual bool RenameEpisodeFile(EpisodeFile episodeFile)
/// Removes files that no longer exist on disk from the database /// Removes files that no longer exist on disk from the database
/// </summary> /// </summary>
/// <param name = "files">list of files to verify</param> /// <param name = "files">list of files to verify</param>
public virtual void CleanUp(List<EpisodeFile> files) public virtual void CleanUp(IList<EpisodeFile> files)
{ {
_mediaFileProvider.CleanEpisodesWithNonExistantFiles();
_mediaFileProvider.DeleteOrphanedEpisodeFiles();
foreach (var episodeFile in files) foreach (var episodeFile in files)
{ {
if (!_diskProvider.FileExists(episodeFile.Path)) if (!_diskProvider.FileExists(episodeFile.Path))

View File

@ -44,9 +44,9 @@ public virtual void Start(ProgressNotification notification, int targetId)
Logger.Debug("Starting New Download Scan Job"); Logger.Debug("Starting New Download Scan Job");
var dropFolder = _configProvider.SabDropDirectory; 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; return;
} }
@ -56,26 +56,24 @@ public virtual void Start(ProgressNotification notification, int targetId)
return; return;
} }
var subfolders = _diskProvider.GetDirectories(dropFolder); foreach (var subfolder in _diskProvider.GetDirectories(dropFolder))
foreach (var subfolder in subfolders)
{ {
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; 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; continue;
} }
//Parse the Folder name //Parse the Folder name
var seriesName = Parser.ParseSeriesName(di.Name); var seriesName = Parser.ParseSeriesName(subfolderInfo.Name);
var series = _seriesProvider.FindSeries(seriesName); var series = _seriesProvider.FindSeries(seriesName);
if (series == null) if (series == null)
@ -84,8 +82,10 @@ public virtual void Start(ProgressNotification notification, int targetId)
return; 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"); Logger.Debug("New Download Scan Job completed successfully");
} }
} }

View File

@ -74,24 +74,41 @@ public virtual FileInfo CalculateFilePath(Series series, int seasonNumber, strin
return new FileInfo(path); 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 WHERE EpisodeFileId IN
(SELECT Episodes.EpisodeFileId FROM Episodes (SELECT Episodes.EpisodeFileId FROM Episodes
LEFT OUTER JOIN EpisodeFiles LEFT OUTER JOIN EpisodeFiles
ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId
WHERE Episodes.EpisodeFileId > 0 AND EpisodeFiles.EpisodeFileId IS null)"); 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 WHERE EpisodeFileId IN
(SELECT EpisodeFiles.EpisodeFileId FROM EpisodeFiles (SELECT EpisodeFiles.EpisodeFileId FROM EpisodeFiles
LEFT OUTER JOIN Episodes LEFT OUTER JOIN Episodes
ON EpisodeFiles.EpisodeFileId = Episodes.EpisodeFileId ON EpisodeFiles.EpisodeFileId = Episodes.EpisodeFileId
WHERE Episodes.EpisodeFileId IS null)"); WHERE Episodes.EpisodeFileId IS null)");
if (updated > 0)
{
Logger.Warn("Removed {0} orphaned files.", updated);
}
return updated;
} }
public virtual string GetNewFilename(IList<Episode> episodes, string seriesTitle, QualityTypes quality) public virtual string GetNewFilename(IList<Episode> episodes, string seriesTitle, QualityTypes quality)

View File

@ -43,8 +43,7 @@ public virtual TvdbSeries GetSeries(int id, bool loadEpisodes)
lock (_handler) lock (_handler)
{ {
Logger.Debug("Fetching SeriesId'{0}' from tvdb", id); 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 //Fix American Dad's scene gongshow
if (result != null && result.Id == 73141) if (result != null && result.Id == 73141)

View File

@ -24,5 +24,19 @@ public class EpisodeFile
[Ignore] [Ignore]
public Series Series { get; set; } public Series Series { get; set; }
[Ignore]
public Model.Quality QualityWrapper
{
get
{
return new Model.Quality(Quality, Proper);
}
set
{
Quality = value.QualityType;
Proper = value.Proper;
}
}
} }
} }