Implemented many unit tests.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Abel Hoogeveen 2020-05-16 19:12:22 +02:00
parent 33c81e6c18
commit 72cd7637b5
No known key found for this signature in database
GPG Key ID: 96C2234920BF4292
15 changed files with 957 additions and 66 deletions

View File

@ -15,14 +15,14 @@ steps:
- name: basetest
image: phpunit:7.3
commands:
- vendor/bin/phpunit -c test/phpunit.xml --coverage-text
- vendor/bin/phpunit -c test/phpunit.xml --coverage-php test/temp/covbase.cov
environment:
TASKSTORAGE_TYPE: DummyTaskStorage
- name: redistest
image: phpunit:7.3
commands:
- vendor/bin/phpunit -c test/phpunit.xml --coverage-text
- vendor/bin/phpunit -c test/phpunit.xml --coverage-php test/temp/covredis.cov
environment:
SUPERVISOR_TYPE: ParallelSuperVisor
TASKSTORAGE_TYPE: RedisTaskStorage

View File

@ -20,6 +20,7 @@
},
"require-dev": {
"phpunit/phpunit": "^9",
"phpunit/phpcov": "^7",
"fuzeworks/mvcr": "~1.2.0"
},
"config": {

View File

@ -36,9 +36,25 @@
namespace FuzeWorks\Async;
/**
* Interface Executor
*
*
* @todo Implement ListRunningTasks
* @package FuzeWorks\Async
*/
interface Executor
{
/**
* Executor constructor.
*
* Parameters are a unique array which can differ for each Executor.
*
* @param array $parameters
*/
public function __construct(array $parameters);
// Control methods
/**
* Start executing a task.
@ -57,16 +73,12 @@ interface Executor
* Returns the task since it makes modifications. Has to be modified in TaskStorage by SuperVisor.
*
* @param Task $task
* @return Task
* @param bool $harshly True to KILL a process
* @return Task|null Returns modified Task on success, or null if no PID is found
*/
public function stopTask(Task $task): Task;
public function stopTask(Task $task, bool $harshly = false): ?Task;
// Task info
public function getTaskRunning(Task $task): bool;
public function getTaskStats(Task $task): ?array;
public function getTaskExitCode(Task $task): ?int;
// All tasks info
public function getRunningTasks(): array;
}

View File

@ -56,22 +56,21 @@ class ShellExecutor implements Executor
* @param array $parameters
* @throws TasksException
*/
public function __construct(string $bootstrapFile, array $parameters)
public function __construct(array $parameters)
{
// Fetch workerFile
$workerFile = $parameters['workerFile'];
$this->worker = $parameters['workerFile'];
if (!file_exists($this->worker))
throw new TasksException("Could not construct ShellExecutor. ShellWorker script does not exist.");
// First determine the PHP binary
$this->binary = PHP_BINDIR . DS . 'php';
$this->bootstrapFile = $bootstrapFile;
if (!file_exists($workerFile))
throw new TasksException("Could not construct ShellExecutor. ShellWorker script does not exist.");
$this->worker = $workerFile;
$this->bootstrapFile = $parameters['bootstrapFile'];
if (!file_exists($this->bootstrapFile))
throw new TasksException("Could not construct ShellExecutor. No bootstrap file found.");
}
private function shellExec($format, array $parameters = [])
protected function shellExec($format, array $parameters = [])
{
$parameters = array_map("escapeshellarg", $parameters);
array_unshift($parameters, $format);
@ -88,15 +87,28 @@ class ShellExecutor implements Executor
// Then execute the command using the base64_encoded string of the taskID
$output = $this->shellExec($commandString, [base64_encode($task->getId())]);
$pid = intval($output[0]);
$task->setProcess(new Process($pid));
$task->addAttribute('pid', $pid);
// And finally return the task
return $task;
}
public function stopTask(Task $task): Task
public function stopTask(Task $task, bool $harshly = false): ?Task
{
// TODO: Implement stopTask() method.
// First prepare the kill command
$commandString = "kill " . ($harshly ? '-9 ' : '') . "%s";
// Fetch the process ID from the task
$pid = $task->attribute('pid');
if (is_null($pid))
return null;
// Then execute the command
$this->shellExec($commandString, [$pid]);
if (!$this->getTaskRunning($task))
$task->removeAttribute('pid');
return $task;
}
public function getTaskRunning(Task $task): bool
@ -111,13 +123,10 @@ class ShellExecutor implements Executor
$commandString = "ps -o pid,%%cpu,%%mem,state,start -p %s | sed 1d";
// First we must determine what process is used.
$process = $task->getProcess();
if (is_null($process))
$pid = $task->attribute('pid');
if (is_null($pid))
return null;
// Then using that process we determine the ProcessID
$pid = $process->getPid();
// And we execute the commandString to fetch info on the process
$output = $this->shellExec($commandString, [$pid]);
@ -141,16 +150,6 @@ class ShellExecutor implements Executor
return null;
// Finally, return the Task information
return $parts;
}
public function getTaskExitCode(Task $task): int
{
// TODO: Implement getTaskExitCode() method.
}
public function getRunningTasks(): array
{
// TODO: Implement getRunningTasks() method.
return ['pid' => (int) $parts[0], 'cpu' => (float) $parts[1], 'mem' => (float) $parts[2], 'state' => $parts[3], 'start' => $parts[4]];
}
}

