239 lines
7.4 KiB
PHP
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));
|
||
|
}
|
||
|
|
||
|
}
|