Async/test/base/ShellExecutorTest.php
Abel Hoogeveen 902693dbbe
All checks were successful
continuous-integration/drone/push Build is passing
Implemented Parent Handlers.
Parent Handlers can be stacked to run in succession. Output is transfered as input into the child handler which can continue with it. If the parent Handler fails, all Child handlers also fail.
2020-06-03 17:00:44 +02:00

239 lines
7.4 KiB
PHP

<?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 Mock\Handlers\EmptyHandler;
use Mock\Handlers\TestStartAndReadTasksHandler;
use Mock\Handlers\TestStopTaskHandler;
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', new 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);
// Pause 1/10th of a second
usleep(500000);
// 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', new TestStartAndReadTasksHandler());
// Then we write this task to the TaskStorage
$this->taskStorage->addTask($dummyTask);
// Then we start the task
$dummyTask = $this->executor->startTask($dummyTask);
// Pause 1/10th of a second
usleep(500000);
// 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', new EmptyHandler());
// 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', new 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);
// Pause 1/10th of a second
usleep(500000);
// Check if the task is running
$this->assertTrue($this->executor->getTaskRunning($dummyTask));
// But then we try and stop it
$output = $this->executor->stopTask($dummyTask);
// Pause 1/10th of a second
usleep(500000);
// 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));
}
}