Fixed: Update Unit Tests for Indexers/Clients

pull/3564/head
Qstick 5 years ago
parent 8a9e2dc90d
commit c76364a891

@ -4,6 +4,7 @@ using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Blacklisting;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
@ -21,7 +22,8 @@ namespace NzbDrone.Core.Test.Blacklisting
{
MovieId = 1234,
Quality = new QualityModel(),
SourceTitle = "series.title.s01e01",
Languages = new List<Language>(),
SourceTitle = "movie.title.1998",
Date = DateTime.UtcNow
};
}
@ -34,7 +36,7 @@ namespace NzbDrone.Core.Test.Blacklisting
}
[Test]
public void should_should_have_episode_ids()
public void should_should_have_movie_id()
{
Subject.Insert(_blacklist);

@ -0,0 +1,59 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class BooleanIntConverterFixture : CoreTest<Core.Datastore.Converters.BooleanIntConverter>
{
[TestCase(true, 1)]
[TestCase(false, 0)]
public void should_return_int_when_saving_boolean_to_db(bool input, int expected)
{
Subject.ToDB(input).Should().Be(expected);
}
[Test]
public void should_return_db_null_for_null_value_when_saving_to_db()
{
Subject.ToDB(null).Should().Be(DBNull.Value);
}
[TestCase(1, true)]
[TestCase(0, false)]
public void should_return_bool_when_getting_int_from_db(int input, bool expected)
{
var context = new ConverterContext
{
DbValue = (long)input
};
Subject.FromDB(context).Should().Be(expected);
}
[Test]
public void should_return_db_null_for_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(DBNull.Value);
}
[Test]
public void should_throw_for_non_boolean_equivalent_number_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = (long)2
};
Assert.Throws<ConversionException>(() => Subject.FromDB(context));
}
}
}

@ -0,0 +1,64 @@
using System;
using System.Data;
using FluentAssertions;
using Marr.Data.Converters;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies.Commands;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class CommandConverterFixture : CoreTest<CommandConverter>
{
[Test]
public void should_return_json_string_when_saving_boolean_to_db()
{
var command = new RefreshMovieCommand();
Subject.ToDB(command).Should().BeOfType<string>();
}
[Test]
public void should_return_null_for_null_value_when_saving_to_db()
{
Subject.ToDB(null).Should().Be(null);
}
[Test]
public void should_return_db_null_for_db_null_value_when_saving_to_db()
{
Subject.ToDB(DBNull.Value).Should().Be(DBNull.Value);
}
[Test]
public void should_return_command_when_getting_json_from_db()
{
var dataRecordMock = new Mock<IDataRecord>();
dataRecordMock.Setup(s => s.GetOrdinal("Name")).Returns(0);
dataRecordMock.Setup(s => s.GetString(0)).Returns("RefreshMovie");
var context = new ConverterContext
{
DataRecord = dataRecordMock.Object,
DbValue = new RefreshMovieCommand().ToJson()
};
Subject.FromDB(context).Should().BeOfType<RefreshMovieCommand>();
}
[Test]
public void should_return_null_for_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(null);
}
}
}

@ -0,0 +1,70 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class DoubleConverterFixture : CoreTest<DoubleConverter>
{
[Test]
public void should_return_double_when_saving_double_to_db()
{
var input = 10.5D;
Subject.ToDB(input).Should().Be(input);
}
[Test]
public void should_return_null_for_null_value_when_saving_to_db()
{
Subject.ToDB(null).Should().Be(null);
}
[Test]
public void should_return_db_null_for_db_null_value_when_saving_to_db()
{
Subject.ToDB(DBNull.Value).Should().Be(DBNull.Value);
}
[Test]
public void should_return_double_when_getting_double_from_db()
{
var expected = 10.5D;
var context = new ConverterContext
{
DbValue = expected
};
Subject.FromDB(context).Should().Be(expected);
}
[Test]
public void should_return_double_when_getting_string_from_db()
{
var expected = 10.5D;
var context = new ConverterContext
{
DbValue = $"{expected}"
};
Subject.FromDB(context).Should().Be(expected);
}
[Test]
public void should_return_null_for_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(DBNull.Value);
}
}
}

@ -0,0 +1,58 @@
using System;
using System.Reflection;
using FluentAssertions;
using Marr.Data.Converters;
using Marr.Data.Mapping;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Download.Pending;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class EnumIntConverterFixture : CoreTest<Core.Datastore.Converters.EnumIntConverter>
{
[Test]
public void should_return_int_when_saving_enum_to_db()
{
Subject.ToDB(PendingReleaseReason.Delay).Should().Be((int)PendingReleaseReason.Delay);
}
[Test]
public void should_return_db_null_for_null_value_when_saving_to_db()
{
Subject.ToDB(null).Should().Be(DBNull.Value);
}
[Test]
public void should_return_enum_when_getting_int_from_db()
{
var mockMemberInfo = new Mock<MemberInfo>();
mockMemberInfo.SetupGet(s => s.DeclaringType).Returns(typeof(PendingRelease));
mockMemberInfo.SetupGet(s => s.Name).Returns("Reason");
var expected = PendingReleaseReason.Delay;
var context = new ConverterContext
{
ColumnMap = new ColumnMap(mockMemberInfo.Object) { FieldType = typeof(PendingReleaseReason) },
DbValue = (long)expected
};
Subject.FromDB(context).Should().Be(expected);
}
[Test]
public void should_return_null_for_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(null);
}
}
}

@ -0,0 +1,51 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class GuidConverterFixture : CoreTest<GuidConverter>
{
[Test]
public void should_return_string_when_saving_guid_to_db()
{
var guid = Guid.NewGuid();
Subject.ToDB(guid).Should().Be(guid.ToString());
}
[Test]
public void should_return_db_null_for_null_value_when_saving_to_db()
{
Subject.ToDB(null).Should().Be(DBNull.Value);
}
[Test]
public void should_return_guid_when_getting_string_from_db()
{
var guid = Guid.NewGuid();
var context = new ConverterContext
{
DbValue = guid.ToString()
};
Subject.FromDB(context).Should().Be(guid);
}
[Test]
public void should_return_empty_guid_for_db_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(Guid.Empty);
}
}
}

@ -0,0 +1,58 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class Int32ConverterFixture : CoreTest<Int32Converter>
{
[Test]
public void should_return_int_when_saving_int_to_db()
{
var i = 5;
Subject.ToDB(5).Should().Be(5);
}
[Test]
public void should_return_int_when_getting_int_from_db()
{
var i = 5;
var context = new ConverterContext
{
DbValue = i
};
Subject.FromDB(context).Should().Be(i);
}
[Test]
public void should_return_int_when_getting_string_from_db()
{
var i = 5;
var context = new ConverterContext
{
DbValue = i.ToString()
};
Subject.FromDB(context).Should().Be(i);
}
[Test]
public void should_return_db_null_for_db_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(DBNull.Value);
}
}
}

@ -0,0 +1,49 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class OsPathConverterFixture : CoreTest<OsPathConverter>
{
[Test]
public void should_return_string_when_saving_os_path_to_db()
{
var path = @"C:\Test\TV".AsOsAgnostic();
var osPath = new OsPath(path);
Subject.ToDB(osPath).Should().Be(path);
}
[Test]
public void should_return_os_path_when_getting_string_from_db()
{
var path = @"C:\Test\TV".AsOsAgnostic();
var osPath = new OsPath(path);
var context = new ConverterContext
{
DbValue = path
};
Subject.FromDB(context).Should().Be(osPath);
}
[Test]
public void should_return_db_null_for_db_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(DBNull.Value);
}
}
}

@ -0,0 +1,58 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class QualityIntConverterFixture : CoreTest<QualityIntConverter>
{
[Test]
public void should_return_int_when_saving_quality_to_db()
{
var quality = Quality.Bluray1080p;
Subject.ToDB(quality).Should().Be(quality.Id);
}
[Test]
public void should_return_0_when_saving_db_null_to_db()
{
Subject.ToDB(DBNull.Value).Should().Be(0);
}
[Test]
public void should_throw_when_saving_another_object_to_db()
{
Assert.Throws<InvalidOperationException>(() => Subject.ToDB("Not a quality"));
}
[Test]
public void should_return_quality_when_getting_string_from_db()
{
var quality = Quality.Bluray1080p;
var context = new ConverterContext
{
DbValue = quality.Id
};
Subject.FromDB(context).Should().Be(quality);
}
[Test]
public void should_return_db_null_for_db_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(Quality.Unknown);
}
}
}

@ -0,0 +1,65 @@
using System;
using System.Globalization;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class TimeSpanConverterFixture : CoreTest<TimeSpanConverter>
{
[Test]
public void should_return_string_when_saving_timespan_to_db()
{
var timeSpan = TimeSpan.FromMinutes(5);
Subject.ToDB(timeSpan).Should().Be(timeSpan.ToString("c", CultureInfo.InvariantCulture));
}
[Test]
public void should_return_null_when_saving_empty_string_to_db()
{
Subject.ToDB("").Should().Be(null);
}
[Test]
public void should_return_time_span_when_getting_time_span_from_db()
{
var timeSpan = TimeSpan.FromMinutes(5);
var context = new ConverterContext
{
DbValue = timeSpan
};
Subject.FromDB(context).Should().Be(timeSpan);
}
[Test]
public void should_return_time_span_when_getting_string_from_db()
{
var timeSpan = TimeSpan.FromMinutes(5);
var context = new ConverterContext
{
DbValue = timeSpan.ToString("c", CultureInfo.InvariantCulture)
};
Subject.FromDB(context).Should().Be(timeSpan);
}
[Test]
public void should_return_time_span_zero_for_db_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(TimeSpan.Zero);
}
}
}

@ -0,0 +1,51 @@
using System;
using FluentAssertions;
using Marr.Data.Converters;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Converters
{
[TestFixture]
public class UtcConverterFixture : CoreTest<UtcConverter>
{
[Test]
public void should_return_date_time_when_saving_date_time_to_db()
{
var dateTime = DateTime.Now;
Subject.ToDB(dateTime).Should().Be(dateTime.ToUniversalTime());
}
[Test]
public void should_return_db_null_when_saving_db_null_to_db()
{
Subject.ToDB(DBNull.Value).Should().Be(DBNull.Value);
}
[Test]
public void should_return_time_span_when_getting_time_span_from_db()
{
var dateTime = DateTime.Now.ToUniversalTime();
var context = new ConverterContext
{
DbValue = dateTime
};
Subject.FromDB(context).Should().Be(dateTime);
}
[Test]
public void should_return_db_null_for_db_null_value_when_getting_from_db()
{
var context = new ConverterContext
{
DbValue = DBNull.Value
};
Subject.FromDB(context).Should().Be(DBNull.Value);
}
}
}

