Commits

Matt Pryor committed 062985b

Added and tested shorthand method.

Comments (0)

Files changed (9)

src/Async/Util.php

+<?php
+
+namespace Async;
+
+
+class Util {
+    /**
+     * Takes an object and returns an appropriate task object:
+     * 
+     *   - If $object is a task, it is returned
+     *   - If $object is a promise, a PromiseTask is returned
+     *   - If $object is a generator, a GeneratorTask is returned
+     *   - If $object is callable, a CallableTask is returned that will call the
+     *     object only once
+     *   - If $object is anything else, a task is returned whose result will be
+     *     $object
+     * 
+     * This method is provided as a convenience for the most commonly used tasks
+     * Other tasks can be created directly using their constructors
+     * 
+     * @param mixed $object
+     * @return \Async\Task\Task
+     */
+    public static function async($object) {
+        if( $object instanceof Task\Task )
+            return $object;
+        
+        if( $object instanceof \React\Promise\PromiseInterface )
+            return new Task\PromiseTask($object);
+        
+        if( $object instanceof \Generator )
+            return new Task\GeneratorTask($object);
+        
+        if( is_callable($object) )
+            return new Task\CallableTask($object);
+        
+        return new Task\CallableTask(function() use($object) { return $object; });
+    }
+}

test/Async/Test/CallableStub.php

+<?php
+
+namespace Async\Test;
+
+
+/**
+ * Stub callable object to allow mocking of callbacks
+ */
+class CallableStub {
+    public function __invoke() { }
+}

test/Async/Test/Scheduler/SchedulerTest.php

         $scheduler = new \Async\Scheduler();
         
         // Add a task that expects tick to be called exactly once
-        $task = $this->getMock('\Async\Task\Task');
+        $task = $this->getMock(\Async\Task\Task::class);
         $task->expects($this->once())->method('tick')->with($scheduler);
         $scheduler->add($task);
         
          *   1. Returns false when isComplete is called
          *   2. Expects tick to be called twice
          */
-        $task = $this->getMock('\Async\Task\Task');
+        $task = $this->getMock(\Async\Task\Task::class);
         $task->expects($this->any())->method('isComplete')->will($this->returnValue(false));
         $task->expects($this->exactly(2))->method('tick')->with($scheduler);
         $scheduler->add($task);
          *   1. Returns true when isComplete is called
          *   2. Expects tick to be called only once
          */
-        $task = $this->getMock('\Async\Task\Task');
+        $task = $this->getMock(\Async\Task\Task::class);
         $task->expects($this->any())->method('isComplete')->will($this->returnValue(true));
         $task->expects($this->exactly(1))->method('tick')->with($scheduler);
         $scheduler->add($task);
         $scheduler = new \Async\Scheduler();
         
         // Add two tasks that expect tick to be called exactly once
-        $task1 = $this->getMock('\Async\Task\Task');
+        $task1 = $this->getMock(\Async\Task\Task::class);
         $task1->expects($this->once())->method('tick')->with($scheduler);
         $scheduler->add($task1);
-        $task2 = $this->getMock('\Async\Task\Task');
+        $task2 = $this->getMock(\Async\Task\Task::class);
         $task2->expects($this->once())->method('tick')->with($scheduler);
         $scheduler->add($task2);
         
         $scheduler = new \Async\Scheduler();
         
         // Create the task that will be added mid-tick
-        $task = $this->getMock('\Async\Task\Task');
+        $task = $this->getMock(\Async\Task\Task::class);
         // The task only expects to be called once
         $task->expects($this->once())->method('tick')->with($scheduler);
         

test/Async/Test/Task/CallableStub.php

-<?php
-
-namespace Async\Test\Task;
-
-
-/**
- * Stub callable object to allow mocking of callbacks
- */
-class CallableStub {
-    public function __invoke() { }
-}

test/Async/Test/Task/CallableTaskTest.php

     public function testTaskResultIsReturnValue() {
         // Create a callable that expects to be called once and returns a known
         // value
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->once())->method('__invoke')
                                          ->will($this->returnValue("returned"));
         
         $this->assertFalse($task->isComplete());
         
         // Run the task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is complete without error and the result is the
         // expected value
      */
     public function testTaskErrorIsThrownException() {
         // Create a callable that expects to be called once and throws an exception
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->once())->method('__invoke')
                                          ->will($this->throwException(new \Exception("thrown")));
         
         $this->assertFalse($task->isComplete());
         
         // Run the task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is complete with the thrown error
         $this->assertTrue($task->isComplete());
      */
     public function testArgumentsPassed() {
         // Create a callable that expects to be called once with known arguments
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->once())->method('__invoke')
                                          ->with(1, 2, 3);
         
         $task = new \Async\Task\CallableTask($callable, [1, 2, 3]);
         
         // Run the task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
     }
     
     /**
      */
     public function testCallableExecutedOnlyOnce() {
         // Create a callable that expects to be called once
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->once())->method('__invoke');
         
         $task = new \Async\Task\CallableTask($callable);
         
         // Run the task twice
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
     }
 }