View File

@ -111,6 +111,7 @@ class ParallelSuperVisor implements SuperVisor
// CANCELLED/COMPLETED: remove the task if requested to do so
elseif ($task->getStatus() === Task::COMPLETED || $task->getStatus() === Task::CANCELLED)
{
// @todo Remove old tasks automatically
}
// RUNNING: check if task is still running. If not, set result based on output
@ -216,7 +217,9 @@ class ParallelSuperVisor implements SuperVisor
$task->addRetry();
$task = $this->executor->startTask($task, true);
}
elseif ($settings['maxRetries'] <= $task->getRetries())
elseif ($settings['retryOnFail'] === true && $settings['retryPostFailures'] === true && $settings['maxRetries'] <= $task->getRetries())
$task->setStatus(Task::CANCELLED);
else
$task->setStatus(Task::CANCELLED);
}
// @todo Retry after $max_Time

View File

@ -338,6 +338,20 @@ class Task
$this->attributes[$key] = $value;
}
/**
* Remove an attribute from a Task
*
* @param string $key
* @throws TasksException
*/
public function removeAttribute(string $key)
{
if (!isset($this->attributes[$key]))
throw new TasksException("Could not remove Task '$this->taskId' attribute '$key'. Not found.");
unset($this->attributes[$key]);
}
/**
* Return the output of this task execution
*

View File

@ -0,0 +1,221 @@
<?php
/**
* FuzeWorks Async Library
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 TechFuze
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2020, TechFuze. (http://techfuze.net)
* @license https://opensource.org/licenses/MIT MIT License
*
* @link http://techfuze.net/fuzeworks
* @since Version 1.0.0
*
* @version Version 1.0.0
*/
use FuzeWorks\Async\Executors\ShellExecutor;
use FuzeWorks\Async\Task;
use FuzeWorks\Async\Tasks;
use FuzeWorks\Async\TasksException;
use FuzeWorks\Async\TaskStorage;
use PHPUnit\Framework\TestCase;
/**
* Class ShellExecutorTest
*
* @coversDefaultClass \FuzeWorks\Async\Executors\ShellExecutor
*/
class ShellExecutorTest extends TestCase
{
/**
* @var ShellExecutor
*/
private $executor;
/**
* @var TaskStorage
*/
private $taskStorage;
public function setUp(): void
{
// Load the TaskStorage so temporary tasks can be stored
// Tasks shall NOT be reset between individual tests automatically
$tasks = new Tasks();
$this->taskStorage = $tasks->getTaskStorage();
$this->taskStorage->reset();
// And load the ShellExecutor using the execution settings
$this->executor = new ShellExecutor([
'bootstrapFile' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'bootstrap.php',
'workerFile' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'worker'
]);
}
public function testClass()
{
$this->assertInstanceOf('FuzeWorks\Async\Executors\ShellExecutor', $this->executor);
}
/**
* @depends testClass
*/
public function testNoWorkerFile()
{
$this->expectException(TasksException::class);
new ShellExecutor(['bootstrapFile' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'bootstrap.php']);
}
/**
* @depends testClass
*/
public function testNoBoostrapFile()
{
$this->expectException(TasksException::class);
new ShellExecutor(['workerFile' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'worker']);
}
/**
* @depends testClass
*/
public function testInvalidWorkerFile()
{
$this->expectException(TasksException::class);
new ShellExecutor([
'bootstrapFile' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'bootstrap.php',
'workerFile' => 'not_found'
]);
}
/**
* @depends testClass
*/
public function testInvalidBootstrapFile()
{
$this->expectException(TasksException::class);
new ShellExecutor([
'bootstrapFile' => 'not_found',
'workerFile' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'worker'
]);
}
/* ---------------------------------- Writing and reading tasks ----------------------- */
/**
* @depends testClass
* @covers ::startTask
* @covers ::getTaskRunning
*/
public function testStartAndReadTasks()
{
// First we create a dummy task
$dummyTask = new Task('testStartAndReadTasks', 'Mock\Handlers\TestStartAndReadTasksHandler');
// Then we write this task to the TaskStorage
$this->taskStorage->addTask($dummyTask);
// Assert that no PID exists yet
$this->assertNull($dummyTask->attribute('pid'));
// Then we fire the task
$task = $this->executor->startTask($dummyTask);
// Assert that the output is the same
$this->assertSame($dummyTask, $task);
// Also assert that a PID has been added
$this->assertIsInt($task->attribute('pid'));
// Also assert that the task is currently running
$this->assertTrue($this->executor->getTaskRunning($task));
}
/**
* @depends testStartAndReadTasks
*/
public function testGetStats()
{
// First we create a dummy task, using the previous handler since nothing changes
$dummyTask = new Task('testGetStats', 'Mock\Handlers\TestStartAndReadTasksHandler');
// Then we write this task to the TaskStorage
$this->taskStorage->addTask($dummyTask);
// Then we start the task
$dummyTask = $this->executor->startTask($dummyTask);
// And we fetch some task statistics
$stats = $this->executor->getTaskStats($dummyTask);
// Assert some assumptions
$this->assertNotNull($stats);
$this->assertIsInt($stats['pid']);
$this->assertIsFloat($stats['cpu']);
$this->assertIsFloat($stats['mem']);
$this->assertIsString($stats['state']);
$this->assertIsString($stats['start']);
}
/**
* @depends testGetStats
*/
public function testGetStatsNotExist()
{
// First we create a dummy task, using the previous handler since nothing changes
$dummyTask = new Task('testGetStatsNotExist', 'none');
// And add a fake PID, since otherwise it will immediately fail
$dummyTask->addAttribute('pid', 1005);
// Then we fetch the process details
$this->assertNull($this->executor->getTaskStats($dummyTask));
}
/**
* @depends testStartAndReadTasks
*/
public function testStopTask()
{
// First we create a dummy task
$dummyTask = new Task('testStopTask', 'Mock\Handlers\TestStopTaskHandler');
// Then we write this task to the TaskStorage
$this->taskStorage->addTask($dummyTask);
// First we start the task and confirm its running
$dummyTask = $this->executor->startTask($dummyTask);
$this->assertTrue($this->executor->getTaskRunning($dummyTask));
// But then we try and stop it
$output = $this->executor->stopTask($dummyTask);
// We check that the output actually is the task
$this->assertSame($dummyTask, $output);
// And check if the Task has actually stopped now
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
}
}