@ -0,0 +1,161 @@
using System;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Download;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Download
{
public class DownloadClientStatusServiceFixture : CoreTest<DownloadClientStatusService>
{
private DateTime _epoch;
[SetUp]
public void SetUp()
{
_epoch = DateTime.UtcNow;
Mocker.GetMock<IRuntimeInfo>()
.SetupGet(v => v.StartTime)
.Returns(_epoch - TimeSpan.FromHours(1));
}
private DownloadClientStatus WithStatus(DownloadClientStatus status)
{
Mocker.GetMock<IDownloadClientStatusRepository>()
.Setup(v => v.FindByProviderId(1))
.Returns(status);
Mocker.GetMock<IDownloadClientStatusRepository>()
.Setup(v => v.All())
.Returns(new[] { status });
return status;
}
private void VerifyUpdate()
{
Mocker.GetMock<IDownloadClientStatusRepository>()
.Verify(v => v.Upsert(It.IsAny<DownloadClientStatus>()), Times.Once());
}
private void VerifyNoUpdate()
{
Mocker.GetMock<IDownloadClientStatusRepository>()
.Verify(v => v.Upsert(It.IsAny<DownloadClientStatus>()), Times.Never());
}
[Test]
public void should_not_consider_blocked_within_5_minutes_since_initial_failure()
{
WithStatus(new DownloadClientStatus
{
InitialFailure = _epoch - TimeSpan.FromMinutes(4),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(4),
EscalationLevel = 3
});
Subject.RecordFailure(1);
VerifyUpdate();
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().BeNull();
}
[Test]
public void should_consider_blocked_after_5_minutes_since_initial_failure()
{
WithStatus(new DownloadClientStatus
{
InitialFailure = _epoch - TimeSpan.FromMinutes(6),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(120),
EscalationLevel = 3
});
Subject.RecordFailure(1);
VerifyUpdate();
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
}
[Test]
public void should_not_escalate_further_till_after_5_minutes_since_initial_failure()
{
var origStatus = WithStatus(new DownloadClientStatus
{
InitialFailure = _epoch - TimeSpan.FromMinutes(4),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(4),
EscalationLevel = 3
});
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().BeNull();
origStatus.EscalationLevel.Should().Be(3);
}
[Test]
public void should_escalate_further_after_5_minutes_since_initial_failure()
{
WithStatus(new DownloadClientStatus
{
InitialFailure = _epoch - TimeSpan.FromMinutes(6),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(120),
EscalationLevel = 3
});
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.EscalationLevel.Should().BeGreaterThan(3);
}
[Test]
public void should_not_escalate_beyond_3_hours()
{
WithStatus(new DownloadClientStatus
{
InitialFailure = _epoch - TimeSpan.FromMinutes(6),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(120),
EscalationLevel = 3
});
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Should().NotBeAfter(_epoch + TimeSpan.FromHours(3.1));
}
}
}

@ -74,6 +74,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
.Returns(1000000);
}
protected void GivenMagnetFilePath(string extension = ".magnet")
{
_magnetFilePath = Path.ChangeExtension(_filePath, extension);
}
protected override RemoteMovie CreateRemoteMovie()
{
var remoteMovie = base.CreateRemoteMovie();
@ -99,6 +104,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
var result = Subject.GetItems().Single();
VerifyCompleted(result);
result.CanBeRemoved.Should().BeFalse();
result.CanMoveFiles.Should().BeFalse();
}
[Test]
@ -137,7 +145,27 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
[Test]
public void Download_should_save_magnet_if_enabled()
{
GivenMagnetFilePath();
Subject.Definition.Settings.As<TorrentBlackholeSettings>().SaveMagnetFiles = true;
var remoteMovie = CreateRemoteMovie();
remoteMovie.Release.DownloadUrl = null;
Subject.Download(remoteMovie);
Mocker.GetMock<IHttpClient>().Verify(c => c.Get(It.Is<HttpRequest>(v => v.Url.FullUri == _downloadUrl)), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_filePath), Times.Never());
Mocker.GetMock<IDiskProvider>().Verify(c => c.OpenWriteStream(_magnetFilePath), Times.Once());
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
}
[Test]
public void Download_should_save_magnet_using_specified_extension()
{
var magnetFileExtension = ".url";
GivenMagnetFilePath(magnetFileExtension);
Subject.Definition.Settings.As<TorrentBlackholeSettings>().SaveMagnetFiles = true;
Subject.Definition.Settings.As<TorrentBlackholeSettings>().MagnetFileExtension = magnetFileExtension;
var remoteMovie = CreateRemoteMovie();
remoteMovie.Release.DownloadUrl = null;

@ -290,6 +290,24 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
item.CanBeRemoved.Should().Be(canBeRemoved);
}
[Test]
public void GetItems_should_ignore_items_without_hash()
{
_downloading.Hash = null;
GivenTorrents(new List<DelugeTorrent>
{
_downloading,
_queued
});
var items = Subject.GetItems();
items.Should().HaveCount(1);
items.First().Status.Should().Be(DownloadItemStatus.Queued);
}
[Test]
public void should_return_status_with_outputdirs()
{

@ -73,6 +73,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "0"},
{ "size_uploaded", "0"},
{ "speed_download", "0" }
}
}
@ -96,6 +97,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "1000"},
{ "size_uploaded", "100"},
{ "speed_download", "0" }
},
}
@ -119,6 +121,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "1000"},
{ "size_uploaded", "100"},
{ "speed_download", "0" }
}
}
@ -142,6 +145,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "100"},
{ "size_uploaded", "10"},
{ "speed_download", "50" }
}
}
@ -165,6 +169,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "10"},
{ "size_uploaded", "1"},
{ "speed_download", "0" }
}
}
@ -188,6 +193,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "1000"},
{ "size_uploaded", "100"},
{ "speed_download", "0" }
}
}
@ -211,6 +217,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "1000"},
{ "size_uploaded", "100"},
{ "speed_download", "0" }
}
}
@ -234,6 +241,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "1000"},
{ "size_uploaded", "100"},
{ "speed_download", "0" }
}
}
@ -257,6 +265,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DownloadStationTests
Transfer = new Dictionary<string, string>
{
{ "size_downloaded", "1000"},
{ "size_uploaded", "100"},
{ "speed_download", "0" }
}
}

@ -172,6 +172,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
var result = Subject.GetItems().Single();
VerifyQueued(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
}
[Test]
@ -185,6 +188,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
var result = Subject.GetItems().Single();
VerifyPaused(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
}
[Test]
@ -198,6 +204,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
var result = Subject.GetItems().Single();
VerifyDownloading(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
}
[Test]
public void post_processing_item_should_have_required_properties()
{
_queued.ActiveDownloads = 1;
GivenQueue(_queued);
GivenHistory(null);
_queued.RemainingSizeLo = 0;
var result = Subject.GetItems().Single();
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
}
[Test]
@ -209,6 +234,9 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
var result = Subject.GetItems().Single();
VerifyCompleted(result);
result.CanBeRemoved.Should().BeTrue();
result.CanMoveFiles.Should().BeTrue();
}
[Test]
@ -377,6 +405,37 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
result.OutputPath.Should().Be(@"O:\mymount\Droned.1998.1080p.WEB-DL-DRONE".AsOsAgnostic());
}
[Test]
public void should_use_dest_dir_if_final_dir_is_null()
{
GivenQueue(null);
GivenHistory(_completed);
Subject.GetItems().First().OutputPath.Should().Be(_completed.DestDir);
}
[Test]
public void should_use_dest_dir_if_final_dir_is_not_set()
{
_completed.FinalDir = string.Empty;
GivenQueue(null);
GivenHistory(_completed);
Subject.GetItems().First().OutputPath.Should().Be(_completed.DestDir);
}
[Test]
public void should_use_final_dir_when_set_instead_of_dest_dir()
{
_completed.FinalDir = "/remote/mount/tv2/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE";
GivenQueue(null);
GivenHistory(_completed);
Subject.GetItems().First().OutputPath.Should().Be(_completed.FinalDir);
}
[TestCase("11.0", false)]
[TestCase("12.0", true)]
[TestCase("11.0-b30ef0134", false)]

