Split integration tests after refactoring AS runner
[MAILPOET-4274]
This commit is contained in:
committed by
Veljko V
parent
d3e2bcdf34
commit
2df7d2f686
@ -0,0 +1,21 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MailPoet\Cron\ActionScheduler;
|
||||||
|
|
||||||
|
class ActionSchedulerTestHelper {
|
||||||
|
public function getMailPoetScheduledActions(): array {
|
||||||
|
$actions = as_get_scheduled_actions([
|
||||||
|
'group' => ActionScheduler::GROUP_ID,
|
||||||
|
'status' => [\ActionScheduler_Store::STATUS_PENDING, \ActionScheduler_Store::STATUS_RUNNING],
|
||||||
|
]);
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailPoetCompleteActions(): array {
|
||||||
|
$actions = as_get_scheduled_actions([
|
||||||
|
'group' => ActionScheduler::GROUP_ID,
|
||||||
|
'status' => [\ActionScheduler_Store::STATUS_COMPLETE],
|
||||||
|
]);
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MailPoet\Cron\ActionScheduler\Actions;
|
||||||
|
|
||||||
|
use MailPoet\Cron\ActionScheduler\ActionScheduler;
|
||||||
|
use MailPoet\Cron\ActionScheduler\ActionSchedulerTestHelper;
|
||||||
|
use MailPoet\Cron\CronTrigger;
|
||||||
|
use MailPoet\Entities\ScheduledTaskEntity;
|
||||||
|
use MailPoet\Settings\SettingsController;
|
||||||
|
use MailPoet\Test\DataFactories\ScheduledTask;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../ActionSchedulerTestHelper.php';
|
||||||
|
|
||||||
|
class DaemonRunTest extends \MailPoetTest {
|
||||||
|
|
||||||
|
/** @var DaemonRun */
|
||||||
|
private $daemonRun;
|
||||||
|
|
||||||
|
/** @var ActionScheduler */
|
||||||
|
private $actionScheduler;
|
||||||
|
|
||||||
|
/** @var ActionSchedulerTestHelper */
|
||||||
|
private $actionSchedulerHelper;
|
||||||
|
|
||||||
|
public function _before(): void {
|
||||||
|
$this->daemonRun = $this->diContainer->get(DaemonRun::class);
|
||||||
|
$this->actionScheduler = $this->diContainer->get(ActionScheduler::class);
|
||||||
|
$this->cleanup();
|
||||||
|
(new ScheduledTask())->withDefaultTasks();
|
||||||
|
$this->actionSchedulerHelper = new ActionSchedulerTestHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanProcessActions(): void {
|
||||||
|
$settings = $this->diContainer->get(SettingsController::class);
|
||||||
|
$settings->set('cron_trigger.method', CronTrigger::METHOD_ACTION_SCHEDULER);
|
||||||
|
// We need configure sender so that Daemon::run doesn't fail due incomplete configuration for Mailer.
|
||||||
|
$settings->set('sender', [
|
||||||
|
'name' => 'John',
|
||||||
|
'address' => 'john@example.com',
|
||||||
|
]);
|
||||||
|
$this->daemonRun->init();
|
||||||
|
expect($this->daemonRun->getDaemonExecutionLimit())->equals(20); // Verify initial execution limit
|
||||||
|
|
||||||
|
$this->actionScheduler->scheduleRecurringAction(time() - 1, 100, DaemonRun::NAME);
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(1);
|
||||||
|
$doneActions = $this->actionSchedulerHelper->getMailPoetCompleteActions();
|
||||||
|
expect($doneActions)->count(0);
|
||||||
|
|
||||||
|
// We can't call $this->daemonRun->process directly because it ends up with wp_die();
|
||||||
|
// We must also instantiate fresh runner, because the global instance may have exhausted execution time, because it is created
|
||||||
|
// at the start of all tests
|
||||||
|
$runner = new \ActionScheduler_QueueRunner();
|
||||||
|
$runner->run();
|
||||||
|
|
||||||
|
$doneActions = $this->actionSchedulerHelper->getMailPoetCompleteActions();
|
||||||
|
expect($doneActions)->count(1);
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(0);
|
||||||
|
|
||||||
|
// Verify execution limit after run. floor(30 - some time taken by previous action) - 10s (safety execution timout margin)
|
||||||
|
expect($this->daemonRun->getDaemonExecutionLimit())->greaterThan(0);
|
||||||
|
expect($this->daemonRun->getDaemonExecutionLimit())->lessThan(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cleanup(): void {
|
||||||
|
global $wpdb;
|
||||||
|
$actionsTable = $wpdb->prefix . 'actionscheduler_actions';
|
||||||
|
$wpdb->query('TRUNCATE ' . $actionsTable);
|
||||||
|
$claimsTable = $wpdb->prefix . 'actionscheduler_claims';
|
||||||
|
$wpdb->query('TRUNCATE ' . $claimsTable);
|
||||||
|
$this->truncateEntity(ScheduledTaskEntity::class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace MailPoet\Cron\ActionScheduler\Actions;
|
||||||
|
|
||||||
|
use MailPoet\Cron\ActionScheduler\ActionScheduler;
|
||||||
|
use MailPoet\Cron\ActionScheduler\ActionSchedulerTestHelper;
|
||||||
|
use MailPoet\Cron\ActionScheduler\RemoteExecutorHandler;
|
||||||
|
use MailPoet\Cron\CronTrigger;
|
||||||
|
use MailPoet\Cron\Workers\UnsubscribeTokens;
|
||||||
|
use MailPoet\Entities\ScheduledTaskEntity;
|
||||||
|
use MailPoet\Settings\SettingsController;
|
||||||
|
use MailPoet\Test\DataFactories\ScheduledTask;
|
||||||
|
use MailPoetVendor\Carbon\Carbon;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../ActionSchedulerTestHelper.php';
|
||||||
|
|
||||||
|
class DaemonTriggerTest extends \MailPoetTest {
|
||||||
|
|
||||||
|
/** @var DaemonTrigger */
|
||||||
|
private $daemonTrigger;
|
||||||
|
|
||||||
|
/** @var ScheduledTask */
|
||||||
|
private $scheduledTaskFactory;
|
||||||
|
|
||||||
|
/** @var ActionSchedulerTestHelper */
|
||||||
|
private $actionSchedulerHelper;
|
||||||
|
|
||||||
|
public function _before(): void {
|
||||||
|
$this->daemonTrigger = $this->diContainer->get(DaemonTrigger::class);
|
||||||
|
$this->cleanup();
|
||||||
|
$this->scheduledTaskFactory = new ScheduledTask();
|
||||||
|
$this->scheduledTaskFactory->withDefaultTasks();
|
||||||
|
$this->actionSchedulerHelper = new ActionSchedulerTestHelper();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItSchedulesTriggerActionOnInit(): void {
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(0);
|
||||||
|
$this->daemonTrigger->init();
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(1);
|
||||||
|
$action = reset($actions);
|
||||||
|
$this->assertInstanceOf(\ActionScheduler_Action::class, $action);
|
||||||
|
expect($action->get_hook())->equals(DaemonTrigger::NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTriggerDoesNotTriggerAnythingIfThereAreNoJobs(): void {
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(0);
|
||||||
|
$this->daemonTrigger->process();
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTriggerUnschedulesRunJobIfThereIsNoMoreWork(): void {
|
||||||
|
$actionScheduler = $this->diContainer->get(ActionScheduler::class);
|
||||||
|
$actionScheduler->scheduleRecurringAction(time() + 60, 1, DaemonRun::NAME);
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(1);
|
||||||
|
$this->daemonTrigger->process();
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTriggerTriggerRunnerActionWhenThereIsJob(): void {
|
||||||
|
$this->diContainer->get(SettingsController::class)->set('cron_trigger.method', CronTrigger::METHOD_ACTION_SCHEDULER);
|
||||||
|
$this->createDueScheduledTask();
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(0);
|
||||||
|
$remoteExecutorHandlerMock = $this->createMock(RemoteExecutorHandler::class);
|
||||||
|
$remoteExecutorHandlerMock->expects($this->once())
|
||||||
|
->method('triggerExecutor');
|
||||||
|
$daemonTrigger = $this->getServiceWithOverrides(DaemonTrigger::class, [
|
||||||
|
'remoteExecutorHandler' => $remoteExecutorHandlerMock,
|
||||||
|
]);
|
||||||
|
$daemonTrigger->process();
|
||||||
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
|
expect($actions)->count(1);
|
||||||
|
$action = reset($actions);
|
||||||
|
$this->assertInstanceOf(\ActionScheduler_Action::class, $action);
|
||||||
|
expect($action->get_hook())->equals(DaemonRun::NAME);
|
||||||
|
$this->cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createDueScheduledTask(): void {
|
||||||
|
$date = Carbon::now()->subSecond();
|
||||||
|
$this->scheduledTaskFactory->create(UnsubscribeTokens::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cleanup(): void {
|
||||||
|
global $wpdb;
|
||||||
|
$actionsTable = $wpdb->prefix . 'actionscheduler_actions';
|
||||||
|
$wpdb->query('TRUNCATE ' . $actionsTable);
|
||||||
|
$claimsTable = $wpdb->prefix . 'actionscheduler_claims';
|
||||||
|
$wpdb->query('TRUNCATE ' . $claimsTable);
|
||||||
|
$this->truncateEntity(ScheduledTaskEntity::class);
|
||||||
|
}
|
||||||
|
}
|
@ -2,36 +2,31 @@
|
|||||||
|
|
||||||
namespace MailPoet\Cron;
|
namespace MailPoet\Cron;
|
||||||
|
|
||||||
use MailPoet\Cron\ActionScheduler\Actions\DaemonRun;
|
|
||||||
use MailPoet\Cron\ActionScheduler\Actions\DaemonTrigger;
|
use MailPoet\Cron\ActionScheduler\Actions\DaemonTrigger;
|
||||||
use MailPoet\Cron\ActionScheduler\ActionScheduler;
|
use MailPoet\Cron\ActionScheduler\ActionSchedulerTestHelper;
|
||||||
use MailPoet\Cron\Workers\UnsubscribeTokens;
|
|
||||||
use MailPoet\Entities\ScheduledTaskEntity;
|
use MailPoet\Entities\ScheduledTaskEntity;
|
||||||
use MailPoet\Settings\SettingsController;
|
|
||||||
use MailPoet\Test\DataFactories\ScheduledTask;
|
require_once __DIR__ . '/ActionScheduler/ActionSchedulerTestHelper.php';
|
||||||
use MailPoet\WP\Functions;
|
|
||||||
use MailPoetVendor\Carbon\Carbon;
|
|
||||||
|
|
||||||
class DaemonActionSchedulerRunnerTest extends \MailPoetTest {
|
class DaemonActionSchedulerRunnerTest extends \MailPoetTest {
|
||||||
|
|
||||||
/** @var DaemonActionSchedulerRunner */
|
/** @var DaemonActionSchedulerRunner */
|
||||||
private $actionSchedulerRunner;
|
private $actionSchedulerRunner;
|
||||||
|
|
||||||
/** @var ScheduledTask */
|
/** @var ActionSchedulerTestHelper */
|
||||||
private $scheduledTaskFactory;
|
private $actionSchedulerHelper;
|
||||||
|
|
||||||
public function _before(): void {
|
public function _before(): void {
|
||||||
$this->actionSchedulerRunner = $this->diContainer->get(DaemonActionSchedulerRunner::class);
|
$this->actionSchedulerRunner = $this->diContainer->get(DaemonActionSchedulerRunner::class);
|
||||||
$this->cleanup();
|
$this->cleanup();
|
||||||
$this->scheduledTaskFactory = new ScheduledTask();
|
$this->actionSchedulerHelper = new ActionSchedulerTestHelper();
|
||||||
$this->scheduledTaskFactory->withDefaultTasks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItSchedulesTriggerActionOnInit(): void {
|
public function testItSchedulesTriggerActionOnInit(): void {
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
expect($actions)->count(0);
|
expect($actions)->count(0);
|
||||||
$this->actionSchedulerRunner->init();
|
$this->actionSchedulerRunner->init();
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
expect($actions)->count(1);
|
expect($actions)->count(1);
|
||||||
$action = reset($actions);
|
$action = reset($actions);
|
||||||
$this->assertInstanceOf(\ActionScheduler_Action::class, $action);
|
$this->assertInstanceOf(\ActionScheduler_Action::class, $action);
|
||||||
@ -40,107 +35,13 @@ class DaemonActionSchedulerRunnerTest extends \MailPoetTest {
|
|||||||
|
|
||||||
public function testItDeactivateAllTasks(): void {
|
public function testItDeactivateAllTasks(): void {
|
||||||
$this->actionSchedulerRunner->init();
|
$this->actionSchedulerRunner->init();
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
expect($actions)->count(1);
|
expect($actions)->count(1);
|
||||||
$this->actionSchedulerRunner->deactivate();
|
$this->actionSchedulerRunner->deactivate();
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
$actions = $this->actionSchedulerHelper->getMailPoetScheduledActions();
|
||||||
expect($actions)->count(0);
|
expect($actions)->count(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTriggerDoesNotTriggerAnythingIfThereAreNoJobs(): void {
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(0);
|
|
||||||
$triggerAction = $this->diContainer->get(DaemonTrigger::class);
|
|
||||||
$triggerAction->process();
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTriggerUnschedulesRunJobIfThereIsNoMoreWork(): void {
|
|
||||||
$actionScheduler = $this->diContainer->get(ActionScheduler::class);
|
|
||||||
$actionScheduler->scheduleRecurringAction(time() + 60, 1, DaemonRun::NAME);
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(1);
|
|
||||||
$triggerAction = $this->diContainer->get(DaemonTrigger::class);
|
|
||||||
$triggerAction->process();
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testTriggerTriggerRunnerActionWhenThereIsJob(): void {
|
|
||||||
$this->diContainer->get(SettingsController::class)->set('cron_trigger.method', CronTrigger::METHOD_ACTION_SCHEDULER);
|
|
||||||
$this->createDueScheduledTask();
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(0);
|
|
||||||
$triggerAction = $this->diContainer->get(DaemonTrigger::class);
|
|
||||||
$triggerAction->process();
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(2);
|
|
||||||
$action = reset($actions);
|
|
||||||
$this->assertInstanceOf(\ActionScheduler_Action::class, $action);
|
|
||||||
expect($action->get_hook())->equals(DaemonRun::NAME);
|
|
||||||
$this->cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRunnerCanProcessActions(): void {
|
|
||||||
$settings = $this->diContainer->get(SettingsController::class);
|
|
||||||
$settings->set('cron_trigger.method', CronTrigger::METHOD_ACTION_SCHEDULER);
|
|
||||||
// We need configure sender so that Daemon::run doesn't fail due incomplete configuration for Mailer.
|
|
||||||
$settings->set('sender', [
|
|
||||||
'name' => 'John',
|
|
||||||
'address' => 'john@example.com',
|
|
||||||
]);
|
|
||||||
$runAction = $this->diContainer->get(DaemonRun::class);
|
|
||||||
// Activate filter for watching execution limit.
|
|
||||||
// This normally happens in DaemonActionSchedulerRunner::init but it can't be called in tests since it cause some background requests and made test flaky
|
|
||||||
$wp = $this->diContainer->get(Functions::class);
|
|
||||||
$wp->addFilter('action_scheduler_maximum_execution_time_likely_to_be_exceeded', [$runAction, 'storeRemainingExecutionLimit'], 10, 5);
|
|
||||||
expect($runAction->getDaemonExecutionLimit())->equals(20); // Verify initial execution limit
|
|
||||||
|
|
||||||
$actionScheduler = $this->diContainer->get(ActionScheduler::class);
|
|
||||||
$actionScheduler->scheduleRecurringAction(time() - 1, 100, DaemonRun::NAME);
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(1);
|
|
||||||
$doneActions = $this->getMailPoetCompleteActions();
|
|
||||||
expect($doneActions)->count(0);
|
|
||||||
|
|
||||||
// We can't call $this->actionSchedulerRunner->runActionScheduler directly because it ends up with wp_die();
|
|
||||||
// We must also instantiate fresh runner, because the global instance may have exhausted execution time, because it is created
|
|
||||||
// at the start of all tests
|
|
||||||
$runner = new \ActionScheduler_QueueRunner();
|
|
||||||
$runner->run();
|
|
||||||
|
|
||||||
$doneActions = $this->getMailPoetCompleteActions();
|
|
||||||
expect($doneActions)->count(1);
|
|
||||||
$actions = $this->getMailPoetScheduledActions();
|
|
||||||
expect($actions)->count(1);
|
|
||||||
|
|
||||||
// Verify execution limit after run. floor(30 - some time taken by previous action) - 10s (safety execution timout margin)
|
|
||||||
expect($runAction->getDaemonExecutionLimit())->greaterThan(0);
|
|
||||||
expect($runAction->getDaemonExecutionLimit())->lessThan(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getMailPoetScheduledActions(): array {
|
|
||||||
$actions = as_get_scheduled_actions([
|
|
||||||
'group' => ActionScheduler::GROUP_ID,
|
|
||||||
'status' => [\ActionScheduler_Store::STATUS_PENDING, \ActionScheduler_Store::STATUS_RUNNING],
|
|
||||||
]);
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getMailPoetCompleteActions(): array {
|
|
||||||
$actions = as_get_scheduled_actions([
|
|
||||||
'group' => ActionScheduler::GROUP_ID,
|
|
||||||
'status' => [\ActionScheduler_Store::STATUS_COMPLETE],
|
|
||||||
]);
|
|
||||||
return $actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createDueScheduledTask(): void {
|
|
||||||
$date = Carbon::now()->subSecond();
|
|
||||||
$this->scheduledTaskFactory->create(UnsubscribeTokens::TASK_TYPE, ScheduledTaskEntity::STATUS_SCHEDULED, $date);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function cleanup(): void {
|
private function cleanup(): void {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
$actionsTable = $wpdb->prefix . 'actionscheduler_actions';
|
$actionsTable = $wpdb->prefix . 'actionscheduler_actions';
|
||||||
|
Reference in New Issue
Block a user