Async/test/base/TaskStorageTest.php

578 lines
21 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\Events\TaskModifyEvent;
use FuzeWorks\Async\Task;
use FuzeWorks\Async\Tasks;
use FuzeWorks\Async\TasksException;
use FuzeWorks\Async\TaskStorage;
use FuzeWorks\Events;
use FuzeWorks\Priority;
use Mock\Handlers\EmptyHandler;
use PHPUnit\Framework\TestCase;
/**
* Class TaskStorageTest
*/
class TaskStorageTest extends TestCase
{
/**
* @var TaskStorage
*/
private $taskStorage;
public function setUp(): void
{
// Add TaskStorage
$tasks = new Tasks();
$this->taskStorage = $tasks->getTaskStorage();
$this->taskStorage->reset();
// Reset events
Events::$listeners = [];
}
public function testDummyTaskStorageClass()
{
$this->assertInstanceOf('FuzeWorks\Async\TaskStorage', $this->taskStorage);
}
/* ---------------------------------- Writing and reading tasks ----------------------- */
/**
* @depends testDummyTaskStorageClass
*/
public function testAddAndReadTasks()
{
// Prepare a dummy task
$dummyTask = new Task('testAddTask', new EmptyHandler());
// Nothing is written yet so it should be empty
$this->assertEmpty($this->taskStorage->readTasks());
// Write task to storage and test properties of readTasks
$this->assertTrue($this->taskStorage->addTask($dummyTask));
$output = $this->taskStorage->readTasks();
$this->assertCount(1, $output);
// Get first
$task = $output[0];
$this->assertEquals($dummyTask, $task);
// Test if the properties match
$this->assertEquals('testAddTask', $task->getId());
$this->assertInstanceOf(EmptyHandler::class, $task->getHandler());
}
/**
* @depends testAddAndReadTasks
*/
public function testReadUnfinishedTasks()
{
// Add the tasks
$finishedTask = new Task('finishedTask', new EmptyHandler());
$finishedTask->setStatus(Task::COMPLETED);
$unfinishedTask1 = new Task('unfinishedTask1', new EmptyHandler());
$unfinishedTask2 = new Task('unfinishedTask2', new EmptyHandler());
// Nothing is written yet so it should be empty
$this->assertEmpty($this->taskStorage->readTasks());
// Write the tasks to TaskStorage
$this->taskStorage->addTask($finishedTask);
$this->taskStorage->addTask($unfinishedTask1);
$this->taskStorage->addTask($unfinishedTask2);
// And check whether they get properly read
$this->assertCount(3, $this->taskStorage->readTasks());
// And whether the finished task gets omitted in the unfinished list
$this->assertCount(2, $this->taskStorage->readTasks(true));
}
/**
* @depends testAddAndReadTasks
*/
public function testAddExistingTask()
{
// Prepare a dummy task
$dummyTask = new Task('testAddExistingTask', new EmptyHandler());
// First check that the task storage starts empty
$this->assertEmpty($this->taskStorage->readTasks());
// Then add the first task
$this->assertTrue($this->taskStorage->addTask($dummyTask));
// But then add another task, which should raise an exception
$this->expectException(TasksException::class);
$this->taskStorage->addTask($dummyTask);
}
/**
* @depends testAddAndReadTasks
*/
public function testGetTaskById()
{
// Prepare a dummy task
$dummyTask1 = new Task('testGetTaskById1', new EmptyHandler());
$dummyTask2 = new Task('testGetTaskById2', new EmptyHandler());
// First we add both tasks
$this->assertEmpty($this->taskStorage->readTasks());
$this->assertTrue($this->taskStorage->addTask($dummyTask1));
$this->assertTrue($this->taskStorage->addTask($dummyTask2));
// Afterwards, we attempt to get the separate tasks
$retrievedTask1 = $this->taskStorage->getTaskById('testGetTaskById1');
$retrievedTask2 = $this->taskStorage->getTaskById('testGetTaskById2');
$this->assertInstanceOf('FuzeWorks\Async\Task', $retrievedTask1);
$this->assertInstanceOf('FuzeWorks\Async\Task', $retrievedTask2);
// Assert they have the values we seek
$this->assertEquals('testGetTaskById1', $retrievedTask1->getId());
$this->assertEquals('testGetTaskById2', $retrievedTask2->getId());
// Test they are not the same
$this->assertNotEquals($retrievedTask1, $retrievedTask2);
// And test they are the initial dummy tasks
$this->assertEquals($dummyTask1, $retrievedTask1);
$this->assertEquals($dummyTask2, $retrievedTask2);
}
/**
* @depends testGetTaskById
*/
public function testGetTaskByIdNotFound()
{
// Prepare a dummy task
$dummyTask = new Task('testGetTaskByIdNotFound', new EmptyHandler());
// First we add the task
$this->assertEmpty($this->taskStorage->readTasks());
$this->assertTrue($this->taskStorage->addTask($dummyTask));
// Afterwards we check if we can get this task
$this->assertInstanceOf('FuzeWorks\Async\Task', $this->taskStorage->getTaskById('testGetTaskByIdNotFound'));
// And afterwards we check if an exception is raised if none exist
$this->expectException(TasksException::class);
$this->taskStorage->getTaskById('DoesNotExist');
}
/**
* @depends testGetTaskById
*/
public function testModifyTask()
{
// Prepare a dummy task
$dummyTask = new Task('testModifyTask', new EmptyHandler());
$dummyTask->setStatus(Task::RUNNING);
// First we add the task
$this->assertEmpty($this->taskStorage->readTasks());
$this->assertTrue($this->taskStorage->addTask($dummyTask));
// Afterwards we check if this task has the known details
$this->assertEquals(Task::RUNNING, $this->taskStorage->getTaskById('testModifyTask')->getStatus());
// Then we change the task
$dummyTask->setStatus(Task::FAILED);
$this->assertTrue($this->taskStorage->modifyTask($dummyTask));
// And check if the details have been changed
$this->assertEquals(Task::FAILED, $this->taskStorage->getTaskById('testModifyTask')->getStatus());
}
/**
* @depends testModifyTask
*/
public function testModifyTaskNotFound()
{
// Prepare a dummy task
$dummyTask = new Task('testModifyTaskNotFound', new EmptyHandler());
// Attempt to change this task, which does not exist.
$this->expectException(TasksException::class);
$this->taskStorage->modifyTask($dummyTask);
}
/**
* @depends testModifyTask
*/
public function testModifyTaskEvent()
{
// Prepare a dummy task
$dummyTask = new Task('testModifyTaskEvent', new EmptyHandler());
$dummyTask->setStatus(Task::PENDING);
// Then add the Task
$this->taskStorage->addTask($dummyTask);
// Now prepare a listener to be fired
Events::addListener(function (TaskModifyEvent $event){
$task = $event->getTask();
$this->assertEquals(Task::PENDING, $task->getStatus());
$task->setStatus(Task::RUNNING);
$event->updateTask($task);
return $event;
}, 'TaskModifyEvent', Priority::NORMAL);
// Now update the task
$this->assertEquals(Task::PENDING, $dummyTask->getStatus());
$this->taskStorage->modifyTask($dummyTask);
// And check whether dummyTask got modified
$this->assertEquals(Task::RUNNING, $dummyTask->getStatus());
// And check whether the TaskStorage has this updated version as well
$modifiedTask = $this->taskStorage->getTaskById($dummyTask->getId());
$this->assertEquals(Task::RUNNING, $modifiedTask->getStatus());
}
/**
* @depends testModifyTaskEvent
*/
public function testModifyTaskCancel()
{
// Prepare a dummy task
$dummyTask = new Task('testModifyTaskCancel', new EmptyHandler());
$dummyTask->setStatus(Task::PENDING);
// Then add the Task
$this->taskStorage->addTask($dummyTask);
// Now prepare a listener to be fired
Events::addListener(function (TaskModifyEvent $event){
$event->setCancelled(true);
return $event;
}, 'TaskModifyEvent', Priority::NORMAL);
// Modify the task
$dummyTask->setStatus(Task::SUCCESS);
$this->assertFalse($this->taskStorage->modifyTask($dummyTask));
// And check that the task actually hasn't updated
$modifiedTask = $this->taskStorage->getTaskById($dummyTask->getId());
$this->assertEquals(Task::PENDING, $modifiedTask->getStatus());
}
/**
* @depends testGetTaskById
*/
public function testDeleteTask()
{
// Prepare a dummy task
$dummyTask = new Task('testDeleteTask', new EmptyHandler());
// Add the task to the storage
$this->assertEmpty($this->taskStorage->readTasks());
$this->assertTrue($this->taskStorage->addTask($dummyTask));
// Test that it exists
$this->assertEquals($dummyTask, $this->taskStorage->getTaskById('testDeleteTask'));
// Then remove the task
$this->assertTrue($this->taskStorage->deleteTask($dummyTask));
// And test that it can't be found
$this->expectException(TasksException::class);
$this->taskStorage->getTaskById('testDeleteTask');
}
/**
* @depends testDeleteTask
*/
public function testDeleteTaskNotFound()
{
// Prepare a dummy task
$dummyTask = new Task('testDeleteTaskNotFound', new EmptyHandler());
// Attempt to delete this task, which does not exist.
$this->expectException(TasksException::class);
$this->taskStorage->deleteTask($dummyTask);
}
/* ---------------------------------- Writing and reading task output ----------------- */
/**
* @depends testDummyTaskStorageClass
*/
public function testWriteAndReadTaskOutput()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskOutput', new EmptyHandler());
// First write the task output
$this->taskStorage->addTask($dummyTask);
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output', 'errors', 0));
// Then try to read the output
$output = $this->taskStorage->readTaskOutput($dummyTask, 1);
$this->assertEquals('output', $output['output']);
$this->assertEquals('errors', $output['errors']);
$this->assertEquals(0, $output['statusCode']);
}
/**
* @depends testWriteAndReadTaskOutput
*/
public function testWriteAndReadMultipleOutput()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadMultipleOutput', new EmptyHandler());
// Write some task output
$this->taskStorage->addTask($dummyTask);
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output1', 'errors1', 0));
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output2', 'errors2', 0));
// Then try to read all the output
$output = $this->taskStorage->readTaskOutput($dummyTask, -1);
$this->assertEquals([
['output' => 'output1', 'errors' => 'errors1', 'statusCode' => 0],
['output' => 'output2', 'errors' => 'errors2', 'statusCode' => 0]
], $output);
// Then try and read the latest
$this->assertEquals(['output' => 'output2', 'errors' => 'errors2', 'statusCode' => 0], $this->taskStorage->readTaskOutput($dummyTask));
}
/**
* @depends testWriteAndReadTaskOutput
*/
public function testWriteAndReadTaskOutputTaskNotExist()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskOutputTaskNotExist', new EmptyHandler());
// Write output while the task does not exist yet, expect exception
$this->expectException(TasksException::class);
$this->taskStorage->writeTaskOutput($dummyTask, 'output', 'errors', 0);
}
/**
* @depends testWriteAndReadTaskOutput
*/
public function testWriteAndReadTaskOutputAttempts()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskOutputAttempts', new EmptyHandler());
$this->taskStorage->addTask($dummyTask);
// Write the different outputs.
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output0', 'errors0', 100));
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output1', 'errors1', 101));
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output2', 'errors2', 102));
// Attempt to load the first output
$output0 = $this->taskStorage->readTaskOutput($dummyTask, 1);
$this->assertEquals('output0', $output0['output']);
$this->assertEquals('errors0', $output0['errors']);
$this->assertEquals(100, $output0['statusCode']);
// Attempt to load the second output
$output1 = $this->taskStorage->readTaskOutput($dummyTask, 2);
$this->assertEquals('output1', $output1['output']);
$this->assertEquals('errors1', $output1['errors']);
$this->assertEquals(101, $output1['statusCode']);
// Attempt to load the third output
$output2 = $this->taskStorage->readTaskOutput($dummyTask, 3);
$this->assertEquals('output2', $output2['output']);
$this->assertEquals('errors2', $output2['errors']);
$this->assertEquals(102, $output2['statusCode']);
// Attempt to load the default output
$output = $this->taskStorage->readTaskOutput($dummyTask);
$this->assertEquals('output2', $output['output']);
$this->assertEquals('errors2', $output['errors']);
$this->assertEquals(102, $output['statusCode']);
// And to load all
$this->assertEquals([
['output' => 'output0', 'errors' => 'errors0', 'statusCode' => 100],
['output' => 'output1', 'errors' => 'errors1', 'statusCode' => 101],
['output' => 'output2', 'errors' => 'errors2', 'statusCode' => 102]
], $this->taskStorage->readTaskOutput($dummyTask, -1));
}
/**
* @depends testWriteAndReadTaskOutput
*/
public function testWriteAndReadTaskOutputNotExist()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskOutputNotExist', new EmptyHandler());
$this->taskStorage->addTask($dummyTask);
$this->assertNull($this->taskStorage->readTaskOutput($dummyTask));
}
/* ---------------------------------- Writing and reading task post output ------------ */
/**
* @depends testDummyTaskStorageClass
*/
public function testWriteAndReadTaskPostOutput()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskPostOutput', new EmptyHandler());
$this->taskStorage->addTask($dummyTask);
// First write the task output
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'postOutput', 'errors', 0));
// Then try to read the output
$output = $this->taskStorage->readPostOutput($dummyTask, 1);
$this->assertEquals('postOutput', $output['output']);
$this->assertEquals('errors', $output['errors']);
$this->assertEquals(0, $output['statusCode']);
}
/**
* @depends testWriteAndReadTaskOutput
*/
public function testWriteAndReadMultiplePostOutput()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadMultiplePostOutput', new EmptyHandler());
// Write some task output
$this->taskStorage->addTask($dummyTask);
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'output1', 'errors1', 0));
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'output2', 'errors2', 0));
// Then try to read all the output
$output = $this->taskStorage->readPostOutput($dummyTask, -1);
$this->assertEquals([
['output' => 'output1', 'errors' => 'errors1', 'statusCode' => 0],
['output' => 'output2', 'errors' => 'errors2', 'statusCode' => 0]
], $output);
$this->assertEquals(['output' => 'output2', 'errors' => 'errors2', 'statusCode' => 0], $this->taskStorage->readPostOutput($dummyTask));
}
/**
* @depends testWriteAndReadTaskPostOutput
*/
public function testWriteAndReadTaskPostOutputAttempts()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskPostOutputAttempts', new EmptyHandler());
$this->taskStorage->addTask($dummyTask);
// Write the different outputs
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'output0', 'errors0', 100));
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'output1', 'errors1', 101));
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'output2', 'errors2', 102));
// Attempt to load the first output
$output0 = $this->taskStorage->readPostOutput($dummyTask, 1);
$this->assertEquals('output0', $output0['output']);
$this->assertEquals('errors0', $output0['errors']);
$this->assertEquals(100, $output0['statusCode']);
// Attempt to load the second output
$output1 = $this->taskStorage->readPostOutput($dummyTask, 2);
$this->assertEquals('output1', $output1['output']);
$this->assertEquals('errors1', $output1['errors']);
$this->assertEquals(101, $output1['statusCode']);
// Attempt to load the third output
$output2 = $this->taskStorage->readPostOutput($dummyTask, 3);
$this->assertEquals('output2', $output2['output']);
$this->assertEquals('errors2', $output2['errors']);
$this->assertEquals(102, $output2['statusCode']);
// Attempt to load the default output
$output = $this->taskStorage->readPostOutput($dummyTask);
$this->assertEquals('output2', $output['output']);
$this->assertEquals('errors2', $output['errors']);
$this->assertEquals(102, $output['statusCode']);
// And to load all
$this->assertEquals([
['output' => 'output0', 'errors' => 'errors0', 'statusCode' => 100],
['output' => 'output1', 'errors' => 'errors1', 'statusCode' => 101],
['output' => 'output2', 'errors' => 'errors2', 'statusCode' => 102]
], $this->taskStorage->readPostOutput($dummyTask, -1));
}
/**
* @depends testWriteAndReadTaskPostOutput
*/
public function testWriteAndReadTaskPostOutputNotExist()
{
// Prepare a dummy task
$dummyTask = new Task('testWriteAndReadTaskPostOutputNotExist', new EmptyHandler());
$this->taskStorage->addTask($dummyTask);
$this->assertNull($this->taskStorage->readPostOutput($dummyTask));
}
/* ---------------------------------- Data persistence and resets --------- ------------ */
/**
* @depends testAddAndReadTasks
* @depends testWriteAndReadTaskOutput
* @depends testWriteAndReadTaskPostOutput
*/
public function testReset()
{
// Prepare a dummy task
$dummyTask = new Task('testReset', new EmptyHandler());
// Add the task and some output
$this->assertTrue($this->taskStorage->addTask($dummyTask));
$this->assertTrue($this->taskStorage->writeTaskOutput($dummyTask, 'output', 'errors', 100));
$this->assertTrue($this->taskStorage->writePostOutput($dummyTask, 'postOutput', 'errors', 100));
// Then reset the data
$this->assertTrue($this->taskStorage->reset());
// And test if the data is actually gone
$this->assertNull($this->taskStorage->readTaskOutput($dummyTask));
$this->assertNull($this->taskStorage->readPostOutput($dummyTask));
$this->expectException(TasksException::class);
$this->taskStorage->getTaskById('testReset');
}
}