Lidarr/NzbDrone.Core.Test/JobTests/JobControllerFixture.cs

231 lines
6.6 KiB
C#

using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using FluentAssertions;
using Moq;
using NCrunch.Framework;
using NUnit.Framework;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Jobs.Implementations;
using NzbDrone.Core.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.JobTests
{
[TestFixture]
[ExclusivelyUses("JOB_PROVIDER")]
public class JobControllerFixture : CoreTest<JobController>
{
FakeJob _fakeJob;
SlowJob _slowJob;
SlowJob2 _slowJob2;
BrokenJob _brokenJob;
DisabledJob _disabledJob;
private JobDefinition _updatedJob = null;
[SetUp]
public void Setup()
{
_fakeJob = new FakeJob();
_slowJob = new SlowJob();
_slowJob2 = new SlowJob2();
_brokenJob = new BrokenJob();
_disabledJob = new DisabledJob();
_updatedJob = null;
IEnumerable<IJob> jobs = new List<IJob> { _fakeJob, _slowJob, _slowJob2, _brokenJob, _disabledJob };
Mocker.SetConstant(jobs);
Mocker.GetMock<IJobRepository>()
.Setup(c => c.Update(It.IsAny<JobDefinition>()))
.Callback<JobDefinition>(c => _updatedJob = c);
Mocker.GetMock<IJobRepository>()
.Setup(c => c.GetDefinition(It.IsAny<Type>()))
.Returns(new JobDefinition());
}
private void GivenPendingJob(IList<JobDefinition> jobDefinition)
{
Mocker.GetMock<IJobRepository>().Setup(c => c.GetPendingJobs()).Returns(jobDefinition);
}
[TearDown]
public void TearDown()
{
Subject.Queue.Should().BeEmpty();
}
private void WaitForQueue()
{
Console.WriteLine("Waiting for queue to clear.");
var queue = Mocker.Resolve<JobController>().Queue;
while (Subject.IsProcessing)
{
Thread.Sleep(100);
}
}
[Test]
public void running_scheduled_jobs_should_updates_last_execution_time()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _fakeJob.GetType().FullName } });
Subject.EnqueueScheduled();
WaitForQueue();
_updatedJob.LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
_updatedJob.LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
_fakeJob.ExecutionCount.Should().Be(1);
}
[Test]
public void failing_scheduled_job_should_mark_job_as_failed()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _brokenJob.GetType().FullName } });
Subject.EnqueueScheduled();
WaitForQueue();
_updatedJob.LastExecution.Should().BeWithin(TimeSpan.FromSeconds(10));
_updatedJob.Success.Should().BeFalse();
_brokenJob.ExecutionCount.Should().Be(1);
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void can_run_job_again()
{
Subject.Enqueue(typeof(FakeJob));
WaitForQueue();
Subject.Enqueue(typeof(FakeJob));
WaitForQueue();
Subject.Queue.Should().BeEmpty();
_fakeJob.ExecutionCount.Should().Be(2);
}
[Test]
public void should_ignore_job_with_same_arg()
{
Subject.Enqueue(typeof(SlowJob2), 1);
Subject.Enqueue(typeof(FakeJob), 1);
Subject.Enqueue(typeof(FakeJob), 1);
WaitForQueue();
Subject.Queue.Should().BeEmpty();
_fakeJob.ExecutionCount.Should().Be(1);
ExceptionVerification.AssertNoUnexcpectedLogs();
}
[Test]
public void can_run_broken_job_again()
{
Subject.Enqueue(typeof(BrokenJob));
WaitForQueue();
Subject.Enqueue(typeof(BrokenJob));
WaitForQueue();
_brokenJob.ExecutionCount.Should().Be(2);
ExceptionVerification.ExpectedErrors(2);
}
[Test]
public void schedule_hit_should_be_ignored_if_queue_is_running()
{
Subject.Enqueue(typeof(SlowJob));
Subject.EnqueueScheduled();
WaitForQueue();
_slowJob.ExecutionCount.Should().Be(1);
_fakeJob.ExecutionCount.Should().Be(0);
}
[Test]
public void can_queue_jobs_at_the_same_time()
{
Subject.Enqueue(typeof(SlowJob));
var thread1 = new Thread(() => Subject.Enqueue(typeof(FakeJob)));
var thread2 = new Thread(() => Subject.Enqueue(typeof(FakeJob)));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
WaitForQueue();
_fakeJob.ExecutionCount.Should().Be(1);
_slowJob.ExecutionCount.Should().Be(1);
Subject.Queue.Should().BeEmpty();
}
[Test]
public void job_with_specific_target_should_not_update_status()
{
Subject.Enqueue(typeof(FakeJob), 10);
WaitForQueue();
Mocker.GetMock<IJobRepository>().Verify(c => c.Update(It.IsAny<JobDefinition>()), Times.Never());
_updatedJob.Should().BeNull();
}
[Test]
public void Item_added_to_queue_while_scheduler_runs_should_be_executed()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _slowJob.GetType().FullName } });
var jobThread = new Thread(Subject.EnqueueScheduled);
jobThread.Start();
Thread.Sleep(200);
Subject.Enqueue(typeof(DisabledJob), 12);
WaitForQueue();
_slowJob.ExecutionCount.Should().Be(1);
_disabledJob.ExecutionCount.Should().Be(1);
}
[Test]
public void trygin_to_queue_unregistered_job_should_fail()
{
Subject.Enqueue(typeof(UpdateInfoJob));
WaitForQueue();
ExceptionVerification.ExpectedErrors(1);
}
[Test]
public void scheduled_job_should_have_scheduler_as_source()
{
GivenPendingJob(new List<JobDefinition> { new JobDefinition { Type = _slowJob.GetType().FullName }, new JobDefinition { Type = _slowJob2.GetType().FullName } });
Subject.EnqueueScheduled();
Subject.Queue.Should().OnlyContain(c => c.Source == JobQueueItem.JobSourceType.Scheduler);
WaitForQueue();
}
}
}