@ -9,6 +9,7 @@ using NzbDrone.Core.MediaFiles.TorrentInfo;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.QBittorrent;
using NzbDrone.Test.Common;
using NzbDrone.Core.Exceptions;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
{
@ -38,7 +39,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
Mocker.GetMock<IQBittorrentProxy>()
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
.Returns(new QBittorrentPreferences());
.Returns(new QBittorrentPreferences() { DhtEnabled = true });
Mocker.GetMock<IQBittorrentProxySelector>()
.Setup(s => s.GetProxy(It.IsAny<QBittorrentSettings>(), It.IsAny<bool>()))
.Returns(Mocker.GetMock<IQBittorrentProxy>().Object);
}
protected void GivenRedirectToMagnet()
@ -95,14 +100,17 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
Subject.Definition.Settings.As<QBittorrentSettings>().RecentMoviePriority = (int) QBittorrentPriority.First;
}
protected void GivenMaxRatio(float maxRatio, bool removeOnMaxRatio = true)
protected void GivenGlobalSeedLimits(float maxRatio, int maxSeedingTime = -1, bool removeOnMaxRatio = false)
{
Mocker.GetMock<IQBittorrentProxy>()
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
.Returns(new QBittorrentPreferences
{
RemoveOnMaxRatio = removeOnMaxRatio,
MaxRatio = maxRatio
MaxRatio = maxRatio,
MaxRatioEnabled = maxRatio >= 0,
MaxSeedingTime = maxSeedingTime,
MaxSeedingTimeEnabled = maxSeedingTime >= 0
});
}
@ -154,7 +162,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
var item = Subject.GetItems().Single();
VerifyPaused(item);
item.RemainingTime.Should().NotBe(TimeSpan.Zero);
item.RemainingTime.Should().NotHaveValue();
}
[TestCase("pausedUP")]
@ -162,6 +170,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
[TestCase("uploading")]
[TestCase("stalledUP")]
[TestCase("checkingUP")]
[TestCase("forcedUP")]
public void completed_item_should_have_required_properties(string state)
{
var torrent = new QBittorrentTorrent
@ -184,6 +193,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
[TestCase("queuedDL")]
[TestCase("checkingDL")]
[TestCase("metaDL")]
public void queued_item_should_have_required_properties(string state)
{
var torrent = new QBittorrentTorrent
@ -201,7 +211,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
var item = Subject.GetItems().Single();
VerifyQueued(item);
item.RemainingTime.Should().NotBe(TimeSpan.Zero);
item.RemainingTime.Should().NotHaveValue();
}
[Test]
@ -243,7 +253,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
var item = Subject.GetItems().Single();
VerifyWarning(item);
item.RemainingTime.Should().NotBe(TimeSpan.Zero);
item.RemainingTime.Should().NotHaveValue();
}
[Test]
@ -271,6 +281,35 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
id.Should().Be(expectedHash);
}
[Test]
public void Download_should_refuse_magnet_if_no_trackers_provided_and_dht_is_disabled()
{
Mocker.GetMock<IQBittorrentProxy>()
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
.Returns(new QBittorrentPreferences() { DhtEnabled = false });
var remoteMovie = CreateRemoteMovie();
remoteMovie.Release.DownloadUrl = "magnet:?xt=urn:btih:ZPBPA2P6ROZPKRHK44D5OW6NHXU5Z6KR";
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteMovie));
}
[Test]
public void Download_should_accept_magnet_if_trackers_provided_and_dht_is_disabled()
{
Mocker.GetMock<IQBittorrentProxy>()
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
.Returns(new QBittorrentPreferences() { DhtEnabled = false });
var remoteMovie = CreateRemoteMovie();
remoteMovie.Release.DownloadUrl = "magnet:?xt=urn:btih:ZPBPA2P6ROZPKRHK44D5OW6NHXU5Z6KR&tr=udp://abc";
Assert.DoesNotThrow(() => Subject.Download(remoteMovie));
Mocker.GetMock<IQBittorrentProxy>()
.Verify(s => s.AddTorrentFromUrl(It.IsAny<string>(), It.IsAny<QBittorrentSettings>()), Times.Once());
}
[Test]
public void Download_should_set_top_priority()
{
@ -352,7 +391,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_not_reached()
{
GivenMaxRatio(1.0f);
GivenGlobalSeedLimits(1.0f);
var torrent = new QBittorrentTorrent
{
@ -373,11 +412,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_reached_and_not_paused()
protected virtual QBittorrentTorrent GivenCompletedTorrent(
string state = "pausedUP",
float ratio = 0.1f, float ratioLimit = -2,
int seedingTime = 1, int seedingTimeLimit = -2)
{
GivenMaxRatio(1.0f);
var torrent = new QBittorrentTorrent
{
Hash = "HASH",
@ -385,12 +424,32 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
Size = 1000,
Progress = 1.0,
Eta = 8640000,
State = "uploading",
State = state,
Label = "",
SavePath = "",
Ratio = 1.0f
Ratio = ratio,
RatioLimit = ratioLimit,
SeedingTimeLimit = seedingTimeLimit
};
GivenTorrents(new List<QBittorrentTorrent> { torrent });
GivenTorrents(new List<QBittorrentTorrent>() { torrent });
Mocker.GetMock<IQBittorrentProxy>()
.Setup(s => s.GetTorrentProperties("HASH", It.IsAny<QBittorrentSettings>()))
.Returns(new QBittorrentTorrentProperties
{
Hash = "HASH",
SeedingTime = seedingTime
});
return torrent;
}
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_reached_and_not_paused()
{
GivenGlobalSeedLimits(1.0f);
GivenCompletedTorrent("uploading", ratio: 1.0f);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
@ -400,45 +459,97 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_is_not_set()
{
GivenMaxRatio(1.0f, false);
GivenGlobalSeedLimits(-1);
GivenCompletedTorrent("pausedUP", ratio: 1.0f);
var torrent = new QBittorrentTorrent
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused()
{
Hash = "HASH",
Name = _title,
Size = 1000,
Progress = 1.0,
Eta = 8640000,
State = "uploading",
Label = "",
SavePath = "",
Ratio = 1.0f
};
GivenTorrents(new List<QBittorrentTorrent> { torrent });
GivenGlobalSeedLimits(1.0f);
GivenCompletedTorrent("pausedUP", ratio: 1.0f);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_overridden_max_ratio_reached_and_paused()
{
GivenGlobalSeedLimits(2.0f);
GivenCompletedTorrent("pausedUP", ratio: 1.0f, ratioLimit: 0.8f);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_not_be_removable_if_overridden_max_ratio_not_reached_and_paused()
{
GivenGlobalSeedLimits(0.2f);
GivenCompletedTorrent("pausedUP", ratio: 0.5f, ratioLimit: 0.8f);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused()
public void should_not_be_removable_and_should_not_allow_move_files_if_max_seedingtime_reached_and_not_paused()
{
GivenMaxRatio(1.0f);
GivenGlobalSeedLimits(-1, 20);
GivenCompletedTorrent("uploading", ratio: 2.0f, seedingTime: 30);
var torrent = new QBittorrentTorrent
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_and_paused()
{
Hash = "HASH",
Name = _title,
Size = 1000,
Progress = 1.0,
Eta = 8640000,
State = "pausedUP",
Label = "",
SavePath = "",
Ratio = 1.0f
};
GivenTorrents(new List<QBittorrentTorrent> { torrent });
GivenGlobalSeedLimits(-1, 20);
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_overridden_max_seedingtime_reached_and_paused()
{
GivenGlobalSeedLimits(-1, 40);
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 20, seedingTimeLimit: 10);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
item.CanMoveFiles.Should().BeTrue();
}
[Test]
public void should_not_be_removable_if_overridden_max_seedingtime_not_reached_and_paused()
{
GivenGlobalSeedLimits(-1, 20);
GivenCompletedTorrent("pausedUP", ratio: 2.0f, seedingTime: 30, seedingTimeLimit: 40);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeFalse();
item.CanMoveFiles.Should().BeFalse();
}
[Test]
public void should_be_removable_and_should_allow_move_files_if_max_seedingtime_reached_but_ratio_not_and_paused()
{
GivenGlobalSeedLimits(2.0f, 20);
GivenCompletedTorrent("pausedUP", ratio: 1.0f, seedingTime: 30);
var item = Subject.GetItems().Single();
item.CanBeRemoved.Should().BeTrue();
@ -449,7 +560,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
public void should_get_category_from_the_category_if_set()
{
const string category = "movies-radarr";
GivenMaxRatio(1.0f);
GivenGlobalSeedLimits(1.0f);
var torrent = new QBittorrentTorrent
{
@ -474,7 +585,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
public void should_get_category_from_the_label_if_the_category_is_not_available()
{
const string category = "movies-radarr";
GivenMaxRatio(1.0f);
GivenGlobalSeedLimits(1.0f);
var torrent = new QBittorrentTorrent
{
@ -494,5 +605,32 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
var item = Subject.GetItems().Single();
item.Category.Should().Be(category);
}
[Test]
public void should_handle_eta_biginteger()
{
// Let this stand as a lesson to never write temporary unit tests on your dev machine and claim it works.
// Commit the tests and let it run with the official build on the official build agents.
// (Also don't replace library versions in your build script)
var json = "{ \"eta\": 18446744073709335000 }";
var torrent = Newtonsoft.Json.JsonConvert.DeserializeObject<QBittorrentTorrent>(json);
torrent.Eta.ToString().Should().Be("18446744073709335000");
}
[Test]
public void Test_should_force_api_version_check()
{
// Set TestConnection up to fail quick
Mocker.GetMock<IQBittorrentProxy>()
.Setup(v => v.GetApiVersion(It.IsAny<QBittorrentSettings>()))
.Returns(new Version(1, 0));
Subject.Test();
Mocker.GetMock<IQBittorrentProxySelector>()
.Verify(v => v.GetProxy(It.IsAny<QBittorrentSettings>(), true), Times.Once());
}
}
}

@ -173,14 +173,50 @@ namespace NzbDrone.Core.Test.Download
}
[Test]
public void should_not_attempt_download_if_client_isnt_configure()
public void Download_report_should_not_trigger_indexer_backoff_on_indexer_404_error()
{
Subject.DownloadReport(_parseResult);
var mock = WithUsenetClient();
mock.Setup(s => s.Download(It.IsAny<RemoteMovie>()))
.Callback<RemoteMovie>(v => {
throw new ReleaseUnavailableException(v.Release, "Error", new WebException());
});
Assert.Throws<ReleaseUnavailableException>(() => Subject.DownloadReport(_parseResult));
Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Never());
}
[Test]
public void should_not_attempt_download_if_client_isnt_configured()
{
Assert.Throws<DownloadClientUnavailableException>(() => Subject.DownloadReport(_parseResult));
Mocker.GetMock<IDownloadClient>().Verify(c => c.Download(It.IsAny<RemoteMovie>()), Times.Never());
VerifyEventNotPublished<MovieGrabbedEvent>();
}
ExceptionVerification.ExpectedWarns(1);
[Test]
public void should_attempt_download_even_if_client_is_disabled()
{
var mockUsenet = WithUsenetClient();
Mocker.GetMock<IDownloadClientStatusService>()
.Setup(v => v.GetBlockedProviders())
.Returns(new List<DownloadClientStatus>
{
new DownloadClientStatus
{
ProviderId = _downloadClients.First().Definition.Id,
DisabledTill = DateTime.UtcNow.AddHours(3)
}
});
Subject.DownloadReport(_parseResult);
Mocker.GetMock<IDownloadClientStatusService>().Verify(c => c.GetBlockedProviders(), Times.Never());
mockUsenet.Verify(c => c.Download(It.IsAny<RemoteMovie>()), Times.Once());
VerifyEventPublished<MovieGrabbedEvent>();
}
[Test]

@ -13,6 +13,7 @@ using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies;
using System.Linq;
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
@ -63,7 +64,11 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns(new List<PendingRelease>());
.Returns(_heldReleases);
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.AllByMovieId(It.IsAny<int>()))
.Returns<int>(i => _heldReleases.Where(v => v.MovieId == i).ToList());
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(It.IsAny<int>()))

@ -13,6 +13,7 @@ using NzbDrone.Core.Profiles;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies;
using System.Linq;
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
@ -23,8 +24,9 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
private Movie _movie;
private Profile _profile;
private ReleaseInfo _release;
private ParsedMovieInfo _parsedEpisodeInfo;
private RemoteMovie _remoteEpisode;
private ParsedMovieInfo _parsedMovieInfo;
private RemoteMovie _remoteMovie;
private List<PendingRelease> _heldReleases;
[SetUp]
public void Setup()
@ -48,28 +50,34 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
_release = Builder<ReleaseInfo>.CreateNew().Build();
_parsedEpisodeInfo = Builder<ParsedMovieInfo>.CreateNew().Build();
_parsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p);
_parsedMovieInfo = Builder<ParsedMovieInfo>.CreateNew().Build();
_parsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p);
_remoteEpisode = new RemoteMovie();
//_remoteEpisode.Episodes = new List<Episode>{ _episode };
_remoteEpisode.Movie = _movie;
_remoteEpisode.ParsedMovieInfo = _parsedEpisodeInfo;
_remoteEpisode.Release = _release;
_remoteMovie = new RemoteMovie();
_remoteMovie.Movie = _movie;
_remoteMovie.ParsedMovieInfo = _parsedMovieInfo;
_remoteMovie.Release = _release;
_temporarilyRejected = new DownloadDecision(_remoteEpisode, new Rejection("Temp Rejected", RejectionType.Temporary));
_temporarilyRejected = new DownloadDecision(_remoteMovie, new Rejection("Temp Rejected", RejectionType.Temporary));
_heldReleases = new List<PendingRelease>();
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns(new List<PendingRelease>());
.Returns(_heldReleases);
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.AllByMovieId(It.IsAny<int>()))
.Returns<int>(i => _heldReleases.Where(v => v.MovieId == i).ToList());
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovie(It.IsAny<int>()))
.Returns(_movie);
//Mocker.GetMock<IParsingService>()
// .Setup(s => s.GetMovie(It.IsAny<ParsedMovieInfo>(), _series.Title))
// .Returns(_episode);
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovies(It.IsAny<IEnumerable<int>>()))
.Returns(new List<Movie> { _movie });
Mocker.GetMock<IPrioritizeDownloadDecision>()
.Setup(s => s.PrioritizeDecisionsForMovies(It.IsAny<List<DownloadDecision>>()))
@ -78,27 +86,25 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
private void GivenHeldRelease(QualityModel quality)
{
var parsedEpisodeInfo = _parsedEpisodeInfo.JsonClone();
parsedEpisodeInfo.Quality = quality;
var parsedMovieInfo = _parsedMovieInfo.JsonClone();
parsedMovieInfo.Quality = quality;
var heldReleases = Builder<PendingRelease>.CreateListOfSize(1)
.All()
.With(h => h.MovieId = _movie.Id)
.With(h => h.Release = _release.JsonClone())
.With(h => h.ParsedMovieInfo = parsedEpisodeInfo)
.With(h => h.ParsedMovieInfo = parsedMovieInfo)
.Build();
Mocker.GetMock<IPendingReleaseRepository>()
.Setup(s => s.All())
.Returns(heldReleases);
_heldReleases.AddRange(heldReleases);
}
[Test]
public void should_delete_if_the_grabbed_quality_is_the_same()
{
GivenHeldRelease(_parsedEpisodeInfo.Quality);
GivenHeldRelease(_parsedMovieInfo.Quality);
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
Subject.Handle(new MovieGrabbedEvent(_remoteMovie));
VerifyDelete();
}
@ -108,7 +114,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
GivenHeldRelease(new QualityModel(Quality.SDTV));
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
Subject.Handle(new MovieGrabbedEvent(_remoteMovie));
VerifyDelete();
}
@ -118,7 +124,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
GivenHeldRelease(new QualityModel(Quality.Bluray720p));
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
Subject.Handle(new MovieGrabbedEvent(_remoteMovie));
VerifyNoDelete();
}

