Async/test/base/ShellExecutorTest.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));
}
}