test/Async/Test/Task/GeneratorTaskTest.php

         $this->assertFalse($task->isComplete());
         
         // Create a mock scheduler that expects the yielded task to be added
-        $scheduler = $this->getMock('\Async\Scheduler');
+        $scheduler = $this->getMock(\Async\Scheduler::class);
         $scheduler->expects($this->once())->method('add')->with($stub);
         
         // Tick the task and check that the task gets scheduled
         // Create the generator task under test
         $task = new \Async\Task\GeneratorTask($generator->generator());
         // Tick the generator task to receive the first yielded task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is not complete and that nothing has been sent
         // back to the generator yet
         $stub->setResult("result");
         
         // Tick the task and verify that the generator received the result
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         $this->assertEquals("result", $generator->current());
     }
     
         // Create the generator task under test
         $task = new \Async\Task\GeneratorTask($generator->generator());
         // Tick the generator task to receive the first yielded task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is not complete and that nothing has been sent
         // back to the generator yet
         $stub->setException(new \Exception('failure'));
         
         // Tick the task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // The generator should have received an exception
         $this->assertNull($generator->current());
         // Create the generator task under test
         $task = new \Async\Task\GeneratorTask($generator->generator());
         // Tick the generator task to receive the first yielded task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Tick the task several times
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Verify that nothing has been sent back to the generator yet
         $this->assertFalse($task->isComplete());
         $stub->setResult('result');
         
         // Tick the generator task again
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Verify that current has been set
         $this->assertEquals('result', $generator->current());
         // Create the generator task under test
         $task = new \Async\Task\GeneratorTask($generator->generator());
         // Tick the generator task to receive the first yielded task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Complete the first yielded task with a result
         $stub1->setResult("stub result 1");
         
         // Tick the task and verify that the generator received the result of the
         // first stub task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         $this->assertEquals("stub result 1", $generator->current());
         
         // Complete the second yielded task with a result
         $this->assertEquals("stub result 1", $generator->current());
         
         // Tick the generator task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         // Verify that the generator received the result of the second task
         $this->assertEquals("stub result 2", $generator->current());
         // Veriry that the generator task completed with no error
         // Create the generator task under test
         $task = new \Async\Task\GeneratorTask($generator->generator());
         // Tick the generator task to receive the yielded task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Complete the first yielded task with a result
         $stub->setResult("result");
         
         // Tick the generator task and verify that it has failed with the
         // thrown exception as the reason
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         $this->assertTrue($task->isComplete());
         $this->assertTrue($task->isFaulted());
         $this->assertEquals('thrown', $task->getException()->getMessage());
         // Create the generator task under test
         $task = new \Async\Task\GeneratorTask($generator->generator());
         // Tick the generator task to receive the first yielded task
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is not complete and that nothing has been sent
         // back to the generator yet
         
         // Tick the generator task and check that the task is complete and that
         // the result was received by the generator
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         $this->assertTrue($task->isComplete());
         $this->assertEquals('result', $generator->current());
         
         // Tick the task a few more times and verify that the current value of
         // the generator is still the same
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         $this->assertTrue($task->isComplete());
         $this->assertEquals('result', $generator->current());

test/Async/Test/Task/PromiseTaskTest.php

         $this->assertFalse($task->isComplete());
         
         // Tick a few times
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // The task should not have completed
         $this->assertFalse($task->isComplete());
         $this->assertEquals("resolved", $task->getResult());
         
         // Tick a few more times
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Verify that the result is unchanged
         $this->assertTrue($task->isComplete());

