You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.0 KiB
167 lines
5.0 KiB
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_than_5_minutes_for_15_min_after_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);
|
|
}
|
|
}
|
|
}
|