tasks = Factory::getInstance('libraries')->get('async'); $this->taskStorage = $this->tasks->getTaskStorage(); $this->taskStorage->reset(); // Reset events Events::$listeners = []; } /* ---------------------------------- Test the dependency constraint ------------------ */ public function testHasConstrainedDeps() { // Create the dependent tasks $depTask1 = new Task('depTask1', new EmptyHandler()); $depTask2 = new Task('depTask2', new EmptyHandler()); // Write those dependencies to TaskStorage $this->taskStorage->addTask($depTask1); $this->taskStorage->addTask($depTask2); // Create the constraint $constraint = new DependencyConstraint(['depTask1', 'depTask2']); // And a dummyTask to accompany $dummyTask = new Task('dependentTask', new EmptyHandler()); $dummyTask->addConstraint($constraint); // Test that the constraint is the same $this->assertSame([$constraint], $dummyTask->getConstraints()); // And test the intervention $this->assertTrue($constraint->intervene($dummyTask)); $this->assertEquals(Task::DELAYED, $constraint->blockCode()); $this->assertEquals(time() + 3, $constraint->delayTime()); } /** * @depends testHasConstrainedDeps */ public function testDelayTimes() { // Create the dependent tasks $depTask1 = new Task('depTask1', new EmptyHandler()); $depTask2 = new Task('depTask2', new EmptyHandler()); // Write those dependencies to TaskStorage $this->taskStorage->addTask($depTask1); $this->taskStorage->addTask($depTask2); // Create some useless dummy task $dummyTask = new Task('dependentTask', new EmptyHandler()); // Create the constraints // Default time $constraintDef = new DependencyConstraint(['depTask1', 'depTask2']); // Modified time (30) $constraintMod1 = new DependencyConstraint(['depTask1', 'depTask2'], 30); // And another (60) $constraintMod2 = new DependencyConstraint(['depTask1', 'depTask2'], 60); // And intervene all of them $this->assertTrue($constraintDef->intervene($dummyTask)); $this->assertTrue($constraintMod1->intervene($dummyTask)); $this->assertTrue($constraintMod2->intervene($dummyTask)); // And check the results $this->assertEquals(Task::DELAYED, $constraintDef->blockCode()); $this->assertEquals(Task::DELAYED, $constraintMod1->blockCode()); $this->assertEquals(Task::DELAYED, $constraintMod2->blockCode()); $this->assertEquals(time() + 3, $constraintDef->delayTime()); $this->assertEquals(time() + 30, $constraintMod1->delayTime()); $this->assertEquals(time() + 60, $constraintMod2->delayTime()); } public function testHasFailedDeps() { // Create the dependent tasks $depTask1 = new Task('depTask1', new EmptyHandler()); $depTask2 = new Task('depTask2', new EmptyHandler()); // And set the first as completed, and second as failed $depTask1->setStatus(Task::COMPLETED); $depTask2->setStatus(Task::CANCELLED); // Write those dependencies to TaskStorage $this->taskStorage->addTask($depTask1); $this->taskStorage->addTask($depTask2); // Create the constraint $constraint = new DependencyConstraint(['depTask1', 'depTask2']); // And a dummyTask to accompany $dummyTask = new Task('dependentTask', new EmptyHandler()); $dummyTask->addConstraint($constraint); // Test that the constraint is the same $this->assertSame([$constraint], $dummyTask->getConstraints()); // And test the intervention $this->assertTrue($constraint->intervene($dummyTask)); $this->assertEquals(Task::CANCELLED, $constraint->blockCode()); $this->assertEquals('Task cancelled due to failed dependency.', $dummyTask->getErrors()); } public function testHasCompletedDeps() { // Create the dependent tasks $depTask1 = new Task('depTask1', new EmptyHandler()); $depTask2 = new Task('depTask2', new EmptyHandler()); // And set the first as completed, and second as failed $depTask1->setStatus(Task::COMPLETED); $depTask2->setStatus(Task::COMPLETED); // Write those dependencies to TaskStorage $this->taskStorage->addTask($depTask1); $this->taskStorage->addTask($depTask2); // Create the constraint $constraint = new DependencyConstraint(['depTask1', 'depTask2']); // And a dummyTask to accompany $dummyTask = new Task('dependentTask', new EmptyHandler()); $dummyTask->addConstraint($constraint); // Test that the constraint is the same $this->assertSame([$constraint], $dummyTask->getConstraints()); // And test the intervention $this->assertFalse($constraint->intervene($dummyTask)); } public function testGetDependencies() { $constraint = new DependencyConstraint(['someTask1', 'someTask2']); $this->assertEquals(['someTask1', 'someTask2'], $constraint->getDependencies()); } /* ---------------------------------- Test the dependent task handler ----------------- */ public function testAddedDependencies() { $handler = new DependentTaskHandler(['someTask1', 'someTask2']); $dummyTask = new Task('someTask', $handler); // Check that the constraints match expectations /** @var DependencyConstraint[] $constraints */ $constraints = $dummyTask->getConstraints(); $this->assertInstanceOf(DependencyConstraint::class, $constraints[0]); // And that the dependencies match $this->assertEquals(['someTask1', 'someTask2'], $constraints[0]->getDependencies()); } public function testPassingOutput() { // Create the dependent tasks $depTask1 = new Task('someTask', new EmptyHandler()); $depTask2 = new Task('someTask2', new EmptyHandler()); // Give the dependencies some output $depTask1->setOutput('First Output', ''); $depTask2->setOutput('Second Output', ''); // Write those to TaskStorage $this->taskStorage->addTask($depTask1); $this->taskStorage->addTask($depTask2); // Create the task $handler = new DependentTaskHandler(['someTask', 'someTask2']); // Create a dummy Task $dummyTask = new Task('someTask3', $handler); // Assert that all is well $this->assertTrue($handler->primaryHandler($dummyTask)); // And test the handler's output $this->assertEquals(json_encode([ 'someTask' => [ 'status' => Task::PENDING, 'output' => 'First Output', 'errors' => '', 'post' => null, 'postErrors' => null ], 'someTask2' => [ 'status' => Task::PENDING, 'output' => 'Second Output', 'errors' => '', 'post' => null, 'postErrors' => null ] ]), $handler->getOutput()); // And test the post handler $this->assertTrue($handler->postHandler($dummyTask)); $this->assertEquals(json_encode([ 'someTask' => [ 'status' => Task::PENDING, 'output' => 'First Output', 'errors' => '', 'post' => null, 'postErrors' => null ], 'someTask2' => [ 'status' => Task::PENDING, 'output' => 'Second Output', 'errors' => '', 'post' => null, 'postErrors' => null ] ]), $handler->getPostOutput()); } /** * @depends testPassingOutput */ public function testMissingDependency() { // Create the task $handler = new DependentTaskHandler(['someTask']); // Create a dummy Task $dummyTask = new Task('someTask2', $handler); // Assert that all is well $this->assertTrue($handler->primaryHandler($dummyTask)); // And test the handler's output $this->assertEquals(json_encode([ 'someTask' => [ 'status' => Task::FAILED, 'output' => null, 'errors' => 'Task not found.', 'post' => null, 'postErrors' => null ], ]), $handler->getOutput()); // And test the post handler $this->assertTrue($handler->postHandler($dummyTask)); $this->assertEquals(json_encode([ 'someTask' => [ 'status' => Task::FAILED, 'output' => null, 'errors' => 'Task not found.', 'post' => null, 'postErrors' => null ], ]), $handler->getPostOutput()); } /** * @depends testPassingOutput */ public function testNoDepedencies() { // Create the task $handler = new DependentTaskHandler([]); // Create a dummy Task $dummyTask = new Task('someTask', $handler); // Assert that all is well $this->assertTrue($handler->primaryHandler($dummyTask)); $this->assertEquals(json_encode([]), $handler->getOutput()); // And test the post handler $this->assertTrue($handler->postHandler($dummyTask)); $this->assertEquals(json_encode([]), $handler->getPostOutput()); } public function testParentHandler() { // Test pass output $handler = new DependentTaskHandler([]); $handler->setParentInput('Passed Input'); $this->assertEquals('Passed Input', $handler->getOutput()); // Test passing a handler $handler = new DependentTaskHandler([]); $parentHandler = $this->createMock(Handler::class); $handler->setParentHandler($parentHandler); $this->assertSame($parentHandler, $handler->getParentHandler()); } public function testPassDependencyOutput() { // Build all systems for this test $superVisor = $this->tasks->getSuperVisor(); // Create the dependency $dependency = new Task('dependency', new ArgumentedHandler(0, 'Prepared Output')); // Write the task to TaskStorage $this->taskStorage->addTask($dependency); // Now create the dependent task $dependent = new Task('dependent', new DependentTaskHandler(['dependency'], 2)); // And write that task to TaskStorage $this->taskStorage->addTask($dependent); // Now we make the SuperVisor cycle, to start the dependency and set the dependent to WAIT $this->assertEquals(SuperVisor::RUNNING, $superVisor->cycle()); // Assert that everything is running $this->assertEquals(Task::RUNNING, $this->taskStorage->getTaskById($dependency->getId())->getStatus() ); $this->assertEquals(Task::DELAYED, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); // Give the task some time to finish usleep(500000); // And re-run the SuperVisor $this->assertEquals(SuperVisor::RUNNING, $superVisor->cycle()); // Now check the tasks again. Dependency should be finished and have output, // whereas dependent should still be delayed $this->assertEquals(Task::SUCCESS, $this->taskStorage->getTaskById($dependency->getId())->getStatus() ); $this->assertEquals(Task::DELAYED, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); // Cycle again and see the dependency be completed, and dependent still delayed $this->assertEquals(SuperVisor::RUNNING, $superVisor->cycle()); $this->assertEquals(Task::COMPLETED, $this->taskStorage->getTaskById($dependency->getId())->getStatus() ); $this->assertEquals(Task::DELAYED, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); // Also check that output is correct $this->assertEquals('Prepared Output', $this->taskStorage->getTaskById($dependency->getId())->getOutput() ); // Now wait long enough for the delay to be finished usleep(2500000); // Now cycle again, and expect the task to be pending $this->assertEquals(SuperVisor::RUNNING, $superVisor->cycle()); $this->assertEquals(Task::PENDING, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); // Cycle again and expect it to be running $this->assertEquals(SuperVisor::RUNNING, $superVisor->cycle()); $this->assertEquals(Task::RUNNING, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); // Give the task some time to finish usleep(500000); // And cycle again and expect the task to have succeeded $this->assertEquals(SuperVisor::RUNNING, $superVisor->cycle()); $this->assertEquals(Task::SUCCESS, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); // Cycle again and expect the task to have completed, and test its output $this->assertEquals(SuperVisor::FINISHED, $superVisor->cycle()); $this->assertEquals(Task::COMPLETED, $this->taskStorage->getTaskById($dependent->getId())->getStatus() ); $this->assertEquals( json_encode(['dependency' => [ 'status' => Task::COMPLETED, 'output' => 'Prepared Output', 'errors' => '', 'post' => null, 'postErrors' => null ]]), $this->taskStorage->getTaskById($dependent->getId())->getOutput() ); } }