diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65fe5d47..7660818c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,11 +19,6 @@ jobs: - 7.3 - 7.2 - 7.1 - - 7.0 - - 5.6 - - 5.5 - - 5.4 - - 5.3 steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 diff --git a/composer.json b/composer.json index de22b26f..1bb6c5da 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ } ], "require": { - "php": ">=5.3.0", + "php": ">=7.1", "react/cache": "^1.0 || ^0.6 || ^0.5", "react/event-loop": "^1.2", "react/promise": "^3.0 || ^2.7 || ^1.2.1" diff --git a/src/Model/Message.php b/src/Model/Message.php index bac2b10d..8a576e08 100644 --- a/src/Model/Message.php +++ b/src/Model/Message.php @@ -126,23 +126,13 @@ public static function createResponseWithAnswersForQuery(Query $query, array $an * DNS response messages can not guess the message ID to avoid possible * cache poisoning attacks. * - * The `random_int()` function is only available on PHP 7+ or when - * https://github.com/paragonie/random_compat is installed. As such, using - * the latest supported PHP version is highly recommended. This currently - * falls back to a less secure random number generator on older PHP versions - * in the hope that this system is properly protected against outside - * attackers, for example by using one of the common local DNS proxy stubs. - * * @return int * @see self::getId() * @codeCoverageIgnore */ private static function generateId() { - if (function_exists('random_int')) { - return random_int(0, 0xffff); - } - return mt_rand(0, 0xffff); + return \random_int(0, 0xffff); } /** diff --git a/src/Query/TcpTransportExecutor.php b/src/Query/TcpTransportExecutor.php index bfaedbae..2b879a8a 100644 --- a/src/Query/TcpTransportExecutor.php +++ b/src/Query/TcpTransportExecutor.php @@ -6,7 +6,6 @@ use React\Dns\Protocol\BinaryDumper; use React\Dns\Protocol\Parser; use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; use React\Promise\Deferred; /** @@ -78,7 +77,6 @@ class TcpTransportExecutor implements ExecutorInterface { private $nameserver; - private $loop; private $parser; private $dumper; @@ -132,9 +130,8 @@ class TcpTransportExecutor implements ExecutorInterface /** * @param string $nameserver - * @param ?LoopInterface $loop */ - public function __construct($nameserver, LoopInterface $loop = null) + public function __construct($nameserver) { if (\strpos($nameserver, '[') === false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === false) { // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets @@ -147,7 +144,6 @@ public function __construct($nameserver, LoopInterface $loop = null) } $this->nameserver = 'tcp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53); - $this->loop = $loop ?: Loop::get(); $this->parser = new Parser(); $this->dumper = new BinaryDumper(); } @@ -190,7 +186,7 @@ public function query(Query $query) } if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::get()->cancelTimer($this->idleTimer); $this->idleTimer = null; } @@ -198,7 +194,7 @@ public function query(Query $query) $this->writeBuffer .= $queryData; if (!$this->writePending) { $this->writePending = true; - $this->loop->addWriteStream($this->socket, array($this, 'handleWritable')); + Loop::get()->addWriteStream($this->socket, array($this, 'handleWritable')); } $names =& $this->names; @@ -243,7 +239,7 @@ public function handleWritable() } $this->readPending = true; - $this->loop->addReadStream($this->socket, array($this, 'handleRead')); + Loop::get()->addReadStream($this->socket, array($this, 'handleRead')); } $errno = 0; @@ -271,7 +267,7 @@ public function handleWritable() if (isset($this->writeBuffer[$written])) { $this->writeBuffer = \substr($this->writeBuffer, $written); } else { - $this->loop->removeWriteStream($this->socket); + Loop::get()->removeWriteStream($this->socket); $this->writePending = false; $this->writeBuffer = ''; } @@ -336,18 +332,18 @@ public function closeError($reason, $code = 0) { $this->readBuffer = ''; if ($this->readPending) { - $this->loop->removeReadStream($this->socket); + Loop::get()->removeReadStream($this->socket); $this->readPending = false; } $this->writeBuffer = ''; if ($this->writePending) { - $this->loop->removeWriteStream($this->socket); + Loop::get()->removeWriteStream($this->socket); $this->writePending = false; } if ($this->idleTimer !== null) { - $this->loop->cancelTimer($this->idleTimer); + Loop::get()->cancelTimer($this->idleTimer); $this->idleTimer = null; } @@ -370,7 +366,7 @@ public function checkIdle() { if ($this->idleTimer === null && !$this->names) { $that = $this; - $this->idleTimer = $this->loop->addTimer($this->idlePeriod, function () use ($that) { + $this->idleTimer = Loop::get()->addTimer($this->idlePeriod, function () use ($that) { $that->closeError('Idle timeout'); }); } diff --git a/src/Query/TimeoutExecutor.php b/src/Query/TimeoutExecutor.php index 06c51b15..b05695d1 100644 --- a/src/Query/TimeoutExecutor.php +++ b/src/Query/TimeoutExecutor.php @@ -3,19 +3,16 @@ namespace React\Dns\Query; use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; use React\Promise\Promise; final class TimeoutExecutor implements ExecutorInterface { private $executor; - private $loop; private $timeout; - public function __construct(ExecutorInterface $executor, $timeout, LoopInterface $loop = null) + public function __construct(ExecutorInterface $executor, $timeout) { $this->executor = $executor; - $this->loop = $loop ?: Loop::get(); $this->timeout = $timeout; } @@ -23,19 +20,18 @@ public function query(Query $query) { $promise = $this->executor->query($query); - $loop = $this->loop; $time = $this->timeout; - return new Promise(function ($resolve, $reject) use ($loop, $time, $promise, $query) { + return new Promise(function ($resolve, $reject) use ($time, $promise, $query) { $timer = null; - $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { + $promise = $promise->then(function ($v) use (&$timer, $resolve) { if ($timer) { - $loop->cancelTimer($timer); + Loop::get()->cancelTimer($timer); } $timer = false; $resolve($v); - }, function ($v) use (&$timer, $loop, $reject) { + }, function ($v) use (&$timer, $reject) { if ($timer) { - $loop->cancelTimer($timer); + Loop::get()->cancelTimer($timer); } $timer = false; $reject($v); @@ -47,7 +43,7 @@ public function query(Query $query) } // start timeout timer which will cancel the pending promise - $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject, $query) { + $timer = Loop::get()->addTimer($time, function () use ($time, &$promise, $reject, $query) { $reject(new TimeoutException( 'DNS query for ' . $query->describe() . ' timed out' )); diff --git a/src/Query/UdpTransportExecutor.php b/src/Query/UdpTransportExecutor.php index 30a3d705..e6dcce37 100644 --- a/src/Query/UdpTransportExecutor.php +++ b/src/Query/UdpTransportExecutor.php @@ -6,7 +6,6 @@ use React\Dns\Protocol\BinaryDumper; use React\Dns\Protocol\Parser; use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; use React\Promise\Deferred; /** @@ -83,7 +82,6 @@ final class UdpTransportExecutor implements ExecutorInterface { private $nameserver; - private $loop; private $parser; private $dumper; @@ -95,10 +93,9 @@ final class UdpTransportExecutor implements ExecutorInterface private $maxPacketSize = 512; /** - * @param string $nameserver - * @param ?LoopInterface $loop + * @param string $nameserver */ - public function __construct($nameserver, LoopInterface $loop = null) + public function __construct($nameserver) { if (\strpos($nameserver, '[') === false && \substr_count($nameserver, ':') >= 2 && \strpos($nameserver, '://') === false) { // several colons, but not enclosed in square brackets => enclose IPv6 address in square brackets @@ -111,7 +108,6 @@ public function __construct($nameserver, LoopInterface $loop = null) } $this->nameserver = 'udp://' . $parts['host'] . ':' . (isset($parts['port']) ? $parts['port'] : 53); - $this->loop = $loop ?: Loop::get(); $this->parser = new Parser(); $this->dumper = new BinaryDumper(); } @@ -163,10 +159,9 @@ public function query(Query $query) )); } - $loop = $this->loop; - $deferred = new Deferred(function () use ($loop, $socket, $query) { + $deferred = new Deferred(function () use ($socket, $query) { // cancellation should remove socket from loop and close socket - $loop->removeReadStream($socket); + Loop::get()->removeReadStream($socket); \fclose($socket); throw new CancellationException('DNS query for ' . $query->describe() . ' has been cancelled'); @@ -175,7 +170,7 @@ public function query(Query $query) $max = $this->maxPacketSize; $parser = $this->parser; $nameserver = $this->nameserver; - $loop->addReadStream($socket, function ($socket) use ($loop, $deferred, $query, $parser, $request, $max, $nameserver) { + Loop::get()->addReadStream($socket, function ($socket) use ($deferred, $query, $parser, $request, $max, $nameserver) { // try to read a single data packet from the DNS server // ignoring any errors, this is uses UDP packets and not a stream of data $data = @\fread($socket, $max); @@ -198,7 +193,7 @@ public function query(Query $query) } // we only react to the first valid message, so remove socket from loop and close - $loop->removeReadStream($socket); + Loop::get()->removeReadStream($socket); \fclose($socket); if ($response->tc) { diff --git a/src/Resolver/Factory.php b/src/Resolver/Factory.php index 5fe608cb..74695514 100644 --- a/src/Resolver/Factory.php +++ b/src/Resolver/Factory.php @@ -16,8 +16,6 @@ use React\Dns\Query\TcpTransportExecutor; use React\Dns\Query\TimeoutExecutor; use React\Dns\Query\UdpTransportExecutor; -use React\EventLoop\Loop; -use React\EventLoop\LoopInterface; final class Factory { @@ -31,14 +29,13 @@ final class Factory * tertiary DNS server. * * @param Config|string $config DNS Config object (recommended) or single nameserver address - * @param ?LoopInterface $loop * @return \React\Dns\Resolver\ResolverInterface * @throws \InvalidArgumentException for invalid DNS server address * @throws \UnderflowException when given DNS Config object has an empty list of nameservers */ - public function create($config, LoopInterface $loop = null) + public function create($config) { - $executor = $this->decorateHostsFileExecutor($this->createExecutor($config, $loop ?: Loop::get())); + $executor = $this->decorateHostsFileExecutor($this->createExecutor($config)); return new Resolver($executor); } @@ -53,20 +50,19 @@ public function create($config, LoopInterface $loop = null) * tertiary DNS server. * * @param Config|string $config DNS Config object (recommended) or single nameserver address - * @param ?LoopInterface $loop * @param ?CacheInterface $cache * @return \React\Dns\Resolver\ResolverInterface * @throws \InvalidArgumentException for invalid DNS server address * @throws \UnderflowException when given DNS Config object has an empty list of nameservers */ - public function createCached($config, LoopInterface $loop = null, CacheInterface $cache = null) + public function createCached($config, CacheInterface $cache = null) { // default to keeping maximum of 256 responses in cache unless explicitly given if (!($cache instanceof CacheInterface)) { $cache = new ArrayCache(256); } - $executor = $this->createExecutor($config, $loop ?: Loop::get()); + $executor = $this->createExecutor($config); $executor = new CachingExecutor($executor, $cache); $executor = $this->decorateHostsFileExecutor($executor); @@ -105,12 +101,11 @@ private function decorateHostsFileExecutor(ExecutorInterface $executor) /** * @param Config|string $nameserver - * @param LoopInterface $loop * @return CoopExecutor * @throws \InvalidArgumentException for invalid DNS server address * @throws \UnderflowException when given DNS Config object has an empty list of nameservers */ - private function createExecutor($nameserver, LoopInterface $loop) + private function createExecutor($nameserver) { if ($nameserver instanceof Config) { if (!$nameserver->nameservers) { @@ -128,10 +123,10 @@ private function createExecutor($nameserver, LoopInterface $loop) return new CoopExecutor( new RetryExecutor( new FallbackExecutor( - $this->createSingleExecutor($primary, $loop), + $this->createSingleExecutor($primary), new FallbackExecutor( - $this->createSingleExecutor($secondary, $loop), - $this->createSingleExecutor($tertiary, $loop) + $this->createSingleExecutor($secondary), + $this->createSingleExecutor($tertiary) ) ) ) @@ -141,8 +136,8 @@ private function createExecutor($nameserver, LoopInterface $loop) return new CoopExecutor( new RetryExecutor( new FallbackExecutor( - $this->createSingleExecutor($primary, $loop), - $this->createSingleExecutor($secondary, $loop) + $this->createSingleExecutor($primary), + $this->createSingleExecutor($secondary) ) ) ); @@ -152,27 +147,26 @@ private function createExecutor($nameserver, LoopInterface $loop) } } - return new CoopExecutor(new RetryExecutor($this->createSingleExecutor($nameserver, $loop))); + return new CoopExecutor(new RetryExecutor($this->createSingleExecutor($nameserver))); } /** * @param string $nameserver - * @param LoopInterface $loop * @return ExecutorInterface * @throws \InvalidArgumentException for invalid DNS server address */ - private function createSingleExecutor($nameserver, LoopInterface $loop) + private function createSingleExecutor($nameserver) { $parts = \parse_url($nameserver); if (isset($parts['scheme']) && $parts['scheme'] === 'tcp') { - $executor = $this->createTcpExecutor($nameserver, $loop); + $executor = $this->createTcpExecutor($nameserver); } elseif (isset($parts['scheme']) && $parts['scheme'] === 'udp') { - $executor = $this->createUdpExecutor($nameserver, $loop); + $executor = $this->createUdpExecutor($nameserver); } else { $executor = new SelectiveTransportExecutor( - $this->createUdpExecutor($nameserver, $loop), - $this->createTcpExecutor($nameserver, $loop) + $this->createUdpExecutor($nameserver), + $this->createTcpExecutor($nameserver) ); } @@ -181,34 +175,29 @@ private function createSingleExecutor($nameserver, LoopInterface $loop) /** * @param string $nameserver - * @param LoopInterface $loop * @return TimeoutExecutor * @throws \InvalidArgumentException for invalid DNS server address */ - private function createTcpExecutor($nameserver, LoopInterface $loop) + private function createTcpExecutor($nameserver) { return new TimeoutExecutor( - new TcpTransportExecutor($nameserver, $loop), - 5.0, - $loop + new TcpTransportExecutor($nameserver), + 5.0 ); } /** * @param string $nameserver - * @param LoopInterface $loop * @return TimeoutExecutor * @throws \InvalidArgumentException for invalid DNS server address */ - private function createUdpExecutor($nameserver, LoopInterface $loop) + private function createUdpExecutor($nameserver) { return new TimeoutExecutor( new UdpTransportExecutor( - $nameserver, - $loop + $nameserver ), - 5.0, - $loop + 5.0 ); } } diff --git a/tests/Query/TcpTransportExecutorTest.php b/tests/Query/TcpTransportExecutorTest.php index 33dddacd..4938cf35 100644 --- a/tests/Query/TcpTransportExecutorTest.php +++ b/tests/Query/TcpTransportExecutorTest.php @@ -8,10 +8,16 @@ use React\Dns\Query\Query; use React\Dns\Query\TcpTransportExecutor; use React\EventLoop\Loop; +use React\EventLoop\StreamSelectLoop; use React\Tests\Dns\TestCase; class TcpTransportExecutorTest extends TestCase { + public function setUp(): void + { + Loop::set(new StreamSelectLoop()); + } + /** * @dataProvider provideDefaultPortProvider * @param string $input @@ -19,9 +25,9 @@ class TcpTransportExecutorTest extends TestCase */ public function testCtorShouldAcceptNameserverAddresses($input, $expected) { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); - $executor = new TcpTransportExecutor($input, $loop); + $executor = new TcpTransportExecutor($input); $ref = new \ReflectionProperty($executor, 'nameserver'); $ref->setAccessible(true); @@ -60,47 +66,37 @@ public static function provideDefaultPortProvider() ); } - public function testCtorWithoutLoopShouldAssignDefaultLoop() - { - $executor = new TcpTransportExecutor('127.0.0.1'); - - $ref = new \ReflectionProperty($executor, 'loop'); - $ref->setAccessible(true); - $loop = $ref->getValue($executor); - - $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); - } - public function testCtorShouldThrowWhenNameserverAddressIsInvalid() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $this->setExpectedException('InvalidArgumentException'); - new TcpTransportExecutor('///', $loop); + new TcpTransportExecutor('///'); } public function testCtorShouldThrowWhenNameserverAddressContainsHostname() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $this->setExpectedException('InvalidArgumentException'); - new TcpTransportExecutor('localhost', $loop); + new TcpTransportExecutor('localhost'); } public function testCtorShouldThrowWhenNameserverSchemeIsInvalid() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $this->setExpectedException('InvalidArgumentException'); - new TcpTransportExecutor('udp://1.2.3.4', $loop); + new TcpTransportExecutor('udp://1.2.3.4'); } public function testQueryRejectsIfMessageExceedsMaximumMessageSize() { $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addWriteStream'); + Loop::set($loop); - $executor = new TcpTransportExecutor('8.8.8.8:53', $loop); + $executor = new TcpTransportExecutor('8.8.8.8:53'); $query = new Query('google.' . str_repeat('.com', 60000), Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); @@ -123,8 +119,9 @@ public function testQueryRejectsIfServerConnectionFails() $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addWriteStream'); + Loop::set($loop); - $executor = new TcpTransportExecutor('::1', $loop); + $executor = new TcpTransportExecutor('::1'); $ref = new \ReflectionProperty($executor, 'nameserver'); $ref->setAccessible(true); @@ -154,11 +151,12 @@ public function testQueryRejectsOnCancellationWithoutClosingSocketButStartsIdleT $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything())->willReturn($timer); $loop->expects($this->never())->method('cancelTimer'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); @@ -189,11 +187,12 @@ public function testTriggerIdleTimerAfterQueryRejectedOnCancellationWillCloseSoc return true; }))->willReturn($timer); $loop->expects($this->once())->method('cancelTimer')->with($timer); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); @@ -217,11 +216,12 @@ public function testQueryRejectsOnCancellationWithoutClosingSocketAndWithoutStar $loop->expects($this->never())->method('addTimer'); $loop->expects($this->never())->method('cancelTimer'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); $promise1 = $executor->query($query); @@ -239,11 +239,12 @@ public function testQueryAgainAfterPreviousWasCancelledReusesExistingSocket() $loop->expects($this->never())->method('removeWriteStream'); $loop->expects($this->never())->method('addReadStream'); $loop->expects($this->never())->method('removeReadStream'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); @@ -284,11 +285,12 @@ public function testQueryStaysPendingWhenClientCanNotSendExcessiveMessageInOneCh $loop->expects($this->once())->method('addReadStream'); $loop->expects($this->never())->method('removeWriteStream'); $loop->expects($this->never())->method('removeReadStream'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google' . str_repeat('.com', 100), Message::TYPE_A, Message::CLASS_IN); @@ -327,11 +329,12 @@ public function testQueryStaysPendingWhenClientCanNotSendExcessiveMessageInOneCh $loop->expects($this->once())->method('addReadStream'); $loop->expects($this->never())->method('removeWriteStream'); $loop->expects($this->never())->method('removeReadStream'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google' . str_repeat('.com', 100), Message::TYPE_A, Message::CLASS_IN); @@ -361,11 +364,12 @@ public function testQueryRejectsWhenClientKeepsSendingWhenServerClosesSocketWith $loop->expects($this->once())->method('addReadStream'); $loop->expects($this->once())->method('removeWriteStream'); $loop->expects($this->once())->method('removeReadStream'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google' . str_repeat('.com', 100), Message::TYPE_A, Message::CLASS_IN); @@ -567,7 +571,7 @@ public function testQueryRejectsWhenServerSendsInvalidId() Loop::removeReadStream($client); $data = fread($client, 512); - list(, $length) = unpack('n', substr($data, 0, 2)); + [, $length] = unpack('n', substr($data, 0, 2)); assert(strlen($data) - 2 === $length); $data = substr($data, 2); @@ -619,7 +623,7 @@ public function testQueryRejectsIfServerSendsTruncatedResponse() Loop::removeReadStream($client); $data = fread($client, 512); - list(, $length) = unpack('n', substr($data, 0, 2)); + [, $length] = unpack('n', substr($data, 0, 2)); assert(strlen($data) - 2 === $length); $data = substr($data, 2); @@ -668,7 +672,7 @@ public function testQueryResolvesIfServerSendsValidResponse() Loop::removeReadStream($client); $data = fread($client, 512); - list(, $length) = unpack('n', substr($data, 0, 2)); + [, $length] = unpack('n', substr($data, 0, 2)); assert(strlen($data) - 2 === $length); fwrite($client, $data); @@ -699,10 +703,11 @@ public function testQueryRejectsIfSocketIsClosedAfterPreviousQueryThatWasStillPe $loop->expects($this->never())->method('addTimer'); $loop->expects($this->never())->method('cancelTimer'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); @@ -733,10 +738,11 @@ public function testQueryResolvesIfServerSendsBackResponseMessageAndWillStartIdl $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything()); $loop->expects($this->never())->method('cancelTimer'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); @@ -767,10 +773,11 @@ public function testQueryResolvesIfServerSendsBackResponseMessageAfterCancelling $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything())->willReturn($timer); $loop->expects($this->never())->method('cancelTimer'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); @@ -801,10 +808,11 @@ public function testQueryResolvesIfServerSendsBackResponseMessageAfterCancelling $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything()); $loop->expects($this->never())->method('cancelTimer'); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); @@ -842,10 +850,11 @@ public function testTriggerIdleTimerAfterPreviousQueryResolvedWillCloseIdleSocke return true; }))->willReturn($timer); $loop->expects($this->once())->method('cancelTimer')->with($timer); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); @@ -880,10 +889,11 @@ public function testClosingConnectionAfterPreviousQueryResolvedWillCancelIdleTim $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything())->willReturn($timer); $loop->expects($this->once())->method('cancelTimer')->with($timer); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); @@ -918,10 +928,11 @@ public function testQueryAgainAfterPreviousQueryResolvedWillReuseSocketAndCancel $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(0.001, $this->anything())->willReturn($timer); $loop->expects($this->once())->method('cancelTimer')->with($timer); + Loop::set($loop); $server = stream_socket_server('tcp://127.0.0.1:0'); $address = stream_socket_get_name($server, false); - $executor = new TcpTransportExecutor($address, $loop); + $executor = new TcpTransportExecutor($address); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); diff --git a/tests/Query/TimeoutExecutorTest.php b/tests/Query/TimeoutExecutorTest.php index b7857783..faf0ae77 100644 --- a/tests/Query/TimeoutExecutorTest.php +++ b/tests/Query/TimeoutExecutorTest.php @@ -7,6 +7,7 @@ use React\Dns\Query\Query; use React\Dns\Query\TimeoutException; use React\Dns\Query\TimeoutExecutor; +use React\EventLoop\Loop; use React\Promise; use React\Promise\Deferred; use React\Tests\Dns\TestCase; @@ -25,19 +26,9 @@ public function setUpExecutor() $this->wrapped = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock(); $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->loop); - $this->executor = new TimeoutExecutor($this->wrapped, 5.0, $this->loop); - } - - public function testCtorWithoutLoopShouldAssignDefaultLoop() - { - $executor = new TimeoutExecutor($this->executor, 5.0); - - $ref = new \ReflectionProperty($executor, 'loop'); - $ref->setAccessible(true); - $loop = $ref->getValue($executor); - - $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); + $this->executor = new TimeoutExecutor($this->wrapped, 5.0); } public function testCancellingPromiseWillCancelWrapped() diff --git a/tests/Query/UdpTransportExecutorTest.php b/tests/Query/UdpTransportExecutorTest.php index 3f04d9ad..bb8893d9 100644 --- a/tests/Query/UdpTransportExecutorTest.php +++ b/tests/Query/UdpTransportExecutorTest.php @@ -19,9 +19,9 @@ class UdpTransportExecutorTest extends TestCase */ public function testCtorShouldAcceptNameserverAddresses($input, $expected) { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); - $executor = new UdpTransportExecutor($input, $loop); + $executor = new UdpTransportExecutor($input); $ref = new \ReflectionProperty($executor, 'nameserver'); $ref->setAccessible(true); @@ -60,47 +60,37 @@ public static function provideDefaultPortProvider() ); } - public function testCtorWithoutLoopShouldAssignDefaultLoop() - { - $executor = new UdpTransportExecutor('127.0.0.1'); - - $ref = new \ReflectionProperty($executor, 'loop'); - $ref->setAccessible(true); - $loop = $ref->getValue($executor); - - $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); - } - public function testCtorShouldThrowWhenNameserverAddressIsInvalid() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $this->setExpectedException('InvalidArgumentException'); - new UdpTransportExecutor('///', $loop); + new UdpTransportExecutor('///'); } public function testCtorShouldThrowWhenNameserverAddressContainsHostname() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $this->setExpectedException('InvalidArgumentException'); - new UdpTransportExecutor('localhost', $loop); + new UdpTransportExecutor('localhost'); } public function testCtorShouldThrowWhenNameserverSchemeIsInvalid() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $this->setExpectedException('InvalidArgumentException'); - new UdpTransportExecutor('tcp://1.2.3.4', $loop); + new UdpTransportExecutor('tcp://1.2.3.4'); } public function testQueryRejectsIfMessageExceedsUdpSize() { $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addReadStream'); + Loop::set($loop); - $executor = new UdpTransportExecutor('8.8.8.8:53', $loop); + $executor = new UdpTransportExecutor('8.8.8.8:53'); $query = new Query('google.' . str_repeat('.com', 200), Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); @@ -128,8 +118,9 @@ public function testQueryRejectsIfServerConnectionFails() $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addReadStream'); + Loop::set($loop); - $executor = new UdpTransportExecutor('::1', $loop); + $executor = new UdpTransportExecutor('::1'); $ref = new \ReflectionProperty($executor, 'nameserver'); $ref->setAccessible(true); @@ -156,8 +147,9 @@ public function testQueryRejectsIfSendToServerFailsAfterConnectionWithoutCalling { $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addReadStream'); + Loop::set($loop); - $executor = new UdpTransportExecutor('0.0.0.0', $loop); + $executor = new UdpTransportExecutor('0.0.0.0'); // increase hard-coded maximum packet size to allow sending excessive data $ref = new \ReflectionProperty($executor, 'maxPacketSize'); @@ -202,8 +194,9 @@ public function testQueryKeepsPendingIfReadFailsBecauseServerRefusesConnection() $callback = $ref; return true; })); + Loop::set($loop); - $executor = new UdpTransportExecutor('0.0.0.0', $loop); + $executor = new UdpTransportExecutor('0.0.0.0'); $query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); @@ -231,8 +224,9 @@ public function testQueryRejectsOnCancellation() $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addReadStream'); $loop->expects($this->once())->method('removeReadStream'); + Loop::set($loop); - $executor = new UdpTransportExecutor('8.8.8.8:53', $loop); + $executor = new UdpTransportExecutor('8.8.8.8:53'); $query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN); $promise = $executor->query($query); diff --git a/tests/Resolver/FactoryTest.php b/tests/Resolver/FactoryTest.php index af758b51..b77d94ee 100644 --- a/tests/Resolver/FactoryTest.php +++ b/tests/Resolver/FactoryTest.php @@ -5,6 +5,7 @@ use React\Dns\Config\Config; use React\Dns\Query\HostsFileExecutor; use React\Dns\Resolver\Factory; +use React\EventLoop\Loop; use React\Tests\Dns\TestCase; class FactoryTest extends TestCase @@ -21,10 +22,10 @@ public function createShouldCreateResolver() /** @test */ public function createWithoutSchemeShouldCreateResolverWithSelectiveUdpAndTcpExecutorStack() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $factory = new Factory(); - $resolver = $factory->create('8.8.8.8:53', $loop); + $resolver = $factory->create('8.8.8.8:53'); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); @@ -76,10 +77,10 @@ public function createWithoutSchemeShouldCreateResolverWithSelectiveUdpAndTcpExe /** @test */ public function createWithUdpSchemeShouldCreateResolverWithUdpExecutorStack() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $factory = new Factory(); - $resolver = $factory->create('udp://8.8.8.8:53', $loop); + $resolver = $factory->create('udp://8.8.8.8:53'); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); @@ -109,10 +110,10 @@ public function createWithUdpSchemeShouldCreateResolverWithUdpExecutorStack() /** @test */ public function createWithTcpSchemeShouldCreateResolverWithTcpExecutorStack() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $factory = new Factory(); - $resolver = $factory->create('tcp://8.8.8.8:53', $loop); + $resolver = $factory->create('tcp://8.8.8.8:53'); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); @@ -142,13 +143,13 @@ public function createWithTcpSchemeShouldCreateResolverWithTcpExecutorStack() /** @test */ public function createWithConfigWithTcpNameserverSchemeShouldCreateResolverWithTcpExecutorStack() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $config = new Config(); $config->nameservers[] = 'tcp://8.8.8.8:53'; $factory = new Factory(); - $resolver = $factory->create($config, $loop); + $resolver = $factory->create($config); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); @@ -178,14 +179,14 @@ public function createWithConfigWithTcpNameserverSchemeShouldCreateResolverWithT /** @test */ public function createWithConfigWithTwoNameserversWithTcpSchemeShouldCreateResolverWithFallbackExecutorStack() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $config = new Config(); $config->nameservers[] = 'tcp://8.8.8.8:53'; $config->nameservers[] = 'tcp://1.1.1.1:53'; $factory = new Factory(); - $resolver = $factory->create($config, $loop); + $resolver = $factory->create($config); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); @@ -245,7 +246,7 @@ public function createWithConfigWithTwoNameserversWithTcpSchemeShouldCreateResol /** @test */ public function createWithConfigWithThreeNameserversWithTcpSchemeShouldCreateResolverWithNestedFallbackExecutorStack() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $config = new Config(); $config->nameservers[] = 'tcp://8.8.8.8:53'; @@ -253,7 +254,7 @@ public function createWithConfigWithThreeNameserversWithTcpSchemeShouldCreateRes $config->nameservers[] = 'tcp://9.9.9.9:53'; $factory = new Factory(); - $resolver = $factory->create($config, $loop); + $resolver = $factory->create($config); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); @@ -337,29 +338,29 @@ public function createWithConfigWithThreeNameserversWithTcpSchemeShouldCreateRes /** @test */ public function createShouldThrowWhenNameserverIsInvalid() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $factory = new Factory(); $this->setExpectedException('InvalidArgumentException'); - $factory->create('///', $loop); + $factory->create('///'); } /** @test */ public function createShouldThrowWhenConfigHasNoNameservers() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $factory = new Factory(); $this->setExpectedException('UnderflowException'); - $factory->create(new Config(), $loop); + $factory->create(new Config()); } /** @test */ public function createShouldThrowWhenConfigHasInvalidNameserver() { - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($this->getMockBuilder('React\EventLoop\LoopInterface')->getMock()); $factory = new Factory(); @@ -367,7 +368,7 @@ public function createShouldThrowWhenConfigHasInvalidNameserver() $config->nameservers[] = '///'; $this->setExpectedException('InvalidArgumentException'); - $factory->create($config, $loop); + $factory->create($config); } /** @test */ @@ -388,9 +389,10 @@ public function createCachedShouldCreateResolverWithCachingExecutorWithCustomCac { $cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + Loop::set($loop); $factory = new Factory(); - $resolver = $factory->createCached('8.8.8.8:53', $loop, $cache); + $resolver = $factory->createCached('8.8.8.8:53', $cache); $this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver); $executor = $this->getResolverPrivateExecutor($resolver);