package net.johnewart.gearman.engine; import com.codahale.metrics.MetricRegistry; import net.johnewart.gearman.common.Job; import net.johnewart.gearman.engine.core.QueuedJob; import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; import net.johnewart.gearman.engine.factories.JobFactory; import net.johnewart.gearman.engine.queue.JobQueue; import net.johnewart.gearman.engine.queue.factories.MemoryJobQueueFactory; import org.hamcrest.core.Is; import org.joda.time.DateTime; import org.joda.time.DateTimeUtils; import org.joda.time.Seconds; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.Collection; public class JobQueueTest { private JobQueue jobQueue; private final String queueName = "delayedJobs"; private final MemoryJobQueueFactory memoryJobQueueFactory; private final MetricRegistry metricRegistry; public JobQueueTest() { metricRegistry = new MetricRegistry(); memoryJobQueueFactory = new MemoryJobQueueFactory(metricRegistry); } @Before public void initialize() throws JobQueueFactoryException { jobQueue = memoryJobQueueFactory.build(queueName); } @Test public void doesNotRunEpochJobsEarly() throws Exception { int futureSeconds = 40; Job futureJob = JobFactory.generateFutureJob(queueName, Seconds.seconds(futureSeconds)); Job normalPriorityJob = JobFactory.generateBackgroundJob(queueName); jobQueue.enqueue(futureJob); Assert.assertThat("Job Queue has one job", jobQueue.size(), Is.is(1L)); long currentMilliseconds = new DateTime().toDate().getTime(); DateTimeUtils.setCurrentMillisFixed(currentMilliseconds); Assert.assertNull("No job is polled yet", jobQueue.poll()); jobQueue.enqueue(normalPriorityJob); Assert.assertThat("After enqueuing a normal job, even after a future one, that it comes out first", jobQueue.poll(), Is.is(normalPriorityJob)); // Jump forward 10 seconds before futureSeconds DateTimeUtils.setCurrentMillisFixed(currentMilliseconds + ((futureSeconds - 10) * 1000)); Assert.assertNull("No job is polled yet when time < job time", jobQueue.poll()); // Jump forward 10 seconds beyond futureSeconds DateTimeUtils.setCurrentMillisFixed(currentMilliseconds + ((futureSeconds + 10) * 1000)); Assert.assertThat("Future job is polled from queue after the time has come", jobQueue.poll(), Is.is(futureJob)); } @Test public void runsJobsInPriorityOrder() throws Exception { Job highPriorityJob = JobFactory.generateHighPriorityBackgroundJob(queueName); Job normalPriorityJob = JobFactory.generateBackgroundJob(queueName); Job lowPriorityJob = JobFactory.generateLowPriorityBackgroundJob(queueName); jobQueue.enqueue(lowPriorityJob); jobQueue.enqueue(normalPriorityJob); jobQueue.enqueue(highPriorityJob); Assert.assertThat("Job queue has three jobs", jobQueue.size(), Is.is(3L)); Assert.assertThat("First polled job is the high priority one", jobQueue.poll(), Is.is(highPriorityJob)); Assert.assertThat("Second polled job is the normal priority job", jobQueue.poll(), Is.is(normalPriorityJob)); Assert.assertThat("Third polled job is the low priority job", jobQueue.poll(), Is.is(lowPriorityJob)); Assert.assertThat("Job queue has size == 0", jobQueue.size(), Is.is(0L)); Assert.assertNull("No job is polled when size == 0", jobQueue.poll()); } @Test public void doesNotDoubleEnqueueJobs() throws Exception { Job normalJob = JobFactory.generateBackgroundJob(queueName); jobQueue.enqueue(normalJob); jobQueue.enqueue(normalJob); Assert.assertThat("There is only one job in the queue", jobQueue.size(), Is.is(1L)); Assert.assertThat("Polled job is the enqueued job", jobQueue.poll(), Is.is(normalJob)); Assert.assertThat("Job queue has size == 0", jobQueue.size(), Is.is(0L)); Assert.assertNull("No job is polled when size == 0", jobQueue.poll()); } @Test public void correctlyReportsWhenUniqueIdInUse() throws Exception { Job normalJob = JobFactory.generateBackgroundJob(queueName); jobQueue.enqueue(normalJob); Assert.assertThat("The queue reports that the job's unique id is in use", jobQueue.uniqueIdInUse(normalJob.getUniqueID()), Is.is(true)); } @Test public void enqueuedJobsAreReturned() throws Exception { Job job; for(int i = 0; i < 10; i++) { job = JobFactory.generateBackgroundJob(queueName); jobQueue.enqueue(job); } for(int i = 0; i < 10; i++) { job = JobFactory.generateHighPriorityBackgroundJob(queueName); jobQueue.enqueue(job); } for(int i = 0; i < 10; i++) { job = JobFactory.generateLowPriorityBackgroundJob(queueName); jobQueue.enqueue(job); } Collection<QueuedJob> allJobs = jobQueue.getAllJobs(); Assert.assertThat("There are thirty jobs in the job queue as reported by getAllJobs()", allJobs.size(), Is.is(30)); } @Test public void removalBehavesCorrectly() throws Exception { Job normalJob = JobFactory.generateBackgroundJob(queueName); Job highJob = JobFactory.generateHighPriorityBackgroundJob(queueName); Job lowJob = JobFactory.generateLowPriorityBackgroundJob(queueName); jobQueue.enqueue(normalJob); jobQueue.enqueue(highJob); jobQueue.enqueue(lowJob); Assert.assertThat("There are three jobs in the queue", jobQueue.size(), Is.is(3L)); Assert.assertTrue(jobQueue.remove(highJob)); Assert.assertThat("Job queue has size == 2", jobQueue.size(), Is.is(2L)); Assert.assertFalse(jobQueue.remove(highJob)); Assert.assertThat("Job queue still has size == 2", jobQueue.size(), Is.is(2L)); Assert.assertTrue(jobQueue.remove(normalJob)); Assert.assertThat("Job queue has size == 1", jobQueue.size(), Is.is(1L)); jobQueue.remove(lowJob); Assert.assertThat("Job queue has size == 0", jobQueue.size(), Is.is(0L)); Assert.assertFalse("Removing a null job fails", jobQueue.remove(null)); } }