@ -38,6 +38,10 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
.Setup(s => s.GetMovie(It.IsAny<int>()))
.Returns(_movie);
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovies(It.IsAny<IEnumerable<int>>()))
.Returns(new List<Movie> { _movie });
Mocker.GetMock<IParsingService>()
.Setup(s => s.GetMovie(It.IsAny<string>()))
.Returns(_movie);
@ -49,7 +53,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
{
Id = id,
ParsedMovieInfo = new ParsedMovieInfo { MovieTitle = title, Year = year },
MovieId = _movie.Id,
MovieId = _movie.Id
});
}
@ -65,90 +69,6 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
AssertRemoved(1);
}
[Test]
public void should_not_remove_different_release()
{
AddPending(id: 1, title: "Movie", year: 2001);
AddPending(2, "Movie 2", 2001);
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-movie{1}", 1, _movie.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1);
}
/*[Test]
public void should_remove_multiple_releases_release()
{
AddPending(id: 1, title: "Movie", year: 2001);
AddPending(id: 2, title: "Movie", year: 2002);
AddPending(id: 3, title: "Movie", year: 2003);
AddPending(id: 4, title: "Movie", year: 2003);
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-movie{1}", 3, _movie.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(3, 4);
}
[Test]
public void should_not_remove_diffrent_season()
{
AddPending(id: 1, title: "Movie", year: 2001);
AddPending(id: 2, title: "Movie", year: 2001);
AddPending(id: 3, title: "Movie", year: 2001);
AddPending(id: 4, title: "Movie", year: 2001);
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-movie{1}", 1, _movie.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1, 2);
}
[Test]
public void should_not_remove_diffrent_episodes()
{
AddPending(id: 1, title: "Movie", year: 2001);
AddPending(id: 2, title: "Movie", year: 2001);
AddPending(id: 3, title: "Movie", year: 2001);
AddPending(id: 4, title: "Movie", year: 2001);
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-movie{1}", 1, _movie.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1, 2);
}
[Test]
public void should_not_remove_multiepisodes()
{
AddPending(id: 1, title: "Movie", year: 2001);
AddPending(id: 2, title: "Movie", year: 2001);
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-movie{1}", 1, _movie.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(1);
}
[Test]
public void should_not_remove_singleepisodes()
{
AddPending(id: 1, title: "Movie", year: 2001);
AddPending(id: 2, title: "Movie", year: 2001);
var queueId = HashConverter.GetHashInt31(string.Format("pending-{0}-movie{1}", 2, _movie.Id));
Subject.RemovePendingQueueItems(queueId);
AssertRemoved(2);
}*/
private void AssertRemoved(params int[] ids)
{
Mocker.GetMock<IPendingReleaseRepository>().Verify(c => c.DeleteMany(It.Is<IEnumerable<int>>(s => s.SequenceEqual(ids))));

@ -70,6 +70,10 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
.Setup(s => s.GetMovie(It.IsAny<int>()))
.Returns(_movie);
Mocker.GetMock<IMovieService>()
.Setup(s => s.GetMovies(It.IsAny<IEnumerable<int>>()))
.Returns(new List<Movie> { _movie });
Mocker.GetMock<IParsingService>()
.Setup(s => s.GetMovie(It.IsAny<string>()))
.Returns(_movie);

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Evolution World</title>
<description>Advanced RSS Feed for xbtitFM by Petr1fied</description>
<link>http://ew.pw</link>
<lastBuildDate>Tue, 15 Aug 2017 00:00:00 +0000</lastBuildDate>
<copyright>(c) 2017 Evolution World</copyright>
<atom:link href="http://ew.pw/advanced_rss.php?cats=34%3B35%3B36%3B37%3B38%3B39%3B41%3B48%3B49%3B50%3B51%3B79%3B80%3B81&amp;tpc=100&amp;auth=secret" rel="self" type="application/rss+xml" />
<item>
<title><![CDATA[[TVShow --> TVShow Bluray 720p] Fargo S01 Complete Season 1 720p BRRip DD5.1 x264-PSYPHER [SEEDERS (3)/LEECHERS (0)]]]></title>
<description><![CDATA[<br />Fargo S01 Complete Season 1 720p BRRip DD5.1 x264-PSYPHER<br /><br /><br /><br />Plot:<br /><br />Various chronicles of deception, intrigue and murder in and around frozen Minnesota.<br /><br />Note::-<br />Encode is tested and its perfect, no sync issue there in any episode.<br />All episodes comes with AC3 Audio for better audio and video plaback and English Subs are muxed in video .<br /><br />TECHNiCAL Information:<br /><br /><br />RUNTIME..................: 1 hr x 10<br />Total SIZE...............: 9.75 GiB<br />Total Episodes...........: 10<br />VIDEO CODEC..............: x264 2nd Pass (High,L4.1)<br />RESOLUTION...............: 1280x720<br />BITRATE (Video)..........: 2100 Kbps - 2400 kbps<br />Aspect Ratio.............: 16:9<br />Video Container..........: MKV<br />FRAMERATE................: 23.967 fps<br />AUDIO....................: English AC3 6 Channel 384 kbps<br />SUBTITLES................: English, English (SDH)<br />CHAPTERS.................: Yes<br />SOURCE...................: DON (Thanks !)<br /><br /><br />GENRE...................: Crime | Drama | Thriller<br />RATING..................: 9.1/10 from 140,765 users<br />IMDB link...............: <a href=&quot;http://www.imdb.com/title/tt2802850/&quot; target=&quot;_blank&quot;>http://www.imdb.com/title/tt2802850/</a>]]></description>
<link>http://ew.pw/index.php?page=torrent-details&amp;id=dea071a7a62a0d662538d46402fb112f30b8c9fa</link>
<guid>http://ew.pw/index.php?page=torrent-details&amp;id=dea071a7a62a0d662538d46402fb112f30b8c9fa</guid>
<enclosure url="http://ew.pw/download.php?id=dea071a7a62a0d662538d46402fb112f30b8c9fa&amp;f=Fargo%20S01%20Complete%20Season%201%20720p%20BRRip%20DD5.1%20x264-PSYPHER.torrent&amp;auth=secret" length="13625" type="application/x-bittorrent" />
<pubDate>Sun, 13 Aug 2017 22:21:43 +0000</pubDate>
</item>
<item>
<title><![CDATA[[TVShow --> TVShow Bluray 720p] American Horror Story S04 Complete Season 4 720p BRRip DD5.1 x264 - PSYPHER [SEEDERS (2)/LEECHERS (0)]]]></title>
<description><![CDATA[]]></description>
<link>http://ew.pw/index.php?page=torrent-details&amp;id=2725fe19ea2addf5aafbd523d134191b8abbb2ee</link>
<guid>http://ew.pw/index.php?page=torrent-details&amp;id=2725fe19ea2addf5aafbd523d134191b8abbb2ee</guid>
<enclosure url="http://ew.pw/download.php?id=2725fe19ea2addf5aafbd523d134191b8abbb2ee&amp;f=American%20Horror%20Story%20S04%20Complete%20Season%204%20720p%20BRRip%20DD5.1%20x264%20-%20PSYPHER.torrent&amp;auth=secret" length="16583" type="application/x-bittorrent" />
<pubDate>Fri, 28 Jul 2017 16:29:51 +0000</pubDate>
</item>
</channel>
</rss>

@ -0,0 +1,98 @@
<?xml version='1.0' encoding='UTF-8' ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>limetorrents.cc - RSS Feed</title>
<link>http://www.limetorrents.cc/</link>
<description>Latest Torrents RSS.</description>
<language>en-us</language>
<pubDate>Thu, 16 Feb 2017 05:48:36 +0200</pubDate>
<lastBuildDate>Thu, 16 Feb 2017 05:48:36 +0200</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>limetorrents.cc RSS Generator 1.1</generator>
<item>
<title>The Expanse 2x04 (720p-HDTV-x264-SVA)[VTV]</title>
<guid isPermaLink='true'>http://www.limetorrents.cc/The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]-torrent-8643587.html</guid>
<pubDate>16 Feb 2017 05:24:26 +0300</pubDate>
<category>TV shows</category>
<link>http://www.limetorrents.cc/The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]-torrent-8643587.html</link>
<size>880496711</size>
<description>
<![CDATA[
Category: <a href="http://www.limetorrents.cc/browse-torrents/TV-shows/">TV shows</a><br />
Seeds: 0<br />Leechers: 0<br />Size: 839.71 MB<br /><br /><a href="http://www.limetorrents.cc/The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]-torrent-8643587.html">More @ limetorrents.cc</a><br /> ]]>
</description>
<comments>http://www.limetorrents.cc/The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]-torrent-8643587.html</comments>
<category domain="http://www.limetorrents.cc/browse-torrents/TV shows">TV shows</category>
<enclosure url="http://itorrents.org/torrent/51C578C9823DD58F6EEA287C368ED935843D63AB.torrent?title=The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]" length="880496711" type="application/x-bittorrent" />
</item>
<item>
<title>Criminal Minds S12E13 720p HDTV x264-FLEET[PRiME]</title>
<guid isPermaLink='true'>http://www.limetorrents.cc/Criminal-Minds-S12E13-720p-HDTV-x264-FLEET[PRiME]-torrent-8643586.html</guid>
<pubDate>16 Feb 2017 05:20:49 +0300</pubDate>
<category>TV shows</category>
<link>http://www.limetorrents.cc/Criminal-Minds-S12E13-720p-HDTV-x264-FLEET[PRiME]-torrent-8643586.html</link>
<size>940818158</size>
<description>
<![CDATA[
Category: <a href="http://www.limetorrents.cc/browse-torrents/TV-shows/">TV shows</a><br />
Seeds: 0<br />Leechers: 0<br />Size: 897.23 MB<br /><br /><a href="http://www.limetorrents.cc/Criminal-Minds-S12E13-720p-HDTV-x264-FLEET[PRiME]-torrent-8643586.html">More @ limetorrents.cc</a><br /> ]]>
</description>
<comments>http://www.limetorrents.cc/Criminal-Minds-S12E13-720p-HDTV-x264-FLEET[PRiME]-torrent-8643586.html</comments>
<category domain="http://www.limetorrents.cc/browse-torrents/TV shows">TV shows</category>
<enclosure url="http://itorrents.org/torrent/C7EBCBE53A82E7C8F0826417F5174C8709DB9DC0.torrent?title=Criminal-Minds-S12E13-720p-HDTV-x264-FLEET[PRiME]" length="940818158" type="application/x-bittorrent" />
</item>
<item>
<title>Legion S01E02 720p HDTV x264-AVS[PRiME]</title>
<guid isPermaLink='true'>http://www.limetorrents.cc/Legion-S01E02-720p-HDTV-x264-AVS[PRiME]-torrent-8643585.html</guid>
<pubDate>16 Feb 2017 05:20:48 +0300</pubDate>
<category>TV shows</category>
<link>http://www.limetorrents.cc/Legion-S01E02-720p-HDTV-x264-AVS[PRiME]-torrent-8643585.html</link>
<size>1320654292</size>
<description>
<![CDATA[
Category: <a href="http://www.limetorrents.cc/browse-torrents/TV-shows/">TV shows</a><br />
Seeds: 0<br />Leechers: 0<br />Size: 1.23 GB<br /><br /><a href="http://www.limetorrents.cc/Legion-S01E02-720p-HDTV-x264-AVS[PRiME]-torrent-8643585.html">More @ limetorrents.cc</a><br /> ]]>
</description>
<comments>http://www.limetorrents.cc/Legion-S01E02-720p-HDTV-x264-AVS[PRiME]-torrent-8643585.html</comments>
<category domain="http://www.limetorrents.cc/browse-torrents/TV shows">TV shows</category>
<enclosure url="http://itorrents.org/torrent/ED2903DB3F4B3D728D2E7091C33B6F502A0FB5D4.torrent?title=Legion-S01E02-720p-HDTV-x264-AVS[PRiME]" length="1320654292" type="application/x-bittorrent" />
</item>
<item>
<title>Suits S06E14 HDTV x264-SVA[PRiME]</title>
<guid isPermaLink='true'>http://www.limetorrents.cc/Suits-S06E14-HDTV-x264-SVA[PRiME]-torrent-8643579.html</guid>
<pubDate>16 Feb 2017 05:11:58 +0300</pubDate>
<category>TV shows</category>
<link>http://www.limetorrents.cc/Suits-S06E14-HDTV-x264-SVA[PRiME]-torrent-8643579.html</link>
<size>212274667</size>
<description>
<![CDATA[
Category: <a href="http://www.limetorrents.cc/browse-torrents/TV-shows/">TV shows</a><br />
Seeds: 0<br />Leechers: 0<br />Size: 202.44 MB<br /><br /><a href="http://www.limetorrents.cc/Suits-S06E14-HDTV-x264-SVA[PRiME]-torrent-8643579.html">More @ limetorrents.cc</a><br /> ]]>
</description>
<comments>http://www.limetorrents.cc/Suits-S06E14-HDTV-x264-SVA[PRiME]-torrent-8643579.html</comments>
<category domain="http://www.limetorrents.cc/browse-torrents/TV shows">TV shows</category>
<enclosure url="http://itorrents.org/torrent/5E412B3200773684AEDBEBF9B053ED58180279DD.torrent?title=Suits-S06E14-HDTV-x264-SVA[PRiME]" length="212274667" type="application/x-bittorrent" />
</item>
<item>
<title>The Expanse S02E04 HDTV x264-SVA[PRiME]</title>
<guid isPermaLink='true'>http://www.limetorrents.cc/The-Expanse-S02E04-HDTV-x264-SVA[PRiME]-torrent-8643578.html</guid>
<pubDate>16 Feb 2017 05:11:57 +0300</pubDate>
<category>TV shows</category>
<link>http://www.limetorrents.cc/The-Expanse-S02E04-HDTV-x264-SVA[PRiME]-torrent-8643578.html</link>
<size>269445781</size>
<description>
<![CDATA[
Category: <a href="http://www.limetorrents.cc/browse-torrents/TV-shows/">TV shows</a><br />
Seeds: 0<br />Leechers: 0<br />Size: 256.96 MB<br /><br /><a href="http://www.limetorrents.cc/The-Expanse-S02E04-HDTV-x264-SVA[PRiME]-torrent-8643578.html">More @ limetorrents.cc</a><br /> ]]>
</description>
<comments>http://www.limetorrents.cc/The-Expanse-S02E04-HDTV-x264-SVA[PRiME]-torrent-8643578.html</comments>
<category domain="http://www.limetorrents.cc/browse-torrents/TV shows">TV shows</category>
<enclosure url="http://itorrents.org/torrent/7E552CD2D99E43C34FBB233E3BAF0C1ECD416C76.torrent?title=The-Expanse-S02E04-HDTV-x264-SVA[PRiME]" length="269445781" type="application/x-bittorrent" />
</item>
</channel>
</rss>

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:newznab="http://www.newznab.com/DTD/2010/feeds/attributes/" xmlns:torznab="http://torznab.com/schemas/2015/feed">
<channel>
<atom:link href="https://localhost/feed/rssx" rel="self" type="application/rss+xml" />
<title>Anime Tosho</title>
<link>https://localhost/</link>
<description>Latest releases feed</description>
<language>en-gb</language>
<ttl>30</ttl>
<lastBuildDate>Wed, 17 May 2017 20:36:06 +0000</lastBuildDate>
<newznab:response offset="0"/>
<item>
<title>[finFAGs]_Frame_Arms_Girl_07_(1280x720_TV_AAC)_[1262B6F7].mkv</title>
<pubDate>Wed, 17 May 2017 20:36:06 +0000</pubDate>
<guid isPermaLink="true">https://localhost/view/123451</guid>
<category>Anime</category>
<description><![CDATA[<strong>Total Size</strong>: 301.8 MB<br />]]></description>
<link>https://localhost/view/finfags-_frame_arms_girl_07_-1280x720_tv_aac-_-1262b6f7-mkv.123451</link>
<comments>https://localhost/view/finfags-_frame_arms_girl_07_-1280x720_tv_aac-_-1262b6f7-mkv.123451</comments>
<enclosure url="http://storage.localhost/torrents/123451.torrent" type="application/x-bittorrent" length="0" />
<source url="http://www.tokyotosho.info/details.php?id=123451">TokyoTosho</source>
<newznab:attr name="category" value="5070" />
<newznab:attr name="category" value="100001" />
<newznab:attr name="files" value="1" />
<newznab:attr name="size" value="316477946" />
<torznab:attr name="files" value="1" />
<torznab:attr name="size" value="316477946" />
<torznab:attr name="category" value="5070" />
<torznab:attr name="category" value="100001" />
<torznab:attr name="infohash" value="2d69a861bef5a9f2cdf791b7328e37b7953205e1" />
<torznab:attr name="magneturl" value="magnet:?xt=urn:btih:VU2QYN66WU7FTPXSG3TFDRXW6KTEBPBF" />
</item>
<item>
<title>[HorribleSubs] Frame Arms Girl - 07 [720p].mkv</title>
<pubDate>Mon, 15 May 2017 19:15:56 +0000</pubDate>
<guid isPermaLink="true">https://localhost/view/123452</guid>
<category>Anime</category>
<description><![CDATA[<strong>Total Size</strong>: 452.0 MB<br />]]></description>
<link>https://localhost/view/horriblesubs-frame-arms-girl-07-720p-mkv.123452</link>
<comments>https://localhost/view/horriblesubs-frame-arms-girl-07-720p-mkv.123452</comments>
<enclosure url="http://storage.localhost/torrents/123452.torrent" type="application/x-bittorrent" length="0" />
<enclosure url="http://storage.localhost/nzb/123452.nzb" type="application/x-nzb" length="0" />
<source url="http://www.tokyotosho.info/details.php?id=123452">TokyoTosho</source>
<newznab:attr name="category" value="5070" />
<newznab:attr name="category" value="100001" />
<newznab:attr name="files" value="1" />
<newznab:attr name="size" value="473987489" />
<torznab:attr name="files" value="1" />
<torznab:attr name="size" value="473987489" />
<torznab:attr name="category" value="5070" />
<torznab:attr name="category" value="100001" />
<torznab:attr name="infohash" value="bff4afebcd50c21949ed6a06323d2120c649bd82" />
<torznab:attr name="magneturl" value="magnet:?xt=urn:btih:5QK77JL7LZVIMEGKJ5VVAMMR5EEQMMSN" />
</item>
</channel>
</rss>

@ -3,7 +3,6 @@ using System.Collections.Generic;
using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
@ -26,7 +25,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
public void should_return_error_when_download_client_throws()
{
var downloadClient = Mocker.GetMock<IDownloadClient>();
downloadClient.Setup(s => s.Definition).Returns(new IndexerDefinition{Name = "Test"});
downloadClient.Setup(s => s.Definition).Returns(new DownloadClientDefinition{Name = "Test"});
downloadClient.Setup(s => s.GetItems())
.Throws<Exception>();
@ -36,8 +35,6 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
.Returns(new IDownloadClient[] { downloadClient.Object });
Subject.Check().ShouldBeError();
ExceptionVerification.ExpectedErrors(1);
}
[Test]

@ -57,13 +57,6 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{
Subject.Check().ShouldBeOk();
}
[Test]
public void should_not_return_error_when_indexer_failed_less_than_an_hour()
{
GivenIndexer(1, 0.1, 0.5);
Subject.Check().ShouldBeOk();
}
[Test]
public void should_return_warning_if_indexer_unavailable()

@ -4,6 +4,8 @@ using NUnit.Framework;
using NzbDrone.Core.History;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Languages;
using System.Collections.Generic;
namespace NzbDrone.Core.Test.HistoryTests
{
@ -20,6 +22,7 @@ namespace NzbDrone.Core.Test.HistoryTests
{
var history = Builder<History.History>.CreateNew()
.With(c => c.Quality = new QualityModel())
.With(c => c.Languages = new List<Language>())
.BuildNew();
history.Data.Add("key1", "value1");
@ -36,12 +39,14 @@ namespace NzbDrone.Core.Test.HistoryTests
{
var historyBluray = Builder<History.History>.CreateNew()
.With(c => c.Quality = new QualityModel(Quality.Bluray1080p))
.With(c => c.Languages = new List<Language> { Language.English })
.With(c => c.MovieId = 12)
.With(c => c.EventType = HistoryEventType.Grabbed)
.BuildNew();
var historyDvd = Builder<History.History>.CreateNew()
.With(c => c.Quality = new QualityModel(Quality.DVD))
.With(c => c.Languages = new List<Language> { Language.English })
.With(c => c.MovieId = 12)
.With(c => c.EventType = HistoryEventType.Grabbed)
.BuildNew();

@ -7,6 +7,7 @@ using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies;
using System.Collections.Generic;
using NzbDrone.Core.Languages;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{
@ -19,6 +20,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
var blacklist = Builder<Blacklist>.CreateNew()
.With(h => h.MovieId = new int())
.With(h => h.Quality = new QualityModel())
.With(h => h.Languages = new List<Language>())
.BuildNew();
Db.Insert(blacklist);
@ -36,6 +38,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
var blacklist = Builder<Blacklist>.CreateNew()
.With(h => h.MovieId = new int())
.With(h => h.Quality = new QualityModel())
.With(h => h.Languages = new List<Language>())
.With(b => b.MovieId = movie.Id)
.BuildNew();

@ -1,10 +1,12 @@
using FizzWare.NBuilder;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Housekeeping.Housekeepers;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Languages;
using System.Collections.Generic;
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
{
@ -31,6 +33,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
var history = Builder<History.History>.CreateNew()
.With(h => h.Quality = new QualityModel())
.With(h => h.Languages = new List<Language>())
.BuildNew();
Db.Insert(history);
@ -45,6 +48,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
var history = Builder<History.History>.CreateNew()
.With(h => h.Quality = new QualityModel())
.With(h => h.Languages = new List<Language>())
.With(h => h.MovieId = _movie.Id)
.BuildNew();
Db.Insert(history);

@ -3,6 +3,7 @@ using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Test.Framework;
@ -16,6 +17,10 @@ namespace NzbDrone.Core.Test.IndexerTests
public void SetUp()
{
_epoch = DateTime.UtcNow;
Mocker.GetMock<IRuntimeInfo>()
.SetupGet(v => v.StartTime)
.Returns(_epoch - TimeSpan.FromHours(1));
}
private void WithStatus(IndexerStatus status)
@ -29,25 +34,16 @@ namespace NzbDrone.Core.Test.IndexerTests
.Returns(new[] { status });
}
private void VerifyUpdate(bool updated = true)
private void VerifyUpdate()
{
Mocker.GetMock<IIndexerStatusRepository>()
.Verify(v => v.Upsert(It.IsAny<IndexerStatus>()), Times.Exactly(updated ? 1 : 0));
.Verify(v => v.Upsert(It.IsAny<IndexerStatus>()), Times.Once());
}
[Test]
public void should_start_backoff_on_first_failure()
private void VerifyNoUpdate()
{
WithStatus(new IndexerStatus());
Subject.RecordFailure(1);
VerifyUpdate();
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Value.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(5), 500);
Mocker.GetMock<IIndexerStatusRepository>()
.Verify(v => v.Upsert(It.IsAny<IndexerStatus>()), Times.Never());
}
[Test]
@ -70,22 +66,7 @@ namespace NzbDrone.Core.Test.IndexerTests
Subject.RecordSuccess(1);
VerifyUpdate(false);
}
[Test]
public void should_preserve_escalation_on_intermittent_success()
{
WithStatus(new IndexerStatus { MostRecentFailure = _epoch - TimeSpan.FromSeconds(4), EscalationLevel = 3 });
Subject.RecordSuccess(1);
Subject.RecordSuccess(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Value.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(15), 500);
VerifyNoUpdate();
}
}
}

@ -5,9 +5,11 @@ using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
{
@ -173,6 +175,32 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
torrentInfo.Seeders.Should().NotHaveValue();
}
[Test]
public void should_parse_recent_feed_from_LimeTorrents()
{
GivenRecentFeedResponse("TorrentRss/LimeTorrents.xml");
var releases = Subject.FetchRecent();
releases.Should().HaveCount(5);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("The Expanse 2x04 (720p-HDTV-x264-SVA)[VTV]");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("http://itorrents.org/torrent/51C578C9823DD58F6EEA287C368ED935843D63AB.torrent?title=The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]");
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
torrentInfo.CommentUrl.Should().Be("http://www.limetorrents.cc/The-Expanse-2x04-(720p-HDTV-x264-SVA)[VTV]-torrent-8643587.html");
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("16 Feb 2017 05:24:26 +0300").ToUniversalTime());
torrentInfo.Size.Should().Be(880496711);
torrentInfo.InfoHash.Should().BeNull();
torrentInfo.MagnetUrl.Should().BeNull();
torrentInfo.Peers.Should().NotHaveValue();
torrentInfo.Seeders.Should().NotHaveValue();
}
[Test]
public void should_parse_recent_feed_from_AnimeTosho_without_size()
{
@ -234,20 +262,43 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
}
[Test]
public void should_parse_recent_feed_from_DanishBits_without_description()
public void should_parse_recent_feed_from_EveolutionWorld_without_size()
{
GivenRecentFeedResponse("TorrentRss/DanishBits.xml");
var oldSettings = Subject.Definition.Settings as TorrentRssIndexerSettings;
oldSettings.AllowZeroSize = true;
Subject.Definition.Settings = oldSettings;
Subject.Definition.Settings.As<TorrentRssIndexerSettings>().AllowZeroSize = true;
GivenRecentFeedResponse("TorrentRss/EvolutionWorld.xml");
var releases = Subject.FetchRecent();
oldSettings.AllowZeroSize = false;
Subject.Definition.Settings = oldSettings;
releases.Should().HaveCount(2);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("[TVShow --> TVShow Bluray 720p] Fargo S01 Complete Season 1 720p BRRip DD5.1 x264-PSYPHER [SEEDERS (3)/LEECHERS (0)]");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("http://ew.pw/download.php?id=dea071a7a62a0d662538d46402fb112f30b8c9fa&f=Fargo%20S01%20Complete%20Season%201%20720p%20BRRip%20DD5.1%20x264-PSYPHER.torrent&auth=secret");
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2017-08-13T22:21:43Z").ToUniversalTime());
torrentInfo.Size.Should().Be(0);
torrentInfo.InfoHash.Should().BeNull();
torrentInfo.MagnetUrl.Should().BeNull();
torrentInfo.Peers.Should().NotHaveValue();
torrentInfo.Seeders.Should().NotHaveValue();
}
[Test]
public void should_record_indexer_failure_if_unsupported_feed()
{
GivenRecentFeedResponse("TorrentRss/invalid/TorrentDay_NoPubDate.xml");
Subject.FetchRecent().Should().BeEmpty();
Mocker.GetMock<IIndexerStatusService>()
.Verify(v => v.RecordFailure(It.IsAny<int>(), TimeSpan.Zero), Times.Once());
releases.Should().HaveCount(30);
ExceptionVerification.ExpectedErrors(1);
}
}
}

