taskStorage = $tasks->getTaskStorage(); $this->taskStorage->reset(); // Clear events Events::$listeners = []; // And load the ShellExecutor using the execution settings $this->executor = new ShellExecutor([ 'bootstrapFile' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'bootstrap.php', 'workerFile' => dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'worker' ]); $this->superVisor = new ParallelSuperVisor($this->taskStorage, $this->executor); } 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); $dummyTaskPFailedYes = new Task('testRetryFailedTaskPY', new ArgumentedHandler(10, 'Some Output'), false); $dummyTaskFailedNo = new Task('testRetryFailedTaskN', new ArgumentedHandler(10, 'Some Output'), false); $dummyTaskPFailedNo = new Task('testRetryFailedTaskPN', new ArgumentedHandler(10, 'Some Output'), false); // Set statuses $dummyTaskFailedYes->setStatus(Task::FAILED); $dummyTaskPFailedYes->setStatus(Task::PFAILED); $dummyTaskFailedNo->setStatus(Task::FAILED); $dummyTaskPFailedNo->setStatus(Task::FAILED); // Set retry settings $dummyTaskFailedYes->setSettings(true, 5, 30, true, true,true); $dummyTaskPFailedYes->setSettings(true, 5, 30, true, true,true); $dummyTaskFailedNo->setSettings(true, 5, 30, false, false,true); $dummyTaskPFailedNo->setSettings(true, 5, 30, 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); $dummyTask2 = new Task('testExceedMaxRetries2', new ArgumentedHandler(10, 'Some Output'), false); // Set status and retry settings $dummyTask->setStatus(Task::FAILED); $dummyTask2->setStatus(Task::FAILED); $dummyTask->setSettings(true, 2, 30, true, true, true); $dummyTask2->setSettings(true, 2, 30, 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), true); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), false); $dummyTaskPostYes = new Task('testSuccessfulTasksY', new ArgumentedHandler(10, 'Some Output'), true); // 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(); // Pause 1/10th of a second usleep(500000); // 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', new ArgumentedHandler(10, 'Some Output'), true); $dummyTaskMissing = new Task('testPostTasksMissing', new ArgumentedHandler(10, 'Some Output'), true); // 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::SUCCESS); // Cycle the SuperVisor $this->superVisor->cycle(); // Pause 1/10th of a second usleep(500000); // 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()); } }