function CronSuspendQueueDelayTest::testSuspendQueueOrder
Same name in other branches
- 10 core/tests/Drupal/Tests/Core/Cron/CronSuspendQueueDelayTest.php \Drupal\Tests\Core\Cron\CronSuspendQueueDelayTest::testSuspendQueueOrder()
Tests queues are executed in order.
If multiple queues are delayed, they must execute in order of time.
File
-
core/
tests/ Drupal/ Tests/ Core/ Cron/ CronSuspendQueueDelayTest.php, line 308
Class
- CronSuspendQueueDelayTest
- Test Cron handling of suspended queues with a delay.
Namespace
Drupal\Tests\Core\CronCode
public function testSuspendQueueOrder() : void {
[
'queueFactory' => $queueFactory,
'queueManager' => $queueManager,
'time' => $time,
] = $this->cronConstructorArguments;
$cron = $this->getMockBuilder(Cron::class)
->onlyMethods([
'usleep',
])
->setConstructorArgs($this->cronConstructorArguments)
->getMock();
$cron->expects($this->any())
->method('usleep');
$queueManager->expects($this->once())
->method('getDefinitions')
->willReturn([
'test_worker_a' => [
'id' => 'test_worker_a',
'cron' => [
'time' => 300,
],
],
'test_worker_b' => [
'id' => 'test_worker_b',
'cron' => [
'time' => 300,
],
],
'test_worker_c' => [
'id' => 'test_worker_c',
'cron' => [
'time' => 300,
],
],
'test_worker_d' => [
'id' => 'test_worker_d',
'cron' => [
'time' => 300,
],
],
]);
$queueA = $this->createMock(QueueInterface::class);
$queueB = $this->createMock(QueueInterface::class);
$queueC = $this->createMock(QueueInterface::class);
$queueD = $this->createMock(QueueInterface::class);
$queueFactory->expects($this->exactly(4))
->method('get')
->willReturnMap([
[
'test_worker_a',
FALSE,
$queueA,
],
[
'test_worker_b',
FALSE,
$queueB,
],
[
'test_worker_c',
FALSE,
$queueC,
],
[
'test_worker_d',
FALSE,
$queueD,
],
]);
$queueA->expects($this->any())
->method('claimItem')
->willReturnOnConsecutiveCalls((object) [
'data' => 'test_data_from_queue_a',
], FALSE);
$queueB->expects($this->any())
->method('claimItem')
->willReturnOnConsecutiveCalls((object) [
'data' => 'test_data_from_queue_b',
], (object) [
'data' => 'test_data_from_queue_b',
], FALSE);
$queueC->expects($this->any())
->method('claimItem')
->willReturnOnConsecutiveCalls((object) [
'data' => 'test_data_from_queue_c',
], (object) [
'data' => 'test_data_from_queue_c',
], FALSE);
$queueD->expects($this->any())
->method('claimItem')
->willReturnOnConsecutiveCalls((object) [
'data' => 'test_data_from_queue_d',
], FALSE);
// Recycle the same worker for all queues to test order sanely:
$queueManager->expects($this->any())
->method('createInstance')
->willReturnMap([
[
'test_worker_a',
[],
$this->workerA,
],
[
'test_worker_b',
[],
$this->workerA,
],
[
'test_worker_c',
[],
$this->workerA,
],
[
'test_worker_d',
[],
$this->workerA,
],
]);
$queues = [
// All queues are executed in sequence of definition:
'test_data_from_queue_a',
'test_data_from_queue_b',
'test_data_from_queue_c',
'test_data_from_queue_d',
// Queue C is executed again, and before queue B.
'test_data_from_queue_c',
// Queue B is executed again, after queue C since its delay was longer.
'test_data_from_queue_b',
];
$this->workerA
->expects($this->exactly(count($queues)))
->method('processItem')
->with($this->callback(function ($queue) use (&$queues) : bool {
return array_shift($queues) === $queue;
}))
->willReturnOnConsecutiveCalls(NULL, $this->throwException(new SuspendQueueException('', 0, NULL, 16.0)), $this->throwException(new SuspendQueueException('', 0, NULL, 8.0)), NULL, NULL, NULL);
$currentTime = 60;
$time->expects($this->any())
->method('getCurrentTime')
->willReturnCallback(function () use (&$currentTime) : int {
return (int) $currentTime;
});
$time->expects($this->any())
->method('getCurrentMicroTime')
->willReturnCallback(function () use (&$currentTime) : float {
return (double) $currentTime;
});
$delays = [
// Expect to wait for 8 seconds, then accelerate time by 4 seconds.
4,
8000000,
// SuspendQueueException requests to delay by 16 seconds, but 4 seconds
// have passed above, so there are just 12 seconds remaining:
0,
12000000,
];
$cron->expects($this->exactly(count($delays) / 2))
->method('usleep')
->with($this->callback(function (int $delay) use (&$currentTime, &$delays) : bool {
$currentTime += array_shift($delays);
return array_shift($delays) === $delay;
}));
$cron->run();
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.