@ -180,6 +180,26 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
});
}
[Test]
public void should_detect_rss_settings_for_LimeTorrents()
{
_indexerSettings.AllowZeroSize = true;
GivenRecentFeedResponse("TorrentRss/LimeTorrents.xml");
var settings = Subject.Detect(_indexerSettings);
settings.ShouldBeEquivalentTo(new TorrentRssIndexerParserSettings
{
UseEZTVFormat = false,
UseEnclosureUrl = true,
UseEnclosureLength = true,
ParseSizeInDescription = false,
ParseSeedersInDescription = false,
SizeElementName = null
});
}
[Test]
public void should_detect_rss_settings_for_AlphaRatio()
{
@ -234,14 +254,11 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
}
[TestCase("BitMeTv/BitMeTv.xml")]
[TestCase("Fanzub/fanzub.xml")]
[TestCase("KickassTorrents/KickassTorrents.xml")]
[TestCase("IPTorrents/IPTorrents.xml")]
[TestCase("Newznab/newznab_nzb_su.xml")]
[TestCase("Nyaa/Nyaa.xml")]
[TestCase("Omgwtfnzbs/Omgwtfnzbs.xml")]
[TestCase("Torznab/torznab_hdaccess_net.xml")]
[TestCase("Torznab/torznab_tpb.xml")]
[TestCase("Torznab/torznab_animetosho.xml")]
public void should_detect_recent_feed(string rssXmlFile)
{
GivenRecentFeedResponse(rssXmlFile);
@ -268,9 +285,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorrentRssIndexerTests
var ex = Assert.Throws<UnsupportedFeedException>(() => Subject.Detect(_indexerSettings));
ex.Message.Should().Contain("Empty feed");
ExceptionVerification.ExpectedErrors(1);
ex.Message.Should().Contain("Rss feed must have a pubDate");
}
[TestCase("Torrentleech/Torrentleech.xml")]

