contacts_events-8.x-1.x-dev/commerce_advancedqueue/tests/src/Kernel/DatabaseBackendTest.php
commerce_advancedqueue/tests/src/Kernel/DatabaseBackendTest.php
<?php
namespace Drupal\Tests\commerce_advancedqueue\Kernel;
use Drupal\advancedqueue\Entity\Queue;
use Drupal\advancedqueue\Job;
use Drupal\commerce_advancedqueue\CommerceOrderJob;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\KernelTests\KernelTestBase;
/**
* Test the Commerce Order Job Database Backedn for advanced queue.
*
* @coversDefaultClass \Drupal\commerce_advancedqueue\Plugin\AdvancedQueue\Backend\CommerceOrderJobDatabaseBackend
* @group commerce_advancedqueue
*/
class DatabaseBackendTest extends KernelTestBase {
/**
* The first tested queue.
*
* @var \Drupal\advancedqueue\Entity\QueueInterface
*/
protected $firstQueue;
/**
* The second tested queue.
*
* @var \Drupal\advancedqueue\Entity\QueueInterface
*/
protected $secondQueue;
/**
* {@inheritdoc}
*/
public static $modules = [
'advancedqueue',
'commerce_advancedqueue',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installSchema('commerce_advancedqueue', ['commerce_advancedqueue_orders']);
// Override the current time to control job timestamps.
$mock_time = $this->prophesize(TimeInterface::class);
$mock_time->getCurrentTime()->willReturn(635814000);
$this->container->set('datetime.time', $mock_time->reveal());
$this->firstQueue = Queue::create([
'id' => 'first_queue',
'label' => 'First queue',
'backend' => 'database_commerce_order_job',
'backend_configuration' => [
'lease_time' => 5,
],
]);
$this->firstQueue->save();
$this->secondQueue = Queue::create([
'id' => 'second_queue',
'label' => 'Second queue',
'backend' => 'database_commerce_order_job',
'backend_configuration' => [
'lease_time' => 5,
],
]);
$this->secondQueue->save();
}
/**
* @covers ::deleteQueue
* @covers ::countJobs
* @covers ::enqueueJob
* @covers ::enqueueJobs
* @covers ::claimJob
* @covers ::onSuccess
* @covers ::onFailure
* @covers ::deleteJob
*/
public function testQueue() {
$first_job = CommerceOrderJob::create('simple', ['test' => '1'], 1);
$second_job = CommerceOrderJob::create('simple', ['test' => '2'], 2);
$third_job = CommerceOrderJob::create('simple', ['test' => '3'], 3);
$fourth_job = CommerceOrderJob::create('simple', ['test' => '4'], 4);
$this->firstQueue->getBackend()->enqueueJobs([$first_job, $third_job]);
// Confirm that the other needed fields have been populated.
$this->assertQueuedJob(1, 'first_queue', 0, $first_job);
$this->assertQueuedJob(2, 'first_queue', 0, $third_job);
// Confirm that the queue now contains two jobs.
$counts = $this->firstQueue->getBackend()->countJobs();
$this->assertEquals([Job::STATE_QUEUED => 2], array_filter($counts));
// Update the jobs to match how they'll look when claimed.
$first_job->setState(Job::STATE_PROCESSING);
$first_job->setExpiresTime(635814000 + 5);
$third_job->setExpiresTime(635814000 + 5);
$third_job->setState(Job::STATE_PROCESSING);
// Confirm that the jobs are returned in the correct order (FIFO).
$first_claimed_job = $this->firstQueue->getBackend()->claimJob();
$this->assertEquals($first_job, $first_claimed_job);
$third_claimed_job = $this->firstQueue->getBackend()->claimJob();
$this->assertEquals($third_job, $third_claimed_job);
$this->assertNull($this->firstQueue->getBackend()->claimJob());
$this->firstQueue->getBackend()->enqueueJobs([$first_job, $third_job]);
$this->secondQueue->getBackend()->enqueueJob($second_job);
$this->secondQueue->getBackend()->enqueueJob($fourth_job);
// Confirm that the other needed fields have been populated.
$this->assertQueuedJob(5, 'second_queue', 0, $second_job);
$this->assertQueuedJob(6, 'second_queue', 0, $fourth_job);
// Update the jobs to match how they'll look when claimed.
$second_job->setState(Job::STATE_PROCESSING);
$second_job->setExpiresTime(635814000 + 5);
$fourth_job->setExpiresTime(635814000 + 5);
$fourth_job->setState(Job::STATE_PROCESSING);
// Confirm that deleting the job works.
$this->secondQueue->getBackend()->deleteJob($second_job->getId());
$fourth_claimed_job = $this->secondQueue->getBackend()->claimJob();
$this->assertEquals($fourth_job, $fourth_claimed_job);
// Confirm fail -> retry -> success.
$fourth_job->setState(Job::STATE_FAILURE);
$this->secondQueue->getBackend()->onFailure($fourth_job);
$this->assertEquals(635814000, $fourth_job->getProcessedTime());
$this->assertEmpty($fourth_job->getExpiresTime());
$this->secondQueue->getBackend()->retryJob($fourth_job, 9);
$this->assertEquals(Job::STATE_QUEUED, $fourth_job->getState());
$this->assertEquals(1, $fourth_job->getNumRetries());
$this->assertEquals(635814000 + 9, $fourth_job->getAvailableTime());
$this->assertEmpty($fourth_job->getExpiresTime());
$this->rewindTime(635814010);
$fourth_job->setState(Job::STATE_PROCESSING);
$fourth_job->setExpiresTime(635814010 + 5);
$fourth_claimed_job = $this->secondQueue->getBackend()->claimJob();
$this->assertEquals($fourth_job, $fourth_claimed_job);
$fourth_job->setState(Job::STATE_SUCCESS);
$this->secondQueue->getBackend()->onSuccess($fourth_job);
$this->assertEquals(635814010, $fourth_job->getProcessedTime());
$this->assertEmpty($fourth_job->getExpiresTime());
// Confirm updated counts.
$this->secondQueue->getBackend()->enqueueJob($first_job);
$this->secondQueue->getBackend()->enqueueJob($second_job);
$counts = $this->secondQueue->getBackend()->countJobs();
$this->assertEquals([
Job::STATE_QUEUED => 2,
Job::STATE_PROCESSING => 0,
Job::STATE_SUCCESS => 1,
Job::STATE_FAILURE => 0,
], $counts);
// Confirm that deleting the queue removes the jobs.
$this->firstQueue->getBackend()->deleteQueue();
$this->assertNull($this->firstQueue->getBackend()->claimJob());
}
/**
* @covers ::enqueueJob
* @covers ::claimJob
*/
public function testFutureQueue() {
$first_job = CommerceOrderJob::create('simple', ['test' => '1'], 1);
$second_job = CommerceOrderJob::create('simple', ['test' => '2'], 2);
$this->firstQueue->getBackend()->enqueueJob($first_job, 5);
$this->firstQueue->getBackend()->enqueueJob($second_job);
$this->assertQueuedJob(1, 'first_queue', 5, $first_job);
$this->assertQueuedJob(2, 'first_queue', 0, $second_job);
// Update the job to match how it will look when claimed.
$second_job->setState(Job::STATE_PROCESSING);
$second_job->setExpiresTime(635814000 + 5);
// Confirm that the first job isn't available because of the delay.
$second_claimed_job = $this->firstQueue->getBackend()->claimJob();
$this->assertEquals($second_job, $second_claimed_job);
$this->assertNull($this->firstQueue->getBackend()->claimJob());
// Confirm that rewinding time makes the first job available.
$this->rewindTime(635814010);
$first_job->setState(Job::STATE_PROCESSING);
$first_job->setExpiresTime(635814010 + 5);
$first_claimed_job = $this->firstQueue->getBackend()->claimJob();
$this->assertEquals($first_job, $first_claimed_job);
}
/**
* @covers ::cleanupQueue
*/
public function testQueueCleanup() {
$job = CommerceOrderJob::create('simple', ['test' => '1'], 1);
$this->firstQueue->getBackend()->enqueueJob($job);
// Update the job to match how it will look when claimed.
$job->setState(Job::STATE_PROCESSING);
$job->setExpiresTime(635814000 + 5);
$claimed_job = $this->firstQueue->getBackend()->claimJob();
$this->assertEquals($job, $claimed_job);
$this->rewindTime(635814000 + 6);
$this->assertNull($this->firstQueue->getBackend()->claimJob());
// Running cleanup should expire the lease, making it possible to claim
// the job for processing again.
$this->firstQueue->getBackend()->cleanupQueue();
$job->setExpiresTime(635814000 + 6 + 5);
$claimed_job = $this->firstQueue->getBackend()->claimJob();
$this->assertEquals($job, $claimed_job);
}
/**
* @covers ::enqueueJobs
*/
public function testEnqueueJobsValidatesJob() {
$first_job = CommerceOrderJob::create('simple', ['test' => 1], 1);
$second_job = Job::create('simple', ['test' => 2]);
$this->expectException('\InvalidArgumentException');
$this->firstQueue->getBackend()->enqueueJobs([$first_job, $second_job]);
}
/**
* @covers ::retryJob
*/
public function testRetryJobValidatesJob() {
$job = Job::create('simple', ['test' => 2]);
$job->setState(Job::STATE_FAILURE);
$this->expectException('\InvalidArgumentException');
$this->firstQueue->getBackend()->retryJob($job);
}
/**
* @covers ::onSuccess
*/
public function testOnSuccessJobValidatesJob() {
$job = Job::create('simple', ['test' => 2]);
$this->expectException('\InvalidArgumentException');
$this->firstQueue->getBackend()->onSuccess($job);
}
/**
* @covers ::onFailure
*/
public function testOnFailureJobValidatesJob() {
$job = Job::create('simple', ['test' => 2]);
$this->expectException('\InvalidArgumentException');
$this->firstQueue->getBackend()->onFailure($job);
}
/**
* @covers ::countJobsForOrder
* @covers ::claimJobForOrder
*/
public function testJobForOrderMethods() {
$first_job = CommerceOrderJob::create('simple', ['test' => '1'], '1');
$second_job = CommerceOrderJob::create('simple', ['test' => '2'], '2');
$third_job = CommerceOrderJob::create('simple', ['test' => '3'], '1');
/** @var \Drupal\commerce_advancedqueue\Plugin\AdvancedQueue\Backend\CommerceOrderJobBackendInterface $backend */
$backend = $this->firstQueue->getBackend();
$backend->enqueueJobs([$first_job, $second_job, $third_job]);
// Check the total count.
$counts = $backend->countJobs();
$this->assertEquals([
Job::STATE_QUEUED => 3,
Job::STATE_PROCESSING => 0,
Job::STATE_SUCCESS => 0,
Job::STATE_FAILURE => 0,
], $counts);
// Check the order counts.
$counts = $backend->countJobsForOrder(1);
$this->assertEquals([
Job::STATE_QUEUED => 2,
Job::STATE_PROCESSING => 0,
Job::STATE_SUCCESS => 0,
Job::STATE_FAILURE => 0,
], $counts);
$counts = $backend->countJobsForOrder(2);
$this->assertEquals([
Job::STATE_QUEUED => 1,
Job::STATE_PROCESSING => 0,
Job::STATE_SUCCESS => 0,
Job::STATE_FAILURE => 0,
], $counts);
// Update the job so it will look like the retrieved version.
$second_job->setState(Job::STATE_PROCESSING);
$second_job->setExpiresTime(635814000 + 5);
// Check claiming returns the correct job, despite queue order.
$claimed_second_job = $backend->claimJobForOrder(2);
$this->assertEqual($claimed_second_job, $second_job);
// Ensure there is nothing else for that order.
$claimed_no_job = $backend->claimJobForOrder(2);
$this->assertNull($claimed_no_job);
// Mark the job as successful.
$claimed_second_job->setState(Job::STATE_SUCCESS);
$backend->onSuccess($claimed_second_job);
// Re-check the counts.
$counts = $backend->countJobsForOrder(2);
$this->assertEquals([
Job::STATE_QUEUED => 0,
Job::STATE_PROCESSING => 0,
Job::STATE_SUCCESS => 1,
Job::STATE_FAILURE => 0,
], $counts);
}
/**
* Changes the current time.
*
* @param int $new_time
* The new time.
*/
protected function rewindTime($new_time) {
$mock_time = $this->prophesize(TimeInterface::class);
$mock_time->getCurrentTime()->willReturn($new_time);
$this->container->set('datetime.time', $mock_time->reveal());
// Reload the queues so that their backends get the updated service.
$storage = $this->container->get('entity_type.manager')->getStorage('advancedqueue_queue');
$storage->resetCache(['first_queue', 'second_queue']);
$this->firstQueue = $storage->load('first_queue');
$this->secondQueue = $storage->load('second_queue');
}
/**
* Asserts that the queued job has the correct data.
*
* @param string $expected_id
* The expected job ID.
* @param string $expected_queue_id
* The expected queue ID.
* @param int $expected_delay
* The expected delay.
* @param \Drupal\commerce_advancedqueue\CommerceOrderJob $job
* The job.
*/
protected function assertQueuedJob($expected_id, $expected_queue_id, $expected_delay, CommerceOrderJob $job) {
$this->assertEquals($expected_id, $job->getId());
$this->assertEquals($expected_queue_id, $job->getQueueId());
$this->assertEquals(Job::STATE_QUEUED, $job->getState());
$this->assertEquals(635814000 + $expected_delay, $job->getAvailableTime());
}
}