test/Async/Test/Task/RecurringTaskTest.php

      */
     public function testCallableExecutedOnTick() {
         // Create a callable that expects to be called once
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->exactly(2))->method('__invoke');
         
         $task = new \Async\Task\RecurringTask($callable);
         $this->assertFalse($task->isComplete());
         
         // Tick the task - $callable should be called
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is still not complete
         $this->assertFalse($task->isComplete());
         
         // Tick the task again - $callable should be called again
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is still not complete
         $this->assertFalse($task->isComplete());
      */
     public function testCallableReceivesArguments() {
         // Create a callable that expects to be called once
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->exactly(2))->method('__invoke')
                                              ->with(1, 2, 3);
         
         $this->assertFalse($task->isComplete());
         
         // Tick the task - $callable should be called
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is still not complete
         $this->assertFalse($task->isComplete());
         
         // Tick the task again - $callable should be called again
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
         
         // Check that the task is still not complete
         $this->assertFalse($task->isComplete());
      */
     public function testTaskCompleteWithZeroTimes() {
         // Create a callable that expects never to be called
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->never())->method('__invoke');
         
         $task = new \Async\Task\RecurringTask($callable, [], 0);
         $this->assertFalse($task->isFaulted());
         $this->assertNull($task->getResult());
         
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
     }
     
     /**
      */
     public function testTaskCompletesAfterCorrectNumberOfTimes() {
         // Create a callable that expects to be called 5 times
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->exactly(5))->method('__invoke');
         
         $task = new \Async\Task\RecurringTask($callable, [], 5);
         // Check 5 times that the task is not complete and tick the task
         for( $i = 0; $i < 5; $i++ ) {
             $this->assertFalse($task->isComplete());
-            $task->tick($this->getMock('\Async\Scheduler'));
+            $task->tick($this->getMock(\Async\Scheduler::class));
         }
         
         // Check that the task is complete with no error, and running it doesn't
         $this->assertFalse($task->isFaulted());
         $this->assertNull($task->getResult());
         
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
     }
     
     /**
      */
     public function testTaskCompleteWhenExceptionThrown() {
         // Create a callable that expects to be called 5 times
-        $callable = $this->getMock('\Async\Test\Task\CallableStub');
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
         $callable->expects($this->exactly(5))->method('__invoke');
         // On the 5th call, throw an exception
         $callable->expects($this->at(4))->method('__invoke')
         // Check 5 times that the task is not complete and tick the task
         for( $i = 0; $i < 5; $i++ ) {
             $this->assertFalse($task->isComplete());
-            $task->tick($this->getMock('\Async\Scheduler'));
+            $task->tick($this->getMock(\Async\Scheduler::class));
         }
         
         // Check that the task is complete with the correct error
         $this->assertEquals("error", $task->getException()->getMessage());
         
         // Check that ticking the task again doesn't invoke the callable again
-        $task->tick($this->getMock('\Async\Scheduler'));
+        $task->tick($this->getMock(\Async\Scheduler::class));
     }
 }

test/Async/Test/Util/AsyncTest.php

+<?php
+
+namespace Async\Test\Util;
+
+
+class AsyncTest extends \PHPUnit_Framework_TestCase {
+    /**
+     * Test that Util::async returns the given task when given a task
+     */
+    public function testWithTask() {
+        $task = $this->getMock(\Async\Task\Task::class);
+        
+        // It should be the exact same task
+        $this->assertSame($task, \Async\Util::async($task));
+    }
+    
+    /**
+     * Test that Util::async returns a PromiseTask when given a promise
+     */
+    public function testWithPromise() {
+        $promise = new \React\Promise\Deferred();
+        
+        $task = \Async\Util::async($promise->promise());
+        
+        // Check it returned an instance of the correct class
+        $this->assertInstanceOf(\Async\Task\PromiseTask::class, $task);
+        
+        // Verify it behaves as if linked to the given promise
+        // The behaviour of PromiseTask is verified in more detail in its own
+        // test
+        $this->assertFalse($task->isComplete());
+        
+        $promise->resolve('resolved');
+        
+        $this->assertTrue($task->isComplete());
+        $this->assertFalse($task->isFaulted());
+        $this->assertEquals('resolved', $task->getResult());
+    }
+    
+    /**
+     * Test that Util::async returns a GeneratorTask when given a generator
+     */
+    public function testWithGenerator() {
+        $generator = function() {
+            for( $i = 0; $i < 3; $i++ )
+                yield new \Async\Task\PromiseTask(\React\Promise\When::resolve($i));
+        };
+        
+        $task = \Async\Util::async($generator());
+        
+        // Check it returned an instance of the correct class
+        $this->assertInstanceOf(\Async\Task\GeneratorTask::class, $task);
+        
+        // Verify it behaves as if linked to the given promise
+        // The behaviour of PromiseTask is verified in more detail in its own
+        // test
+        $this->assertFalse($task->isComplete());
+    }
+    
+    /**
+     * Test that Util::async returns a CallableTask when given a callable
+     */
+    public function testWithCallable() {
+        // The callable expects to be called once
+        $callable = $this->getMock(\Async\Test\CallableStub::class);
+        $callable->expects($this->once())->method('__invoke');
+        
+        $task = \Async\Util::async($callable);
+        
+        // Check it returned an instance of the correct class
+        $this->assertInstanceOf(\Async\Task\CallableTask::class, $task);
+        
+        // Tick the task and verify it has completed and the callable was called
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        
+        $this->assertTrue($task->isComplete());
+    }
+    
+    /**
+     * Test that Util::async returns an appropriate CallableTask when given any
+     * other object
+     * 
+     * I.e. one that, when ticked, the task result is the given object
+     */
+    public function testWithOther() {
+        $task = \Async\Util::async(101);
+        
+        // Check it returned an instance of the correct class
+        $this->assertInstanceOf(\Async\Task\CallableTask::class, $task);
+        
+        // Check the task is currently incomplete
+        $this->assertFalse($task->isComplete());
+        
+        // Tick the task
+        $task->tick($this->getMock(\Async\Scheduler::class));
+        
+        // Verify the task is complete and has the correct result
+        $this->assertTrue($task->isComplete());
+        $this->assertFalse($task->isFaulted());
+        $this->assertEquals(101, $task->getResult());
+    }
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.