@ -95,6 +95,37 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
releaseInfo.Peers.Should().Be(36724);
}
[Test]
public void should_parse_recent_feed_from_torznab_animetosho()
{
var recentFeed = ReadAllText(@"Files/Indexers/Torznab/torznab_animetosho.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(2);
releases.First().Should().BeOfType<TorrentInfo>();
var releaseInfo = releases.First() as TorrentInfo;
releaseInfo.Title.Should().Be("[finFAGs]_Frame_Arms_Girl_07_(1280x720_TV_AAC)_[1262B6F7].mkv");
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
releaseInfo.DownloadUrl.Should().Be("http://storage.localhost/torrents/123451.torrent");
releaseInfo.InfoUrl.Should().Be("https://localhost/view/finfags-_frame_arms_girl_07_-1280x720_tv_aac-_-1262b6f7-mkv.123451");
releaseInfo.CommentUrl.Should().Be("https://localhost/view/finfags-_frame_arms_girl_07_-1280x720_tv_aac-_-1262b6f7-mkv.123451");
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("Wed, 17 May 2017 20:36:06 +0000").ToUniversalTime());
releaseInfo.Size.Should().Be(316477946);
releaseInfo.TvdbId.Should().Be(0);
releaseInfo.TvRageId.Should().Be(0);
releaseInfo.InfoHash.Should().Be("2d69a861bef5a9f2cdf791b7328e37b7953205e1");
releaseInfo.Seeders.Should().BeNull();
releaseInfo.Peers.Should().BeNull();
}
[Test]
public void should_use_pagesize_reported_by_caps()
{

@ -0,0 +1,79 @@
using System.Linq;
using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Languages;
namespace NzbDrone.Core.Test.Languages
{
[TestFixture]
public class LanguageFixture : CoreTest
{
public static object[] FromIntCases =
{
new object[] {1, Language.English},
new object[] {2, Language.French},
new object[] {3, Language.Spanish},
new object[] {4, Language.German},
new object[] {5, Language.Italian},
new object[] {6, Language.Danish},
new object[] {7, Language.Dutch},
new object[] {8, Language.Japanese},
new object[] {9, Language.Icelandic},
new object[] {10, Language.Chinese},
new object[] {11, Language.Russian},
new object[] {12, Language.Polish},
new object[] {13, Language.Vietnamese},
new object[] {14, Language.Swedish},
new object[] {15, Language.Norwegian},
new object[] {16, Language.Finnish},
new object[] {17, Language.Turkish},
new object[] {18, Language.Portuguese},
new object[] {19, Language.Flemish},
new object[] {20, Language.Greek},
new object[] {21, Language.Korean},
new object[] {22, Language.Hungarian}
};
public static object[] ToIntCases =
{
new object[] {Language.English, 1},
new object[] {Language.French, 2},
new object[] {Language.Spanish, 3},
new object[] {Language.German, 4},
new object[] {Language.Italian, 5},
new object[] {Language.Danish, 6},
new object[] {Language.Dutch, 7},
new object[] {Language.Japanese, 8},
new object[] {Language.Icelandic, 9},
new object[] {Language.Chinese, 10},
new object[] {Language.Russian, 11},
new object[] {Language.Polish, 12},
new object[] {Language.Vietnamese, 13},
new object[] {Language.Swedish, 14},
new object[] {Language.Norwegian, 15},
new object[] {Language.Finnish, 16},
new object[] {Language.Turkish, 17},
new object[] {Language.Portuguese, 18},
new object[] {Language.Flemish, 19},
new object[] {Language.Greek, 20},
new object[] {Language.Korean, 21},
new object[] {Language.Hungarian, 22}
};
[Test, TestCaseSource("FromIntCases")]
public void should_be_able_to_convert_int_to_languageTypes(int source, Language expected)
{
var language = (Language)source;
language.Should().Be(expected);
}
[Test, TestCaseSource("ToIntCases")]
public void should_be_able_to_convert_languageTypes_to_int(Language source, int expected)
{
var i = (int)source;
i.Should().Be(expected);
}
}
}

@ -115,7 +115,17 @@
<Compile Include="CustomFormat\CustomFormatsFixture.cs" />
<Compile Include="CustomFormat\QualityTagFixture.cs" />
<Compile Include="Datastore\BasicRepositoryFixture.cs" />
<Compile Include="Datastore\Converters\BooleanIntConverterFixture.cs" />
<Compile Include="Datastore\Converters\CommandConverterFixture.cs" />
<Compile Include="Datastore\Converters\DoubleConverterFixture.cs" />
<Compile Include="Datastore\Converters\EnumIntConverterFixture.cs" />
<Compile Include="Datastore\Converters\GuidConverterFixture.cs" />
<Compile Include="Datastore\Converters\Int32ConverterFixture.cs" />
<Compile Include="Datastore\Converters\OsPathConverterFixture.cs" />
<Compile Include="Datastore\Converters\ProviderSettingConverterFixture.cs" />
<Compile Include="Datastore\Converters\QualityIntConverterFixture.cs" />
<Compile Include="Datastore\Converters\TimeSpanConverterFixture.cs" />
<Compile Include="Datastore\Converters\UtcConverterFixture.cs" />
<Compile Include="Datastore\DatabaseFixture.cs" />
<Compile Include="Datastore\DatabaseRelationshipFixture.cs" />
<Compile Include="Datastore\MappingExtentionFixture.cs" />
@ -167,6 +177,7 @@
<Compile Include="DiskSpace\DiskSpaceServiceFixture.cs" />
<Compile Include="Download\CompletedDownloadServiceFixture.cs" />
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
<Compile Include="Download\DownloadClientStatusServiceFixture.cs" />
<Compile Include="Download\DownloadClientTests\Blackhole\ScanWatchFolderFixture.cs" />
<Compile Include="Download\DownloadClientTests\Blackhole\TorrentBlackholeFixture.cs" />
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
@ -270,6 +281,7 @@
<Compile Include="InstrumentationTests\DatabaseTargetFixture.cs" />
<Compile Include="JobTests\JobRepositoryFixture.cs" />
<Compile Include="JobTests\TestJobs.cs" />
<Compile Include="Languages\LanguageFixture.cs" />
<Compile Include="MediaCoverTests\CoverExistsSpecificationFixture.cs" />
<Compile Include="MediaCoverTests\ImageResizerFixture.cs" />
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
@ -307,6 +319,7 @@
<Compile Include="ParserTests\ParsingServiceTests\AugmentersTests\AugmentWithReleaseInfoFixture.cs" />
<Compile Include="ParserTests\ParsingServiceTests\ParseQualityDefinitionFixture.cs" />
<Compile Include="ParserTests\RomanNumeralTests\RomanNumeralConversionFixture.cs" />
<Compile Include="Profiles\Delay\DelayProfileServiceFixture.cs" />
<Compile Include="Profiles\Qualities\QualityIndexCompareToFixture.cs" />
<Compile Include="Qualities\RevisionComparableFixture.cs" />
<Compile Include="QueueTests\QueueServiceFixture.cs" />
@ -419,6 +432,15 @@
<None Include="Files\Indexers\TorrentRss\DanishBits.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<Content Include="Files\Indexers\TorrentRss\EvolutionWorld.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Indexers\TorrentRss\LimeTorrents.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Files\Indexers\Torznab\torznab_animetosho.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="License.txt" />
<None Include="Files\Indexers\BroadcastheNet\RecentFeed.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

@ -0,0 +1,112 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Profiles.Delay
{
[TestFixture]
public class DelayProfileServiceFixture : CoreTest<DelayProfileService>
{
private List<DelayProfile> _delayProfiles;
private DelayProfile _first;
private DelayProfile _last;
[SetUp]
public void Setup()
{
_delayProfiles = Builder<DelayProfile>.CreateListOfSize(4)
.TheFirst(1)
.With(d => d.Order = int.MaxValue)
.TheNext(1)
.With(d => d.Order = 1)
.TheNext(1)
.With(d => d.Order = 2)
.TheNext(1)
.With(d => d.Order = 3)
.Build()
.ToList();
_first = _delayProfiles[1];
_last = _delayProfiles.Last();
Mocker.GetMock<IDelayProfileRepository>()
.Setup(s => s.All())
.Returns(_delayProfiles);
}
[Test]
public void should_move_to_first_if_afterId_is_null()
{
var moving = _last;
var result = Subject.Reorder(moving.Id, null).OrderBy(d => d.Order).ToList();
var moved = result.First();
moved.Id.Should().Be(moving.Id);
moved.Order.Should().Be(1);
}
[Test]
public void should_move_after_if_afterId_is_not_null()
{
var after = _first;
var moving = _last;
var result = Subject.Reorder(moving.Id, _first.Id).OrderBy(d => d.Order).ToList();
var moved = result[1];
moved.Id.Should().Be(moving.Id);
moved.Order.Should().Be(after.Order + 1);
}
[Test]
public void should_reorder_delay_profiles_that_are_after_moved()
{
var moving = _last;
var result = Subject.Reorder(moving.Id, null).OrderBy(d => d.Order).ToList();
for (int i = 1; i < result.Count; i++)
{
var delayProfile = result[i];
if (delayProfile.Id == 1)
{
delayProfile.Order.Should().Be(int.MaxValue);
}
else
{
delayProfile.Order.Should().Be(i + 1);
}
}
}
[Test]
public void should_not_change_afters_order_if_moving_was_after()
{
var after = _first;
var afterOrder = after.Order;
var moving = _last;
var result = Subject.Reorder(moving.Id, _first.Id).OrderBy(d => d.Order).ToList();
var afterMove = result.First();
afterMove.Id.Should().Be(after.Id);
afterMove.Order.Should().Be(afterOrder);
}
[Test]
public void should_change_afters_order_if_moving_was_before()
{
var after = _last;
var afterOrder = after.Order;
var moving = _first;
var result = Subject.Reorder(moving.Id, after.Id).OrderBy(d => d.Order).ToList();
var afterMove = result.Single(d => d.Id == after.Id);
afterMove.Order.Should().BeLessThan(afterOrder);
}
}
}

@ -0,0 +1,29 @@
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Newznab;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ThingiProviderTests
{
public class ProviderRepositoryFixture : DbTest<IndexerRepository, IndexerDefinition>
{
[Test]
public void should_read_write_download_provider()
{
var model = Builder<IndexerDefinition>.CreateNew().BuildNew();
var newznabSettings = Builder<NewznabSettings>.CreateNew().Build();
model.Settings = newznabSettings;
Subject.Insert(model);
var storedProvider = Subject.Single();
storedProvider.Settings.Should().BeOfType<NewznabSettings>();
var storedSetting = (NewznabSettings)storedProvider.Settings;
storedSetting.ShouldBeEquivalentTo(newznabSettings, o=>o.IncludingAllRuntimeProperties());
}
}
}

@ -0,0 +1,167 @@
using System;
using System.Linq;
using FluentAssertions;
using Moq;
using NLog;
using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.ThingiProvider.Status;
namespace NzbDrone.Core.Test.ThingiProviderTests
{
public class MockProviderStatus : ProviderStatusBase
{
}
public interface IMockProvider : IProvider
{
}
public interface IMockProviderStatusRepository : IProviderStatusRepository<MockProviderStatus>
{
}
public class MockProviderStatusService : ProviderStatusServiceBase<IMockProvider, MockProviderStatus>
{
public MockProviderStatusService(IMockProviderStatusRepository providerStatusRepository, IEventAggregator eventAggregator, IRuntimeInfo runtimeInfo, Logger logger)
: base(providerStatusRepository, eventAggregator, runtimeInfo, logger)
{
}
}
public class ProviderStatusServiceFixture : CoreTest<MockProviderStatusService>
{
private DateTime _epoch;
[SetUp]
public void SetUp()
{
_epoch = DateTime.UtcNow;
Mocker.GetMock<IRuntimeInfo>()
.SetupGet(v => v.StartTime)
.Returns(_epoch - TimeSpan.FromHours(1));
}
private void GivenRecentStartup()
{
Mocker.GetMock<IRuntimeInfo>()
.SetupGet(v => v.StartTime)
.Returns(_epoch - TimeSpan.FromMinutes(12));
}
private MockProviderStatus WithStatus(MockProviderStatus status)
{
Mocker.GetMock<IMockProviderStatusRepository>()
.Setup(v => v.FindByProviderId(1))
.Returns(status);
Mocker.GetMock<IMockProviderStatusRepository>()
.Setup(v => v.All())
.Returns(new[] { status });
return status;
}
private void VerifyUpdate()
{
Mocker.GetMock<IMockProviderStatusRepository>()
.Verify(v => v.Upsert(It.IsAny<MockProviderStatus>()), Times.Once());
}
private void VerifyNoUpdate()
{
Mocker.GetMock<IMockProviderStatusRepository>()
.Verify(v => v.Upsert(It.IsAny<MockProviderStatus>()), Times.Never());
}
[Test]
public void should_start_backoff_on_first_failure()
{
WithStatus(new MockProviderStatus());
Subject.RecordFailure(1);
VerifyUpdate();
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Value.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(5), 500);
}
[Test]
public void should_cancel_backoff_on_success()
{
WithStatus(new MockProviderStatus { EscalationLevel = 2 });
Subject.RecordSuccess(1);
VerifyUpdate();
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().BeNull();
}
[Test]
public void should_not_store_update_if_already_okay()
{
WithStatus(new MockProviderStatus { EscalationLevel = 0 });
Subject.RecordSuccess(1);
VerifyNoUpdate();
}
[Test]
public void should_preserve_escalation_on_intermittent_success()
{
WithStatus(new MockProviderStatus
{
InitialFailure = _epoch - TimeSpan.FromSeconds(20),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(4),
EscalationLevel = 3
});
Subject.RecordSuccess(1);
Subject.RecordSuccess(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
status.DisabledTill.Should().HaveValue();
status.DisabledTill.Value.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(15), 500);
}
[Test]
public void should_not_escalate_further_till_after_5_minutes_since_startup()
{
GivenRecentStartup();
var origStatus = WithStatus(new MockProviderStatus
{
InitialFailure = _epoch - TimeSpan.FromMinutes(6),
MostRecentFailure = _epoch - TimeSpan.FromSeconds(120),
EscalationLevel = 3
});
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
Subject.RecordFailure(1);
var status = Subject.GetBlockedProviders().FirstOrDefault();
status.Should().NotBeNull();
origStatus.EscalationLevel.Should().Be(3);
status.DisabledTill.Should().BeCloseTo(_epoch + TimeSpan.FromMinutes(5), 500);
}
}
}

