diff --git a/src/GlobalLoop.php b/src/GlobalLoop.php new file mode 100644 index 00000000..d6aad5b3 --- /dev/null +++ b/src/GlobalLoop.php @@ -0,0 +1,92 @@ +run(); + }); + + self::$loop = self::create(); + + self::$loop->futureTick(function () { + self::$didRun = true; + }); + + return self::$loop; + } + + public static function reset() + { + self::$loop = null; + self::$didRun = false; + } + + /** + * @return LoopInterface + */ + public static function create() + { + if (self::$factory) { + return self::createFromCustomFactory(self::$factory); + } + + return Factory::create(); + } + + private static function createFromCustomFactory(callable $factory) + { + $loop = call_user_func($factory); + + if (!$loop instanceof LoopInterface) { + throw new \LogicException( + sprintf( + 'The GlobalLoop factory must return an instance of LoopInterface but returned %s.', + is_object($loop) ? get_class($loop) : gettype($loop) + ) + ); + } + + return $loop; + } +} diff --git a/tests/GlobalLoopTest.php b/tests/GlobalLoopTest.php new file mode 100644 index 00000000..4ec94729 --- /dev/null +++ b/tests/GlobalLoopTest.php @@ -0,0 +1,76 @@ +assertInstanceOf('React\EventLoop\LoopInterface', GlobalLoop::get()); + } + + public function testSubsequentGetCallsReturnSameInstance() + { + $this->assertSame(GlobalLoop::get(), GlobalLoop::get()); + } + + public function testSubsequentGetCallsReturnNotSameInstanceWhenResetting() + { + $loop = GlobalLoop::get(); + + GlobalLoop::reset(); + + $this->assertNotSame($loop, GlobalLoop::get()); + } + + public function testCreatesLoopWithFactory() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface') + ->getMock(); + + $factory = $this->createCallableMock(); + $factory + ->expects($this->once()) + ->method('__invoke') + ->will($this->returnValue($loop)); + + GlobalLoop::setFactory($factory); + + $this->assertSame($loop, GlobalLoop::get()); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage The GlobalLoop factory must return an instance of LoopInterface but returned NULL. + */ + public function testThrowsExceptionWhenFactoryDoesNotReturnALoopInterface() + { + $factory = $this->createCallableMock(); + $factory + ->expects($this->once()) + ->method('__invoke'); + + GlobalLoop::setFactory($factory); + + GlobalLoop::get(); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Setting a factory after the global loop has been started is not allowed. + */ + public function testThrowsExceptionWhenSettingAFactoryAfterLoopIsCreated() + { + GlobalLoop::get()->run(); + + GlobalLoop::setFactory(null); + } +}