View File

@ -41,6 +41,9 @@ use FuzeWorks\Async\TaskStorage;
use FuzeWorks\Async\TaskStorage\DummyTaskStorage;
use PHPUnit\Framework\TestCase;
/**
* Class TaskStorageTest
*/
class TaskStorageTest extends TestCase
{

View File

@ -151,6 +151,14 @@ class TaskTest extends TestCase
// Now add it and test if it is there
$dummyTask->addAttribute('testKey', 'SomeContent');
$this->assertEquals('SomeContent', $dummyTask->attribute('testKey'));
// Remove attribute
$dummyTask->removeAttribute('testKey');
$this->assertNull($dummyTask->attribute('testKey'));
// Remove attribute not found
$this->expectException(TasksException::class);
$dummyTask->removeAttribute('NotExistant');
}
/**

View File

@ -36,7 +36,7 @@
require_once(dirname(__DIR__) . '/vendor/autoload.php');
use FuzeWorks\Logger;
use FuzeWorks\Core;
use FuzeWorks\Priority;
// Open configurator
@ -55,7 +55,8 @@ $configurator->deferComponentClassMethod('libraries', 'addLibraryClass', null, '
// Add test directory so that config.tasks.php can be loaded
$configurator->addDirectory(dirname(__FILE__), 'config', Priority::HIGH);
// Add mock directory for tests and other classes
Core::addAutoloadMap('\Mock', dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mock');
// Create container
$container = $configurator->createContainer();
Logger::enableScreenLog();
return $container;
return $configurator->createContainer();

View File

@ -0,0 +1,85 @@
<?php
/**
* FuzeWorks Async Library
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 TechFuze
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2020, TechFuze. (http://techfuze.net)
* @license https://opensource.org/licenses/MIT MIT License
*
* @link http://techfuze.net/fuzeworks
* @since Version 1.0.0
*
* @version Version 1.0.0
*/
namespace Mock\Handlers;
use FuzeWorks\Async\Handler;
use FuzeWorks\Async\Task;
class ArgumentedHandler implements Handler
{
private $output;
private $sleeptime;
/**
* @inheritDoc
*/
public function primaryHandler(Task $task): bool
{
$arguments = $task->getArguments();
$this->sleeptime = $arguments[0];
$this->output = $arguments[1];
sleep($this->sleeptime);
return true;
}
/**
* @inheritDoc
*/
public function getOutput()
{
return $this->output;
}
/**
* @inheritDoc
*/
public function postHandler(Task $task)
{
sleep($this->sleeptime);
return true;
}
/**
* @inheritDoc
*/
public function getPostOutput()
{
return $this->output;
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* FuzeWorks Async Library
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 TechFuze
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2020, TechFuze. (http://techfuze.net)
* @license https://opensource.org/licenses/MIT MIT License
*
* @link http://techfuze.net/fuzeworks
* @since Version 1.0.0
*
* @version Version 1.0.0
*/
namespace Mock\Handlers;
use FuzeWorks\Async\Handler;
use FuzeWorks\Async\Task;
class TestStartAndReadTasksHandler implements Handler
{
/**
* @inheritDoc
*/
public function primaryHandler(Task $task): bool
{
sleep(2);
return true;
}
/**
* @inheritDoc
*/
public function getOutput()
{
return "Valid Output";
}
/**
* @inheritDoc
*/
public function postHandler(Task $task)
{
}
/**
* @inheritDoc
*/
public function getPostOutput()
{
}
}

View File

@ -34,40 +34,43 @@
* @version Version 1.0.0
*/
namespace FuzeWorks\Async;
class Process
namespace Mock\Handlers;
use FuzeWorks\Async\Handler;
use FuzeWorks\Async\Task;
class TestStopTaskHandler implements Handler
{
const PENDING = 1;
const RUNNING = 2;
const FAILED = 3;
const FINISHED = 4;
/**
* The current status of the process
*
* @var int
* @inheritDoc
*/
protected $status = Process::PENDING;
/**
* @var int
*/
protected $pid;
public function __construct(int $pid)
public function primaryHandler(Task $task): bool
{
$this->pid = $pid;
sleep(30);
return true;
}
/**
* Receive the process Id of this process
*
* @return int
* @inheritDoc
*/
public function getPid(): int
public function getOutput()
{
return $this->pid;
return "Valid Output";
}
/**
* @inheritDoc
*/
public function postHandler(Task $task)
{
}
/**
* @inheritDoc
*/
public function getPostOutput()
{
}
}

View File

@ -12,6 +12,7 @@
<testsuites>
<testsuite name="Base Functionality">
<directory>./base/</directory>
<directory>./system/</directory>
</testsuite>
</testsuites>

View File

@ -0,0 +1,464 @@
<?php
/**
* FuzeWorks Async Library
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 TechFuze
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author TechFuze
* @copyright Copyright (c) 2013 - 2020, TechFuze. (http://techfuze.net)
* @license https://opensource.org/licenses/MIT MIT License
*
* @link http://techfuze.net/fuzeworks
* @since Version 1.0.0
*
* @version Version 1.0.0
*/
use FuzeWorks\Async\Constraint\FixedTimeConstraint;
use FuzeWorks\Async\Executors\ShellExecutor;
use FuzeWorks\Async\SuperVisor;
use FuzeWorks\Async\Supervisors\ParallelSuperVisor;
use FuzeWorks\Async\Task;
use FuzeWorks\Async\Tasks;
use FuzeWorks\Async\TaskStorage;
use PHPUnit\Framework\TestCase;
class ParallelSuperVisorTest extends TestCase
{
/**
* @var ShellExecutor
*/
private $executor;
/**
* @var TaskStorage
*/
private $taskStorage;
/**
* @var ParallelSuperVisor
*/
private $superVisor;
public function setUp(): void
{
// Load the TaskStorage so temporary tasks can be stored
// Tasks shall NOT be reset between individual tests automatically
$tasks = new Tasks();
$this->taskStorage = $tasks->getTaskStorage();
$this->taskStorage->reset();
// And load the ShellExecutor using the execution settings
$this->executor = new ShellExecutor([
'bootstrapFile' => dirname(__DIR__) . DIRECTORY_SEPARATOR,
'workerFile' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'worker'
]);
$this->superVisor = new ParallelSuperVisor($this->taskStorage, $this->executor, ['outstream' => null]);
}
public function testClass()
{
$this->assertInstanceOf('FuzeWorks\Async\Supervisors\ParallelSuperVisor', $this->superVisor);
}
/* ---------------------------------- Writing and reading tasks ----------------------- */
/**
* @depends testClass
*/
public function testEmptyCycle()
{
$this->assertEquals(SuperVisor::FINISHED, $this->superVisor->cycle());
}
public function testToRunning()
{
// First create a dummy task
$dummyTask = new Task('testToRunning', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Write the dummy to TaskStorage
$this->taskStorage->addTask($dummyTask);
// Assert that the status is PENDING and not running
$this->assertEquals(Task::PENDING, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it is running for real
$this->assertEquals(Task::RUNNING, $dummyTask->getStatus());
$this->assertTrue($this->executor->getTaskRunning($dummyTask));
}
/**
* @depends testToRunning
*/
public function testConstrainedPending()
{
// First create a dummy task
$dummyTask = new Task('testConstrainedPending', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Add a constraint
$dummyTask->addConstraint(new FixedTimeConstraint(time() + 3600));
// Write the dummy to TaskStorage
$this->taskStorage->addTask($dummyTask);
// Assert that the status is PENDING and not running
$this->assertEquals(Task::PENDING, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it is delayed
$this->assertEquals(Task::DELAYED, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
}
/**
* @depends testToRunning
*/
public function testChangeDelayedToPending()
{
// First create a dummy task
$dummyTask = new Task('testChangeDelayedToPending', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set to delayed and set to NOW
$dummyTask->setStatus(Task::DELAYED);
$dummyTask->setDelayTime(time() - 3600);
// Write the dummy to TaskStorage
$this->taskStorage->addTask($dummyTask);
// Assert that the status is DELAYED and not running
$this->assertEquals(Task::DELAYED, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it is delayed
$this->assertEquals(Task::PENDING, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
}
/**
* @depends testToRunning
*/
public function testKeepDelayed()
{
// First create a dummy task
$dummyTask = new Task('testKeepDelayed', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set to delayed and set to NOW
$dummyTask->setStatus(Task::DELAYED);
$dummyTask->setDelayTime(time() + 3600);
// Write the dummy to TaskStorage
$this->taskStorage->addTask($dummyTask);
// Assert that the status is DELAYED and not running
$this->assertEquals(Task::DELAYED, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it is delayed
$this->assertEquals(Task::DELAYED, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
}
/**
* @depends testToRunning
*/
public function testFinishedTask()
{
// First create a dummy task
$dummyTask = new Task('testFinishedTask', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set status to running
$dummyTask->setStatus(Task::RUNNING);
$dummyTask->addAttribute('pid', 1005);
// Write the dummy and some output to TaskStorage
$this->taskStorage->addTask($dummyTask);
$this->taskStorage->writeTaskOutput($dummyTask, 'Some Output', '', Task::SUCCESS);
// Test if everything is set
$this->assertEquals(Task::RUNNING, $dummyTask->getStatus());
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it is finished indeed
$this->assertEquals(Task::SUCCESS, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
$this->assertEquals('Some Output', $dummyTask->getOutput());
}
/**
* @depends testFinishedTask
*/
public function testMissingTask()
{
// First create a dummy task
$dummyTask = new Task('testMissingTask', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set status to running
$dummyTask->setStatus(Task::RUNNING);
$dummyTask->addAttribute('pid', 1006);
// Write the dummy and no output to TaskStorage
$this->taskStorage->addTask($dummyTask);
// Test if everything is set
$this->assertEquals(Task::RUNNING, $dummyTask->getStatus());
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it has failed indeed
$this->assertEquals(Task::PFAILED, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
}
/**
* @depends testFinishedTask
*/
public function testFailedTask()
{
// First create a dummy task
$dummyTask = new Task('testFailedTask', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set status to running
$dummyTask->setStatus(Task::RUNNING);
$dummyTask->addAttribute('pid', 1007);
// Write the dummy and some output to TaskStorage
$this->taskStorage->addTask($dummyTask);
$this->taskStorage->writeTaskOutput($dummyTask, 'Some Output', 'Some Errors', Task::FAILED);
// Test if everything is set
$this->assertEquals(Task::RUNNING, $dummyTask->getStatus());
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Then re-fetch the Task
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
// And check that it is finished indeed
$this->assertEquals(Task::FAILED, $dummyTask->getStatus());
$this->assertFalse($this->executor->getTaskRunning($dummyTask));
$this->assertEquals('Some Errors', $dummyTask->getErrors());
}
/**
* @depends testFailedTask
*/
public function testRetryFailedTask()
{
// First create the dummy tasks
$dummyTaskFailedYes = new Task('testRetryFailedTaskY', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
$dummyTaskPFailedYes = new Task('testRetryFailedTaskPY', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
$dummyTaskFailedNo = new Task('testRetryFailedTaskN', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
$dummyTaskPFailedNo = new Task('testRetryFailedTaskPN', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set statuses
$dummyTaskFailedYes->setStatus(Task::FAILED);
$dummyTaskPFailedYes->setStatus(Task::PFAILED);
$dummyTaskFailedNo->setStatus(Task::FAILED);
$dummyTaskPFailedNo->setStatus(Task::FAILED);
// Set retry settings
$dummyTaskFailedYes->setRetrySettings(true, 5, true, true,true);
$dummyTaskPFailedYes->setRetrySettings(true, 5, true, true,true);
$dummyTaskFailedNo->setRetrySettings(true, 5, false, false,true);
$dummyTaskPFailedNo->setRetrySettings(true, 5, false, false,true);
// Save all these tasks
$this->taskStorage->addTask($dummyTaskFailedYes);
$this->taskStorage->addTask($dummyTaskPFailedYes);
$this->taskStorage->addTask($dummyTaskFailedNo);
$this->taskStorage->addTask($dummyTaskPFailedNo);
// Then cycle the SuperVisor
$this->superVisor->cycle();
// Reload all tasks from TaskStorage
$dummyTaskFailedYes = $this->taskStorage->getTaskById($dummyTaskFailedYes->getId());
$dummyTaskPFailedYes = $this->taskStorage->getTaskById($dummyTaskPFailedYes->getId());
$dummyTaskFailedNo = $this->taskStorage->getTaskById($dummyTaskFailedNo->getId());
$dummyTaskPFailedNo = $this->taskStorage->getTaskById($dummyTaskPFailedNo->getId());
// Check if the tasks that should retry are running
$this->assertEquals(Task::RUNNING, $dummyTaskFailedYes->getStatus());
$this->assertEquals(Task::RUNNING, $dummyTaskPFailedYes->getStatus());
$this->assertTrue($this->executor->getTaskRunning($dummyTaskFailedYes));
$this->assertTrue($this->executor->getTaskRunning($dummyTaskPFailedYes));
// Check if the tasks that shouldn't have been cancelled
$this->assertEquals(Task::CANCELLED, $dummyTaskFailedNo->getStatus());
$this->assertEquals(Task::CANCELLED, $dummyTaskPFailedNo->getStatus());
}
/**
* @depends testFailedTask
*/
public function testExceedMaxRetries()
{
// First create the dummy tasks
$dummyTask = new Task('testExceedMaxRetries', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
$dummyTask2 = new Task('testExceedMaxRetries2', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
// Set status and retry settings
$dummyTask->setStatus(Task::FAILED);
$dummyTask2->setStatus(Task::FAILED);
$dummyTask->setRetrySettings(true, 2, true, true, true);
$dummyTask2->setRetrySettings(true, 2, true, true, true);
// Set retries to 2 for the first task, and 1 for the second task
$dummyTask->addRetry();
$dummyTask->addRetry();
$dummyTask2->addRetry();
// Write the task to TaskStorage
$this->taskStorage->addTask($dummyTask);
$this->taskStorage->addTask($dummyTask2);
// Cycle the SuperVisor
$this->superVisor->cycle();
// And check if the Task has been cancelled
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
$dummyTask2 = $this->taskStorage->getTaskById($dummyTask2->getId());
$this->assertEquals(Task::CANCELLED, $dummyTask->getStatus());
$this->assertEquals(Task::RUNNING, $dummyTask2->getStatus());
}
/**
* @depends testFailedTask
*/
public function testFailedToPost()
{
// First create the dummy tasks
$dummyTask = new Task('testFailedToPost', 'Mock\Handlers\ArgumentedHandler', true, 10, 'Some Output');
// Set status and settings
$dummyTask->setStatus(Task::FAILED);
$dummyTask->addAttribute('pid', 1010);
// Write the task to TaskStorage
$this->taskStorage->addTask($dummyTask);
// Cycle the SuperVisor
$this->superVisor->cycle();
// And check if the Task has been moved to Post
$dummyTask = $this->taskStorage->getTaskById($dummyTask->getId());
$this->assertEquals(Task::POST, $dummyTask->getStatus());
$this->assertTrue($this->executor->getTaskRunning($dummyTask));
$this->assertIsInt($dummyTask->attribute('pid'));
$this->assertNotEquals(1010, $dummyTask->attribute('pid'));
}
/**
* @depends testFinishedTask
*/
public function testSuccessfulTasks()
{
// First create the dummy tasks
$dummyTaskPostNo = new Task('testSuccessfulTasksN', 'Mock\Handlers\ArgumentedHandler', false, 10, 'Some Output');
$dummyTaskPostYes = new Task('testSuccessfulTasksY', 'Mock\Handlers\ArgumentedHandler', true, 10, 'Some Output');
// Set status and settings
$dummyTaskPostNo->setStatus(Task::SUCCESS);
$dummyTaskPostYes->setStatus(Task::SUCCESS);
// Write the tasks to TaskStorage
$this->taskStorage->addTask($dummyTaskPostNo);
$this->taskStorage->addTask($dummyTaskPostYes);
// Cycle the SuperVisor
$this->superVisor->cycle();
// And check if the Tasks have been completed or moved to post
$dummyTaskPostNo = $this->taskStorage->getTaskById($dummyTaskPostNo->getId());
$dummyTaskPostYes = $this->taskStorage->getTaskById($dummyTaskPostYes->getId());
$this->assertEquals(Task::COMPLETED, $dummyTaskPostNo->getStatus());
$this->assertEquals(Task::POST, $dummyTaskPostYes->getStatus());
$this->assertTrue($this->executor->getTaskRunning($dummyTaskPostYes));
}
public function testPostTasks()
{
// First create the dummy tasks
$dummyTaskFinished = new Task('testPostTasksFinished', 'Mock\Handlers\ArgumentedHandler', true, 10, 'Some Output');
$dummyTaskMissing = new Task('testPostTasksMissing', 'Mock\Handlers\ArgumentedHandler', true, 10, 'Some Output');
// Set status and settings
$dummyTaskFinished->setStatus(Task::POST);
$dummyTaskMissing->setStatus(Task::POST);
$dummyTaskFinished->addAttribute('pid', 1011);
$dummyTaskMissing->addAttribute('pid', 1012);
// Write the tasks to TaskStorage
$this->taskStorage->addTask($dummyTaskFinished);
$this->taskStorage->addTask($dummyTaskMissing);
$this->taskStorage->writePostOutput($dummyTaskFinished, 'Post Output', 'Post Errors', Task::COMPLETED);
// Cycle the SuperVisor
$this->superVisor->cycle();
// And check if the Tasks have been completed or failed
$dummyTaskFinished = $this->taskStorage->getTaskById($dummyTaskFinished->getId());
$dummyTaskMissing = $this->taskStorage->getTaskById($dummyTaskMissing->getId());
$this->assertEquals(Task::COMPLETED, $dummyTaskFinished->getStatus());
$this->assertEquals(Task::CANCELLED, $dummyTaskMissing->getStatus());
$this->assertEquals('Post Output', $dummyTaskFinished->getPostOutput());
$this->assertNull($dummyTaskMissing->getPostOutput());
}
}