mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 12:02:35 +02:00
Fixed: Update Unit Tests for Indexers/Clients
This commit is contained in:
parent
8a9e2dc90d
commit
c76364a891
@ -4,6 +4,7 @@
|
||||
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 @@ public void Setup()
|
||||
{
|
||||
MovieId = 1234,
|
||||
Quality = new QualityModel(),
|
||||
SourceTitle = "series.title.s01e01",
|
||||
Languages = new List<Language>(),
|
||||
SourceTitle = "movie.title.1998",
|
||||
Date = DateTime.UtcNow
|
||||
};
|
||||
}
|
||||
@ -34,7 +36,7 @@ public void should_be_able_to_write_to_database()
|
||||
}
|
||||
|
||||
[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 @@ protected void GivenCompletedItem()
|
||||
.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 @@ public void completed_download_should_have_required_properties()
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeFalse();
|
||||
result.CanMoveFiles.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -137,6 +145,7 @@ public void Download_should_download_file_if_it_doesnt_exist()
|
||||
[Test]
|
||||
public void Download_should_save_magnet_if_enabled()
|
||||
{
|
||||
GivenMagnetFilePath();
|
||||
Subject.Definition.Settings.As<TorrentBlackholeSettings>().SaveMagnetFiles = true;
|
||||
|
||||
var remoteMovie = CreateRemoteMovie();
|
||||
@ -150,6 +159,25 @@ public void Download_should_save_magnet_if_enabled()
|
||||
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;
|
||||
|
||||
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_not_save_magnet_if_disabled()
|
||||
{
|
||||
|
@ -290,6 +290,24 @@ public void GetItems_should_check_share_ratio_for_moveFiles_and_remove(double ra
|
||||
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 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "0"},
|
||||
{ "size_uploaded", "0"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
@ -96,6 +97,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "size_uploaded", "100"},
|
||||
{ "speed_download", "0" }
|
||||
},
|
||||
}
|
||||
@ -119,6 +121,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "size_uploaded", "100"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
@ -142,6 +145,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "100"},
|
||||
{ "size_uploaded", "10"},
|
||||
{ "speed_download", "50" }
|
||||
}
|
||||
}
|
||||
@ -165,6 +169,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "10"},
|
||||
{ "size_uploaded", "1"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
@ -188,6 +193,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "size_uploaded", "100"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
@ -211,6 +217,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "size_uploaded", "100"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
@ -234,6 +241,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "size_uploaded", "100"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
@ -257,6 +265,7 @@ public void Setup()
|
||||
Transfer = new Dictionary<string, string>
|
||||
{
|
||||
{ "size_downloaded", "1000"},
|
||||
{ "size_uploaded", "100"},
|
||||
{ "speed_download", "0" }
|
||||
}
|
||||
}
|
||||
|
@ -168,10 +168,13 @@ public void queued_item_should_have_required_properties()
|
||||
|
||||
GivenQueue(_queued);
|
||||
GivenHistory(null);
|
||||
|
||||
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyQueued(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -185,6 +188,9 @@ public void paused_item_should_have_required_properties()
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyPaused(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -198,6 +204,25 @@ public void downloading_item_should_have_required_properties()
|
||||
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 @@ public void completed_download_should_have_required_properties()
|
||||
var result = Subject.GetItems().Single();
|
||||
|
||||
VerifyCompleted(result);
|
||||
|
||||
result.CanBeRemoved.Should().BeTrue();
|
||||
result.CanMoveFiles.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -377,6 +405,37 @@ public void should_remap_storage_if_mounted()
|
||||
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.Download;
|
||||
using NzbDrone.Core.Download.Clients.QBittorrent;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Core.Exceptions;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
{
|
||||
@ -37,8 +38,12 @@ public void Setup()
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new Byte[0]));
|
||||
|
||||
Mocker.GetMock<IQBittorrentProxy>()
|
||||
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
|
||||
.Returns(new QBittorrentPreferences());
|
||||
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
|
||||
.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,15 +100,18 @@ protected void GivenHighPriority()
|
||||
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
|
||||
});
|
||||
.Setup(s => s.GetConfig(It.IsAny<QBittorrentSettings>()))
|
||||
.Returns(new QBittorrentPreferences
|
||||
{
|
||||
RemoveOnMaxRatio = removeOnMaxRatio,
|
||||
MaxRatio = maxRatio,
|
||||
MaxRatioEnabled = maxRatio >= 0,
|
||||
MaxSeedingTime = maxSeedingTime,
|
||||
MaxSeedingTimeEnabled = maxSeedingTime >= 0
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void GivenTorrents(List<QBittorrentTorrent> torrents)
|
||||
@ -154,7 +162,7 @@ public void paused_item_should_have_required_properties()
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyPaused(item);
|
||||
item.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
item.RemainingTime.Should().NotHaveValue();
|
||||
}
|
||||
|
||||
[TestCase("pausedUP")]
|
||||
@ -162,6 +170,7 @@ public void paused_item_should_have_required_properties()
|
||||
[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 @@ public void completed_item_should_have_required_properties(string state)
|
||||
|
||||
[TestCase("queuedDL")]
|
||||
[TestCase("checkingDL")]
|
||||
[TestCase("metaDL")]
|
||||
public void queued_item_should_have_required_properties(string state)
|
||||
{
|
||||
var torrent = new QBittorrentTorrent
|
||||
@ -201,7 +211,7 @@ public void queued_item_should_have_required_properties(string state)
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyQueued(item);
|
||||
item.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
item.RemainingTime.Should().NotHaveValue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -243,7 +253,7 @@ public void stalledDL_item_should_have_required_properties()
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
VerifyWarning(item);
|
||||
item.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||
item.RemainingTime.Should().NotHaveValue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -271,6 +281,35 @@ public void Download_should_get_hash_from_magnet_url(string magnetUrl, string ex
|
||||
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 @@ public void Download_should_handle_http_redirect_to_torrent()
|
||||
[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 @@ public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio
|
||||
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 @@ public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio
|
||||
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,21 +459,8 @@ public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio
|
||||
[Test]
|
||||
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_is_not_set()
|
||||
{
|
||||
GivenMaxRatio(1.0f, false);
|
||||
|
||||
var torrent = new QBittorrentTorrent
|
||||
{
|
||||
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);
|
||||
GivenCompletedTorrent("pausedUP", ratio: 1.0f);
|
||||
|
||||
var item = Subject.GetItems().Single();
|
||||
item.CanBeRemoved.Should().BeFalse();
|
||||
@ -424,21 +470,86 @@ public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio
|
||||
[Test]
|
||||
public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached_and_paused()
|
||||
{
|
||||
GivenMaxRatio(1.0f);
|
||||
GivenGlobalSeedLimits(1.0f);
|
||||
GivenCompletedTorrent("pausedUP", ratio: 1.0f);
|
||||
|
||||
var torrent = new QBittorrentTorrent
|
||||
{
|
||||
Hash = "HASH",
|
||||
Name = _title,
|
||||
Size = 1000,
|
||||
Progress = 1.0,
|
||||
Eta = 8640000,
|
||||
State = "pausedUP",
|
||||
Label = "",
|
||||
SavePath = "",
|
||||
Ratio = 1.0f
|
||||
};
|
||||
GivenTorrents(new List<QBittorrentTorrent> { torrent });
|
||||
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_not_be_removable_and_should_not_allow_move_files_if_max_seedingtime_reached_and_not_paused()
|
||||
{
|
||||
GivenGlobalSeedLimits(-1, 20);
|
||||
GivenCompletedTorrent("uploading", ratio: 2.0f, seedingTime: 30);
|
||||
|
||||
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()
|
||||
{
|
||||
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 @@ public void should_be_removable_and_should_allow_move_files_if_max_ratio_reached
|
||||
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 @@ public void should_get_category_from_the_category_if_set()
|
||||
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 @@ public void should_get_category_from_the_label_if_the_category_is_not_available(
|
||||
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 @@ public void Download_report_should_not_trigger_indexer_backoff_on_downloadclient
|
||||
}
|
||||
|
||||
[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.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Movies;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
{
|
||||
@ -63,7 +64,11 @@ public void Setup()
|
||||
|
||||
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.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Movies;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
|
||||
{
|
||||
@ -23,8 +24,9 @@ public class RemoveGrabbedFixture : CoreTest<PendingReleaseService>
|
||||
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 @@ public void Setup()
|
||||
|
||||
_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 @@ public void Setup()
|
||||
|
||||
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 @@ public void should_delete_if_the_grabbed_quality_is_the_higher()
|
||||
{
|
||||
GivenHeldRelease(new QualityModel(Quality.SDTV));
|
||||
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteMovie));
|
||||
|
||||
VerifyDelete();
|
||||
}
|
||||
@ -118,7 +124,7 @@ public void should_not_delete_if_the_grabbed_quality_is_the_lower()
|
||||
{
|
||||
GivenHeldRelease(new QualityModel(Quality.Bluray720p));
|
||||
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteEpisode));
|
||||
Subject.Handle(new MovieGrabbedEvent(_remoteMovie));
|
||||
|
||||
VerifyNoDelete();
|
||||
}
|
||||
|
@ -38,6 +38,10 @@ public void Setup()
|
||||
.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 @@ private void AddPending(int id, string title, int year)
|
||||
{
|
||||
Id = id,
|
||||
ParsedMovieInfo = new ParsedMovieInfo { MovieTitle = title, Year = year },
|
||||
MovieId = _movie.Id,
|
||||
MovieId = _movie.Id
|
||||
});
|
||||
}
|
||||
|
||||
@ -65,90 +69,6 @@ public void should_remove_same_release()
|
||||
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))));
|
||||
|
@ -69,6 +69,10 @@ public void Setup()
|
||||
Mocker.GetMock<IMovieService>()
|
||||
.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>()))
|
||||
|
@ -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&tpc=100&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="http://www.imdb.com/title/tt2802850/" target="_blank">http://www.imdb.com/title/tt2802850/</a>]]></description>
|
||||
<link>http://ew.pw/index.php?page=torrent-details&id=dea071a7a62a0d662538d46402fb112f30b8c9fa</link>
|
||||
<guid>http://ew.pw/index.php?page=torrent-details&id=dea071a7a62a0d662538d46402fb112f30b8c9fa</guid>
|
||||
<enclosure url="http://ew.pw/download.php?id=dea071a7a62a0d662538d46402fb112f30b8c9fa&f=Fargo%20S01%20Complete%20Season%201%20720p%20BRRip%20DD5.1%20x264-PSYPHER.torrent&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&id=2725fe19ea2addf5aafbd523d134191b8abbb2ee</link>
|
||||
<guid>http://ew.pw/index.php?page=torrent-details&id=2725fe19ea2addf5aafbd523d134191b8abbb2ee</guid>
|
||||
<enclosure url="http://ew.pw/download.php?id=2725fe19ea2addf5aafbd523d134191b8abbb2ee&f=American%20Horror%20Story%20S04%20Complete%20Season%204%20720p%20BRRip%20DD5.1%20x264%20-%20PSYPHER.torrent&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 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 @@ public void should_return_warning_when_download_client_has_not_been_configured()
|
||||
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 @@ public void should_return_error_when_download_client_throws()
|
||||
.Returns(new IDownloadClient[] { downloadClient.Object });
|
||||
|
||||
Subject.Check().ShouldBeError();
|
||||
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -57,13 +57,6 @@ public void should_not_return_error_when_no_indexers()
|
||||
{
|
||||
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 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 @@ public void should_read_write_dictionary()
|
||||
{
|
||||
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 @@ public void should_get_download_history()
|
||||
{
|
||||
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.Test.Framework;
|
||||
using NzbDrone.Core.Movies;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Languages;
|
||||
|
||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
{
|
||||
@ -19,6 +20,7 @@ public void should_delete_orphaned_blacklist_items()
|
||||
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 @@ public void should_not_delete_unorphaned_blacklist_items()
|
||||
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 @@ public void should_delete_orphaned_items()
|
||||
|
||||
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 @@ public void should_not_delete_unorphaned()
|
||||
|
||||
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);
|
||||
@ -53,4 +57,4 @@ public void should_not_delete_unorphaned()
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,4 +51,4 @@ public void should_not_delete_unorphaned_indexerstatus()
|
||||
AllStoredModels.Should().Contain(h => h.ProviderId == _indexer.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
@ -11,11 +12,15 @@ namespace NzbDrone.Core.Test.IndexerTests
|
||||
public class IndexerStatusServiceFixture : CoreTest<IndexerStatusService>
|
||||
{
|
||||
private DateTime _epoch;
|
||||
|
||||
|
||||
[SetUp]
|
||||
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 @@ private void WithStatus(IndexerStatus status)
|
||||
.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 @@ public void should_not_store_update_if_already_okay()
|
||||
|
||||
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 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
|
||||
{
|
||||
@ -48,7 +50,7 @@ public void should_parse_recent_feed_from_ImmortalSeed()
|
||||
|
||||
releases.Should().HaveCount(50);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
|
||||
var torrentInfo = (TorrentInfo)releases.First();
|
||||
|
||||
torrentInfo.Title.Should().Be("Conan.2015.02.05.Jeff.Bridges.720p.HDTV.X264-CROOKS");
|
||||
@ -173,6 +175,32 @@ public void should_parse_recent_feed_from_ExtraTorrents()
|
||||
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()
|
||||
{
|
||||
@ -213,7 +241,7 @@ public void should_parse_multi_enclosure_from_AnimeTosho()
|
||||
|
||||
torrentInfo.Title.Should().Be("DAYS - 05 (1280x720 HEVC2 AAC).mkv");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("http://storage.animetosho.org/torrents/4b58360143d59a55cbd922397a3eaa378165f3ff/DAYS%20-%2005%20%281280x720%20HEVC2%20AAC%29.torrent");
|
||||
torrentInfo.DownloadUrl.Should().Be("http://storage.animetosho.org/torrents/4b58360143d59a55cbd922397a3eaa378165f3ff/DAYS%20-%2005%20%281280x720%20HEVC2%20AAC%29.torrent");
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -234,20 +262,43 @@ public void should_parse_recent_feed_from_AlphaRatio()
|
||||
}
|
||||
|
||||
[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>();
|
||||
|
||||
releases.Should().HaveCount(30);
|
||||
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());
|
||||
|
||||
ExceptionVerification.ExpectedErrors(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +180,26 @@ public void should_detect_rss_settings_for_ExtraTorrents()
|
||||
});
|
||||
}
|
||||
|
||||
[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 @@ public void should_detect_rss_settings_for_AnimeTosho_without_size()
|
||||
}
|
||||
|
||||
[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 @@ public void should_reject_recent_feed_without_pubDate(string rssXmlFile)
|
||||
|
||||
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")]
|
||||
|
@ -44,7 +44,7 @@ public void should_parse_recent_feed_from_torznab_hdaccess_net()
|
||||
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(5);
|
||||
@ -95,6 +95,37 @@ public void should_parse_recent_feed_from_torznab_tpb()
|
||||
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()
|
||||
{
|
||||
|
79
src/NzbDrone.Core.Test/Languages/LanguageFixture.cs
Normal file
79
src/NzbDrone.Core.Test/Languages/LanguageFixture.cs
Normal file
@ -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 @@ protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash
|
||||
|
||||
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 @@ public void Clean()
|
||||
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 @@ public interface IDelayProfileService
|
||||
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 @@ public void Delete(int id)
|
||||
}
|
||||
|
||||
_repo.UpdateMany(all);
|
||||
_bestForTagsCache.Clear();
|
||||
}
|
||||
|
||||
public List<DelayProfile> All()
|
||||
@ -69,13 +82,87 @@ public List<DelayProfile> AllForTag(int tagId)
|
||||
|
||||
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…
Reference in New Issue
Block a user