@ -50,7 +50,7 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
title = FileNameBuilder.CleanFileName(title);
var filepath = Path.Combine(Settings.TorrentFolder, string.Format("{0}.magnet", title));
var filepath = Path.Combine(Settings.TorrentFolder, $"{title}.{Settings.MagnetFileExtension.Trim('.')}");
var fileContent = Encoding.UTF8.GetBytes(magnetLink);
using (var stream = _diskProvider.OpenWriteStream(filepath))

@ -1,4 +1,4 @@
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Housekeeping.Housekeepers
{
@ -20,7 +20,7 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
WHERE Id IN (
SELECT IndexerStatus.Id FROM IndexerStatus
LEFT OUTER JOIN Indexers
ON IndexerStatus.IndexerId = Indexers.Id
ON IndexerStatus.ProviderId = Indexers.Id
WHERE Indexers.Id IS NULL)");
}
}

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Core.Profiles.Delay
@ -14,25 +16,35 @@ namespace NzbDrone.Core.Profiles.Delay
List<DelayProfile> AllForTag(int tagId);
List<DelayProfile> AllForTags(HashSet<int> tagIds);
DelayProfile BestForTags(HashSet<int> tagIds);
List<DelayProfile> Reorder(int id, int? afterId);
}
public class DelayProfileService : IDelayProfileService
{
private readonly IDelayProfileRepository _repo;
private readonly ICached<DelayProfile> _bestForTagsCache;
public DelayProfileService(IDelayProfileRepository repo)
public DelayProfileService(IDelayProfileRepository repo, ICacheManager cacheManager)
{
_repo = repo;
_bestForTagsCache = cacheManager.GetCache<DelayProfile>(GetType(), "best");
}
public DelayProfile Add(DelayProfile profile)
{
return _repo.Insert(profile);
profile.Order = _repo.Count();
var result = _repo.Insert(profile);
_bestForTagsCache.Clear();
return result;
}
public DelayProfile Update(DelayProfile profile)
{
return _repo.Update(profile);
var result = _repo.Update(profile);
_bestForTagsCache.Clear();
return result;
}
public void Delete(int id)
@ -49,6 +61,7 @@ namespace NzbDrone.Core.Profiles.Delay
}
_repo.UpdateMany(all);
_bestForTagsCache.Clear();
}
public List<DelayProfile> All()
@ -69,13 +82,87 @@ namespace NzbDrone.Core.Profiles.Delay
public List<DelayProfile> AllForTags(HashSet<int> tagIds)
{
return _repo.All().Where(r => r.Tags.Intersect(tagIds).Any() || r.Tags.Empty()).ToList();
return All().Where(r => r.Tags.Intersect(tagIds).Any() || r.Tags.Empty()).ToList();
}
public DelayProfile BestForTags(HashSet<int> tagIds)
{
return _repo.All().Where(r => r.Tags.Intersect(tagIds).Any() || r.Tags.Empty())
var key = "-" + tagIds.Select(v => v.ToString()).Join(",");
return _bestForTagsCache.Get(key, () => FetchBestForTags(tagIds), TimeSpan.FromSeconds(30));
}
private DelayProfile FetchBestForTags(HashSet<int> tagIds)
{
return _repo.All()
.Where(r => r.Tags.Intersect(tagIds).Any() || r.Tags.Empty())
.OrderBy(d => d.Order).First();
}
public List<DelayProfile> Reorder(int id, int? afterId)
{
var all = All().OrderBy(d => d.Order)
.ToList();
var moving = all.SingleOrDefault(d => d.Id == id);
var after = afterId.HasValue ? all.SingleOrDefault(d => d.Id == afterId) : null;
if (moving == null)
{
// TODO: This should throw
return all;
}
var afterOrder = GetAfterOrder(moving, after);
var afterCount = afterOrder + 2;
var movingOrder = moving.Order;
foreach (var delayProfile in all)
{
if (delayProfile.Id == 1)
{
continue;
}
if (delayProfile.Id == id)
{
delayProfile.Order = afterOrder + 1;
}
else if (delayProfile.Id == after?.Id)
{
delayProfile.Order = afterOrder;
}
else if (delayProfile.Order > afterOrder)
{
delayProfile.Order = afterCount;
afterCount++;
}
else if (delayProfile.Order > movingOrder)
{
delayProfile.Order--;
}
}
_repo.UpdateMany(all);
return All();
}
private int GetAfterOrder(DelayProfile moving, DelayProfile after)
{
if (after == null)
{
return 0;
}
if (moving.Order < after.Order)
{
return after.Order - 1;
}
return after.Order;
}
}
}

Loading…
Cancel
Save