init
This commit is contained in:
10
vendor/react/dns/tests/CallableStub.php
vendored
Executable file
10
vendor/react/dns/tests/CallableStub.php
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns;
|
||||
|
||||
class CallableStub
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
}
|
||||
}
|
||||
189
vendor/react/dns/tests/Config/ConfigTest.php
vendored
Executable file
189
vendor/react/dns/tests/Config/ConfigTest.php
vendored
Executable file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Config;
|
||||
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\Config\Config;
|
||||
|
||||
class ConfigTest extends TestCase
|
||||
{
|
||||
public function testLoadsSystemDefault()
|
||||
{
|
||||
$config = Config::loadSystemConfigBlocking();
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Config\Config', $config);
|
||||
}
|
||||
|
||||
public function testLoadsDefaultPath()
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
$this->markTestSkipped('Not supported on Windows');
|
||||
}
|
||||
|
||||
$config = Config::loadResolvConfBlocking();
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Config\Config', $config);
|
||||
}
|
||||
|
||||
public function testLoadsFromExplicitPath()
|
||||
{
|
||||
$config = Config::loadResolvConfBlocking(__DIR__ . '/../Fixtures/etc/resolv.conf');
|
||||
|
||||
$this->assertEquals(array('8.8.8.8'), $config->nameservers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testLoadThrowsWhenPathIsInvalid()
|
||||
{
|
||||
Config::loadResolvConfBlocking(__DIR__ . '/invalid.conf');
|
||||
}
|
||||
|
||||
public function testParsesSingleEntryFile()
|
||||
{
|
||||
$contents = 'nameserver 8.8.8.8';
|
||||
$expected = array('8.8.8.8');
|
||||
|
||||
$config = Config::loadResolvConfBlocking('data://text/plain;base64,' . base64_encode($contents));
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testParsesNameserverEntriesFromAverageFileCorrectly()
|
||||
{
|
||||
$contents = '#
|
||||
# Mac OS X Notice
|
||||
#
|
||||
# This file is not used by the host name and address resolution
|
||||
# or the DNS query routing mechanisms used by most processes on
|
||||
# this Mac OS X system.
|
||||
#
|
||||
# This file is automatically generated.
|
||||
#
|
||||
domain v.cablecom.net
|
||||
nameserver 127.0.0.1
|
||||
nameserver ::1
|
||||
';
|
||||
$expected = array('127.0.0.1', '::1');
|
||||
|
||||
$config = Config::loadResolvConfBlocking('data://text/plain;base64,' . base64_encode($contents));
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testParsesEmptyFileWithoutNameserverEntries()
|
||||
{
|
||||
$contents = '';
|
||||
$expected = array();
|
||||
|
||||
$config = Config::loadResolvConfBlocking('data://text/plain;base64,');
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testParsesFileAndIgnoresCommentsAndInvalidNameserverEntries()
|
||||
{
|
||||
$contents = '
|
||||
# nameserver 1.2.3.4
|
||||
; nameserver 2.3.4.5
|
||||
|
||||
nameserver 3.4.5.6 # nope
|
||||
nameserver 4.5.6.7 5.6.7.8
|
||||
nameserver 6.7.8.9
|
||||
NameServer 7.8.9.10
|
||||
';
|
||||
$expected = array();
|
||||
|
||||
$config = Config::loadResolvConfBlocking('data://text/plain;base64,' . base64_encode($contents));
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testLoadsFromWmicOnWindows()
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR !== '\\') {
|
||||
$this->markTestSkipped('Only on Windows');
|
||||
}
|
||||
|
||||
$config = Config::loadWmicBlocking();
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Config\Config', $config);
|
||||
}
|
||||
|
||||
public function testLoadsSingleEntryFromWmicOutput()
|
||||
{
|
||||
$contents = '
|
||||
Node,DNSServerSearchOrder
|
||||
ACE,
|
||||
ACE,{192.168.2.1}
|
||||
ACE,
|
||||
';
|
||||
$expected = array('192.168.2.1');
|
||||
|
||||
$config = Config::loadWmicBlocking($this->echoCommand($contents));
|
||||
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testLoadsEmptyListFromWmicOutput()
|
||||
{
|
||||
$contents = '
|
||||
Node,DNSServerSearchOrder
|
||||
ACE,
|
||||
';
|
||||
$expected = array();
|
||||
|
||||
$config = Config::loadWmicBlocking($this->echoCommand($contents));
|
||||
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testLoadsSingleEntryForMultipleNicsFromWmicOutput()
|
||||
{
|
||||
$contents = '
|
||||
Node,DNSServerSearchOrder
|
||||
ACE,
|
||||
ACE,{192.168.2.1}
|
||||
ACE,
|
||||
ACE,{192.168.2.2}
|
||||
ACE,
|
||||
';
|
||||
$expected = array('192.168.2.1', '192.168.2.2');
|
||||
|
||||
$config = Config::loadWmicBlocking($this->echoCommand($contents));
|
||||
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testLoadsMultipleEntriesForSingleNicWithSemicolonFromWmicOutput()
|
||||
{
|
||||
$contents = '
|
||||
Node,DNSServerSearchOrder
|
||||
ACE,
|
||||
ACE,{192.168.2.1;192.168.2.2}
|
||||
ACE,
|
||||
';
|
||||
$expected = array('192.168.2.1', '192.168.2.2');
|
||||
|
||||
$config = Config::loadWmicBlocking($this->echoCommand($contents));
|
||||
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
public function testLoadsMultipleEntriesForSingleNicWithQuotesFromWmicOutput()
|
||||
{
|
||||
$contents = '
|
||||
Node,DNSServerSearchOrder
|
||||
ACE,
|
||||
ACE,{"192.168.2.1","192.168.2.2"}
|
||||
ACE,
|
||||
';
|
||||
$expected = array('192.168.2.1', '192.168.2.2');
|
||||
|
||||
$config = Config::loadWmicBlocking($this->echoCommand($contents));
|
||||
|
||||
$this->assertEquals($expected, $config->nameservers);
|
||||
}
|
||||
|
||||
private function echoCommand($output)
|
||||
{
|
||||
return 'echo ' . escapeshellarg($output);
|
||||
}
|
||||
}
|
||||
70
vendor/react/dns/tests/Config/FilesystemFactoryTest.php
vendored
Executable file
70
vendor/react/dns/tests/Config/FilesystemFactoryTest.php
vendored
Executable file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace React\Test\Dns\Config;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\Dns\Config\FilesystemFactory;
|
||||
|
||||
class FilesystemFactoryTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
public function parseEtcResolvConfShouldParseCorrectly()
|
||||
{
|
||||
$contents = '#
|
||||
# Mac OS X Notice
|
||||
#
|
||||
# This file is not used by the host name and address resolution
|
||||
# or the DNS query routing mechanisms used by most processes on
|
||||
# this Mac OS X system.
|
||||
#
|
||||
# This file is automatically generated.
|
||||
#
|
||||
domain v.cablecom.net
|
||||
nameserver 127.0.0.1
|
||||
nameserver 8.8.8.8
|
||||
';
|
||||
$expected = array('127.0.0.1', '8.8.8.8');
|
||||
|
||||
$capturedConfig = null;
|
||||
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
$factory = new FilesystemFactory($loop);
|
||||
$factory->parseEtcResolvConf($contents)->then(function ($config) use (&$capturedConfig) {
|
||||
$capturedConfig = $config;
|
||||
});
|
||||
|
||||
$this->assertNotNull($capturedConfig);
|
||||
$this->assertSame($expected, $capturedConfig->nameservers);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function createShouldLoadStuffFromFilesystem()
|
||||
{
|
||||
$this->markTestIncomplete('Filesystem API is incomplete');
|
||||
|
||||
$expected = array('8.8.8.8');
|
||||
|
||||
$triggerListener = null;
|
||||
$capturedConfig = null;
|
||||
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
$loop
|
||||
->expects($this->once())
|
||||
->method('addReadStream')
|
||||
->will($this->returnCallback(function ($stream, $listener) use (&$triggerListener) {
|
||||
$triggerListener = function () use ($stream, $listener) {
|
||||
call_user_func($listener, $stream);
|
||||
};
|
||||
}));
|
||||
|
||||
$factory = new FilesystemFactory($loop);
|
||||
$factory->create(__DIR__.'/../Fixtures/etc/resolv.conf')->then(function ($config) use (&$capturedConfig) {
|
||||
$capturedConfig = $config;
|
||||
});
|
||||
|
||||
$triggerListener();
|
||||
|
||||
$this->assertNotNull($capturedConfig);
|
||||
$this->assertSame($expected, $capturedConfig->nameservers);
|
||||
}
|
||||
}
|
||||
170
vendor/react/dns/tests/Config/HostsFileTest.php
vendored
Executable file
170
vendor/react/dns/tests/Config/HostsFileTest.php
vendored
Executable file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Config;
|
||||
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\Config\HostsFile;
|
||||
|
||||
class HostsFileTest extends TestCase
|
||||
{
|
||||
public function testLoadsFromDefaultPath()
|
||||
{
|
||||
$hosts = HostsFile::loadFromPathBlocking();
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Config\HostsFile', $hosts);
|
||||
}
|
||||
|
||||
public function testDefaultShouldHaveLocalhostMapped()
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
$this->markTestSkipped('Not supported on Windows');
|
||||
}
|
||||
|
||||
$hosts = HostsFile::loadFromPathBlocking();
|
||||
|
||||
$this->assertContains('127.0.0.1', $hosts->getIpsForHost('localhost'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testLoadThrowsForInvalidPath()
|
||||
{
|
||||
HostsFile::loadFromPathBlocking('does/not/exist');
|
||||
}
|
||||
|
||||
public function testContainsSingleLocalhostEntry()
|
||||
{
|
||||
$hosts = new HostsFile('127.0.0.1 localhost');
|
||||
|
||||
$this->assertEquals(array('127.0.0.1'), $hosts->getIpsForHost('localhost'));
|
||||
$this->assertEquals(array(), $hosts->getIpsForHost('example.com'));
|
||||
}
|
||||
|
||||
public function testNonIpReturnsNothingForInvalidHosts()
|
||||
{
|
||||
$hosts = new HostsFile('a b');
|
||||
|
||||
$this->assertEquals(array(), $hosts->getIpsForHost('a'));
|
||||
$this->assertEquals(array(), $hosts->getIpsForHost('b'));
|
||||
}
|
||||
|
||||
public function testIgnoresIpv6ZoneId()
|
||||
{
|
||||
$hosts = new HostsFile('fe80::1%lo0 localhost');
|
||||
|
||||
$this->assertEquals(array('fe80::1'), $hosts->getIpsForHost('localhost'));
|
||||
}
|
||||
|
||||
public function testSkipsComments()
|
||||
{
|
||||
$hosts = new HostsFile('# start' . PHP_EOL .'#127.0.0.1 localhost' . PHP_EOL . '127.0.0.2 localhost # example.com');
|
||||
|
||||
$this->assertEquals(array('127.0.0.2'), $hosts->getIpsForHost('localhost'));
|
||||
$this->assertEquals(array(), $hosts->getIpsForHost('example.com'));
|
||||
}
|
||||
|
||||
public function testContainsSingleLocalhostEntryWithCaseIgnored()
|
||||
{
|
||||
$hosts = new HostsFile('127.0.0.1 LocalHost');
|
||||
|
||||
$this->assertEquals(array('127.0.0.1'), $hosts->getIpsForHost('LOCALHOST'));
|
||||
}
|
||||
|
||||
public function testEmptyFileContainsNothing()
|
||||
{
|
||||
$hosts = new HostsFile('');
|
||||
|
||||
$this->assertEquals(array(), $hosts->getIpsForHost('example.com'));
|
||||
}
|
||||
|
||||
public function testSingleEntryWithMultipleNames()
|
||||
{
|
||||
$hosts = new HostsFile('127.0.0.1 localhost example.com');
|
||||
|
||||
$this->assertEquals(array('127.0.0.1'), $hosts->getIpsForHost('example.com'));
|
||||
$this->assertEquals(array('127.0.0.1'), $hosts->getIpsForHost('localhost'));
|
||||
}
|
||||
|
||||
public function testMergesEntriesOverMultipleLines()
|
||||
{
|
||||
$hosts = new HostsFile("127.0.0.1 localhost\n127.0.0.2 localhost\n127.0.0.3 a localhost b\n127.0.0.4 a localhost");
|
||||
|
||||
$this->assertEquals(array('127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'), $hosts->getIpsForHost('localhost'));
|
||||
}
|
||||
|
||||
public function testMergesIpv4AndIpv6EntriesOverMultipleLines()
|
||||
{
|
||||
$hosts = new HostsFile("127.0.0.1 localhost\n::1 localhost");
|
||||
|
||||
$this->assertEquals(array('127.0.0.1', '::1'), $hosts->getIpsForHost('localhost'));
|
||||
}
|
||||
|
||||
public function testReverseLookup()
|
||||
{
|
||||
$hosts = new HostsFile('127.0.0.1 localhost');
|
||||
|
||||
$this->assertEquals(array('localhost'), $hosts->getHostsForIp('127.0.0.1'));
|
||||
$this->assertEquals(array(), $hosts->getHostsForIp('192.168.1.1'));
|
||||
}
|
||||
|
||||
public function testReverseSkipsComments()
|
||||
{
|
||||
$hosts = new HostsFile("# start\n#127.0.0.1 localhosted\n127.0.0.2\tlocalhost\t# example.com\n\t127.0.0.3\t\texample.org\t\t");
|
||||
|
||||
$this->assertEquals(array(), $hosts->getHostsForIp('127.0.0.1'));
|
||||
$this->assertEquals(array('localhost'), $hosts->getHostsForIp('127.0.0.2'));
|
||||
$this->assertEquals(array('example.org'), $hosts->getHostsForIp('127.0.0.3'));
|
||||
}
|
||||
|
||||
public function testReverseNonIpReturnsNothing()
|
||||
{
|
||||
$hosts = new HostsFile('127.0.0.1 localhost');
|
||||
|
||||
$this->assertEquals(array(), $hosts->getHostsForIp('localhost'));
|
||||
$this->assertEquals(array(), $hosts->getHostsForIp('127.0.0.1.1'));
|
||||
}
|
||||
|
||||
public function testReverseNonIpReturnsNothingForInvalidHosts()
|
||||
{
|
||||
$hosts = new HostsFile('a b');
|
||||
|
||||
$this->assertEquals(array(), $hosts->getHostsForIp('a'));
|
||||
$this->assertEquals(array(), $hosts->getHostsForIp('b'));
|
||||
}
|
||||
|
||||
public function testReverseLookupReturnsLowerCaseHost()
|
||||
{
|
||||
$hosts = new HostsFile('127.0.0.1 LocalHost');
|
||||
|
||||
$this->assertEquals(array('localhost'), $hosts->getHostsForIp('127.0.0.1'));
|
||||
}
|
||||
|
||||
public function testReverseLookupChecksNormalizedIpv6()
|
||||
{
|
||||
$hosts = new HostsFile('FE80::00a1 localhost');
|
||||
|
||||
$this->assertEquals(array('localhost'), $hosts->getHostsForIp('fe80::A1'));
|
||||
}
|
||||
|
||||
public function testReverseLookupIgnoresIpv6ZoneId()
|
||||
{
|
||||
$hosts = new HostsFile('fe80::1%lo0 localhost');
|
||||
|
||||
$this->assertEquals(array('localhost'), $hosts->getHostsForIp('fe80::1'));
|
||||
}
|
||||
|
||||
public function testReverseLookupReturnsMultipleHostsOverSingleLine()
|
||||
{
|
||||
$hosts = new HostsFile("::1 ip6-localhost ip6-loopback");
|
||||
|
||||
$this->assertEquals(array('ip6-localhost', 'ip6-loopback'), $hosts->getHostsForIp('::1'));
|
||||
}
|
||||
|
||||
public function testReverseLookupReturnsMultipleHostsOverMultipleLines()
|
||||
{
|
||||
$hosts = new HostsFile("::1 ip6-localhost\n::1 ip6-loopback");
|
||||
|
||||
$this->assertEquals(array('ip6-localhost', 'ip6-loopback'), $hosts->getHostsForIp('::1'));
|
||||
}
|
||||
}
|
||||
1
vendor/react/dns/tests/Fixtures/etc/resolv.conf
vendored
Executable file
1
vendor/react/dns/tests/Fixtures/etc/resolv.conf
vendored
Executable file
@@ -0,0 +1 @@
|
||||
nameserver 8.8.8.8
|
||||
171
vendor/react/dns/tests/FunctionalResolverTest.php
vendored
Executable file
171
vendor/react/dns/tests/FunctionalResolverTest.php
vendored
Executable file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns;
|
||||
|
||||
use React\EventLoop\Factory as LoopFactory;
|
||||
use React\Dns\Resolver\Factory;
|
||||
use React\Dns\RecordNotFoundException;
|
||||
use React\Dns\Model\Message;
|
||||
|
||||
class FunctionalTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->loop = LoopFactory::create();
|
||||
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->create('8.8.8.8', $this->loop);
|
||||
}
|
||||
|
||||
public function testResolveLocalhostResolves()
|
||||
{
|
||||
$promise = $this->resolver->resolve('localhost');
|
||||
$promise->then($this->expectCallableOnce(), $this->expectCallableNever());
|
||||
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
public function testResolveAllLocalhostResolvesWithArray()
|
||||
{
|
||||
$promise = $this->resolver->resolveAll('localhost', Message::TYPE_A);
|
||||
$promise->then($this->expectCallableOnceWith($this->isType('array')), $this->expectCallableNever());
|
||||
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group internet
|
||||
*/
|
||||
public function testResolveGoogleResolves()
|
||||
{
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
$promise->then($this->expectCallableOnce(), $this->expectCallableNever());
|
||||
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group internet
|
||||
*/
|
||||
public function testResolveAllGoogleMxResolvesWithCache()
|
||||
{
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->createCached('8.8.8.8', $this->loop);
|
||||
|
||||
$promise = $this->resolver->resolveAll('google.com', Message::TYPE_MX);
|
||||
$promise->then($this->expectCallableOnceWith($this->isType('array')), $this->expectCallableNever());
|
||||
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @group internet
|
||||
*/
|
||||
public function testResolveInvalidRejects()
|
||||
{
|
||||
$ex = $this->callback(function ($param) {
|
||||
return ($param instanceof RecordNotFoundException && $param->getCode() === Message::RCODE_NAME_ERROR);
|
||||
});
|
||||
|
||||
$promise = $this->resolver->resolve('example.invalid');
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnceWith($ex));
|
||||
|
||||
$this->loop->run();
|
||||
}
|
||||
|
||||
public function testResolveCancelledRejectsImmediately()
|
||||
{
|
||||
$ex = $this->callback(function ($param) {
|
||||
return ($param instanceof \RuntimeException && $param->getMessage() === 'DNS query for google.com has been cancelled');
|
||||
});
|
||||
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnceWith($ex));
|
||||
$promise->cancel();
|
||||
|
||||
$time = microtime(true);
|
||||
$this->loop->run();
|
||||
$time = microtime(true) - $time;
|
||||
|
||||
$this->assertLessThan(0.1, $time);
|
||||
}
|
||||
|
||||
public function testInvalidResolverDoesNotResolveGoogle()
|
||||
{
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->create('255.255.255.255', $this->loop);
|
||||
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testResolveShouldNotCauseGarbageReferencesWhenUsingInvalidNameserver()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->create('255.255.255.255', $this->loop);
|
||||
|
||||
gc_collect_cycles();
|
||||
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
unset($promise);
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
public function testResolveCachedShouldNotCauseGarbageReferencesWhenUsingInvalidNameserver()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->createCached('255.255.255.255', $this->loop);
|
||||
|
||||
gc_collect_cycles();
|
||||
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
unset($promise);
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
public function testCancelResolveShouldNotCauseGarbageReferences()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->create('127.0.0.1', $this->loop);
|
||||
|
||||
gc_collect_cycles();
|
||||
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
$promise->cancel();
|
||||
$promise = null;
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
public function testCancelResolveCachedShouldNotCauseGarbageReferences()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$factory = new Factory();
|
||||
$this->resolver = $factory->createCached('127.0.0.1', $this->loop);
|
||||
|
||||
gc_collect_cycles();
|
||||
|
||||
$promise = $this->resolver->resolve('google.com');
|
||||
$promise->cancel();
|
||||
$promise = null;
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
}
|
||||
31
vendor/react/dns/tests/Model/MessageTest.php
vendored
Executable file
31
vendor/react/dns/tests/Model/MessageTest.php
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Model;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
|
||||
class MessageTest extends TestCase
|
||||
{
|
||||
public function testCreateRequestDesiresRecusion()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$request = Message::createRequestForQuery($query);
|
||||
|
||||
$this->assertTrue($request->header->isQuery());
|
||||
$this->assertSame(1, $request->header->get('rd'));
|
||||
}
|
||||
|
||||
public function testCreateResponseWithNoAnswers()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$answers = array();
|
||||
$request = Message::createResponseWithAnswersForQuery($query, $answers);
|
||||
|
||||
$this->assertFalse($request->header->isQuery());
|
||||
$this->assertTrue($request->header->isResponse());
|
||||
$this->assertEquals(0, $request->header->get('anCount'));
|
||||
$this->assertEquals(Message::RCODE_OK, $request->getResponseCode());
|
||||
}
|
||||
}
|
||||
278
vendor/react/dns/tests/Protocol/BinaryDumperTest.php
vendored
Executable file
278
vendor/react/dns/tests/Protocol/BinaryDumperTest.php
vendored
Executable file
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Protocol;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\Dns\Protocol\BinaryDumper;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
|
||||
class BinaryDumperTest extends TestCase
|
||||
{
|
||||
public function testToBinaryRequestMessage()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 00 00 00 00 00"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 01 00 01"; // question: type A, class IN
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$request = new Message();
|
||||
$request->header->set('id', 0x7262);
|
||||
$request->header->set('rd', 1);
|
||||
|
||||
$request->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_A,
|
||||
'class' => Message::CLASS_IN,
|
||||
);
|
||||
|
||||
$request->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($request);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
public function testToBinaryRequestMessageWithCustomOptForEdns0()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 00 00 00 00 01"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 01 00 01"; // question: type A, class IN
|
||||
$data .= "00"; // additional: (empty hostname)
|
||||
$data .= "00 29 03 e8 00 00 00 00 00 00 "; // additional: type OPT, class UDP size, TTL 0, no RDATA
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$request = new Message();
|
||||
$request->header->set('id', 0x7262);
|
||||
$request->header->set('rd', 1);
|
||||
|
||||
$request->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_A,
|
||||
'class' => Message::CLASS_IN,
|
||||
);
|
||||
|
||||
$request->additional[] = new Record('', 41, 1000, 0, '');
|
||||
|
||||
$request->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($request);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
public function testToBinaryResponseMessageWithoutRecords()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 00 00 00 00 00"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 01 00 01"; // question: type A, class IN
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$response = new Message();
|
||||
$response->header->set('id', 0x7262);
|
||||
$response->header->set('rd', 1);
|
||||
$response->header->set('rcode', Message::RCODE_OK);
|
||||
|
||||
$response->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_A,
|
||||
'class' => Message::CLASS_IN
|
||||
);
|
||||
|
||||
$response->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($response);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
public function testToBinaryForResponseWithSRVRecord()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 01 00 00 00 00"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 21 00 01"; // question: type SRV, class IN
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 21 00 01"; // answer: type SRV, class IN
|
||||
$data .= "00 01 51 80"; // answer: ttl 86400
|
||||
$data .= "00 0c"; // answer: rdlength 12
|
||||
$data .= "00 0a 00 14 1f 90 04 74 65 73 74 00"; // answer: rdata priority 10, weight 20, port 8080 test
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$response = new Message();
|
||||
$response->header->set('id', 0x7262);
|
||||
$response->header->set('rd', 1);
|
||||
$response->header->set('rcode', Message::RCODE_OK);
|
||||
|
||||
$response->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_SRV,
|
||||
'class' => Message::CLASS_IN
|
||||
);
|
||||
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_SRV, Message::CLASS_IN, 86400, array(
|
||||
'priority' => 10,
|
||||
'weight' => 20,
|
||||
'port' => 8080,
|
||||
'target' => 'test'
|
||||
));
|
||||
$response->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($response);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
public function testToBinaryForResponseWithSOARecord()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 01 00 00 00 00"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 06 00 01"; // question: type SOA, class IN
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 06 00 01"; // answer: type SOA, class IN
|
||||
$data .= "00 01 51 80"; // answer: ttl 86400
|
||||
$data .= "00 27"; // answer: rdlength 39
|
||||
$data .= "02 6e 73 05 68 65 6c 6c 6f 00"; // answer: rdata ns.hello (mname)
|
||||
$data .= "01 65 05 68 65 6c 6c 6f 00"; // answer: rdata e.hello (rname)
|
||||
$data .= "78 49 28 d5 00 00 2a 30 00 00 0e 10"; // answer: rdata 2018060501, 10800, 3600
|
||||
$data .= "00 09 3e 68 00 00 0e 10"; // answer: 605800, 3600
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$response = new Message();
|
||||
$response->header->set('id', 0x7262);
|
||||
$response->header->set('rd', 1);
|
||||
$response->header->set('rcode', Message::RCODE_OK);
|
||||
|
||||
$response->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_SOA,
|
||||
'class' => Message::CLASS_IN
|
||||
);
|
||||
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_SOA, Message::CLASS_IN, 86400, array(
|
||||
'mname' => 'ns.hello',
|
||||
'rname' => 'e.hello',
|
||||
'serial' => 2018060501,
|
||||
'refresh' => 10800,
|
||||
'retry' => 3600,
|
||||
'expire' => 605800,
|
||||
'minimum' => 3600
|
||||
));
|
||||
$response->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($response);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
public function testToBinaryForResponseWithMultipleAnswerRecords()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 04 00 00 00 00"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 ff 00 01"; // question: type ANY, class IN
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 01 00 01 00 00 00 00 00 04"; // answer: type A, class IN, TTL 0, 4 bytes
|
||||
$data .= "7f 00 00 01"; // answer: 127.0.0.1
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 1c 00 01 00 00 00 00 00 10"; // question: type AAAA, class IN, TTL 0, 16 bytes
|
||||
$data .= "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01"; // answer: ::1
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 10 00 01 00 00 00 00 00 0c"; // answer: type TXT, class IN, TTL 0, 12 bytes
|
||||
$data .= "05 68 65 6c 6c 6f 05 77 6f 72 6c 64"; // answer: hello, world
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 0f 00 01 00 00 00 00 00 03"; // anwser: type MX, class IN, TTL 0, 3 bytes
|
||||
$data .= "00 00 00"; // priority 0, no target
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$response = new Message();
|
||||
$response->header->set('id', 0x7262);
|
||||
$response->header->set('rd', 1);
|
||||
$response->header->set('rcode', Message::RCODE_OK);
|
||||
|
||||
$response->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_ANY,
|
||||
'class' => Message::CLASS_IN
|
||||
);
|
||||
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 0, '127.0.0.1');
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_AAAA, Message::CLASS_IN, 0, '::1');
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_TXT, Message::CLASS_IN, 0, array('hello', 'world'));
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_MX, Message::CLASS_IN, 0, array('priority' => 0, 'target' => ''));
|
||||
$response->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($response);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
public function testToBinaryForResponseWithAnswerAndAdditionalRecord()
|
||||
{
|
||||
$data = "";
|
||||
$data .= "72 62 01 00 00 01 00 01 00 00 00 01"; // header
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // question: igor.io
|
||||
$data .= "00 02 00 01"; // question: type NS, class IN
|
||||
$data .= "04 69 67 6f 72 02 69 6f 00"; // answer: igor.io
|
||||
$data .= "00 02 00 01 00 00 00 00 00 0d"; // answer: type NS, class IN, TTL 0, 10 bytes
|
||||
$data .= "07 65 78 61 6d 70 6c 65 03 63 6f 6d 00"; // answer: example.com
|
||||
$data .= "07 65 78 61 6d 70 6c 65 03 63 6f 6d 00"; // additional: example.com
|
||||
$data .= "00 01 00 01 00 00 00 00 00 04"; // additional: type A, class IN, TTL 0, 4 bytes
|
||||
$data .= "7f 00 00 01"; // additional: 127.0.0.1
|
||||
|
||||
$expected = $this->formatHexDump($data);
|
||||
|
||||
$response = new Message();
|
||||
$response->header->set('id', 0x7262);
|
||||
$response->header->set('rd', 1);
|
||||
$response->header->set('rcode', Message::RCODE_OK);
|
||||
|
||||
$response->questions[] = array(
|
||||
'name' => 'igor.io',
|
||||
'type' => Message::TYPE_NS,
|
||||
'class' => Message::CLASS_IN
|
||||
);
|
||||
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_NS, Message::CLASS_IN, 0, 'example.com');
|
||||
$response->additional[] = new Record('example.com', Message::TYPE_A, Message::CLASS_IN, 0, '127.0.0.1');
|
||||
$response->prepare();
|
||||
|
||||
$dumper = new BinaryDumper();
|
||||
$data = $dumper->toBinary($response);
|
||||
$data = $this->convertBinaryToHexDump($data);
|
||||
|
||||
$this->assertSame($expected, $data);
|
||||
}
|
||||
|
||||
private function convertBinaryToHexDump($input)
|
||||
{
|
||||
return $this->formatHexDump(implode('', unpack('H*', $input)));
|
||||
}
|
||||
|
||||
private function formatHexDump($input)
|
||||
{
|
||||
return implode(' ', str_split(str_replace(' ', '', $input), 2));
|
||||
}
|
||||
}
|
||||
1033
vendor/react/dns/tests/Protocol/ParserTest.php
vendored
Executable file
1033
vendor/react/dns/tests/Protocol/ParserTest.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
100
vendor/react/dns/tests/Query/CachedExecutorTest.php
vendored
Executable file
100
vendor/react/dns/tests/Query/CachedExecutorTest.php
vendored
Executable file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\Query\CachedExecutor;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
use React\Promise;
|
||||
|
||||
class CachedExecutorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers React\Dns\Query\CachedExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldDelegateToDecoratedExecutor()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnValue($this->createPromiseMock()));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Dns\Query\RecordCache')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$cache
|
||||
->expects($this->once())
|
||||
->method('lookup')
|
||||
->will($this->returnValue(Promise\reject()));
|
||||
$cachedExecutor = new CachedExecutor($executor, $cache);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$cachedExecutor->query('8.8.8.8', $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\CachedExecutor
|
||||
* @test
|
||||
*/
|
||||
public function callingQueryTwiceShouldUseCachedResult()
|
||||
{
|
||||
$cachedRecords = array(new Record('igor.io', Message::TYPE_A, Message::CLASS_IN));
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->will($this->callQueryCallbackWithAddress('178.79.169.131'));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Dns\Query\RecordCache')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$cache
|
||||
->expects($this->at(0))
|
||||
->method('lookup')
|
||||
->with($this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnValue(Promise\reject()));
|
||||
$cache
|
||||
->expects($this->at(1))
|
||||
->method('storeResponseMessage')
|
||||
->with($this->isType('integer'), $this->isInstanceOf('React\Dns\Model\Message'));
|
||||
$cache
|
||||
->expects($this->at(2))
|
||||
->method('lookup')
|
||||
->with($this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnValue(Promise\resolve($cachedRecords)));
|
||||
|
||||
$cachedExecutor = new CachedExecutor($executor, $cache);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$cachedExecutor->query('8.8.8.8', $query, function () {}, function () {});
|
||||
$cachedExecutor->query('8.8.8.8', $query, function () {}, function () {});
|
||||
}
|
||||
|
||||
private function callQueryCallbackWithAddress($address)
|
||||
{
|
||||
return $this->returnCallback(function ($nameserver, $query) use ($address) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
$response->answers[] = new Record($query->name, $query->type, $query->class, 3600, $address);
|
||||
|
||||
return Promise\resolve($response);
|
||||
});
|
||||
}
|
||||
|
||||
private function createExecutorMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
}
|
||||
|
||||
private function createPromiseMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Promise\PromiseInterface')->getMock();
|
||||
}
|
||||
}
|
||||
183
vendor/react/dns/tests/Query/CachingExecutorTest.php
vendored
Executable file
183
vendor/react/dns/tests/Query/CachingExecutorTest.php
vendored
Executable file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Query\CachingExecutor;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Promise\Promise;
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Promise\Deferred;
|
||||
use React\Dns\Model\Record;
|
||||
|
||||
class CachingExecutorTest extends TestCase
|
||||
{
|
||||
public function testQueryWillReturnPendingPromiseWhenCacheIsPendingWithoutSendingQueryToFallbackExecutor()
|
||||
{
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->never())->method('query');
|
||||
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn(new Promise(function () { }));
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testQueryWillReturnPendingPromiseWhenCacheReturnsMissAndWillSendSameQueryToFallbackExecutor()
|
||||
{
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->once())->method('query')->with('8.8.8.8', $query)->willReturn(new Promise(function () { }));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->willReturn(\React\Promise\resolve(null));
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testQueryWillReturnResolvedPromiseWhenCacheReturnsHitWithoutSendingQueryToFallbackExecutor()
|
||||
{
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->never())->method('query');
|
||||
|
||||
$message = new Message();
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn(\React\Promise\resolve($message));
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableOnceWith($message), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testQueryWillReturnResolvedPromiseWhenCacheReturnsMissAndFallbackExecutorResolvesAndSaveMessageToCacheWithMinimumTtlFromRecord()
|
||||
{
|
||||
$message = new Message();
|
||||
$message->answers[] = new Record('reactphp.org', Message::TYPE_A, Message::CLASS_IN, 3700, '127.0.0.1');
|
||||
$message->answers[] = new Record('reactphp.org', Message::TYPE_A, Message::CLASS_IN, 3600, '127.0.0.1');
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->once())->method('query')->willReturn(\React\Promise\resolve($message));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn(\React\Promise\resolve(null));
|
||||
$cache->expects($this->once())->method('set')->with('reactphp.org:1:1', $message, 3600);
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableOnceWith($message), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testQueryWillReturnResolvedPromiseWhenCacheReturnsMissAndFallbackExecutorResolvesAndSaveMessageToCacheWithDefaultTtl()
|
||||
{
|
||||
$message = new Message();
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->once())->method('query')->willReturn(\React\Promise\resolve($message));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn(\React\Promise\resolve(null));
|
||||
$cache->expects($this->once())->method('set')->with('reactphp.org:1:1', $message, 60);
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableOnceWith($message), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testQueryWillReturnResolvedPromiseWhenCacheReturnsMissAndFallbackExecutorResolvesWithTruncatedResponseButShouldNotSaveTruncatedMessageToCache()
|
||||
{
|
||||
$message = new Message();
|
||||
$message->header->set('tc', 1);
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->once())->method('query')->willReturn(\React\Promise\resolve($message));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn(\React\Promise\resolve(null));
|
||||
$cache->expects($this->never())->method('set');
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableOnceWith($message), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testQueryWillReturnRejectedPromiseWhenCacheReturnsMissAndFallbackExecutorRejects()
|
||||
{
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->once())->method('query')->willReturn(\React\Promise\reject(new \RuntimeException()));
|
||||
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->willReturn(\React\Promise\resolve(null));
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnceWith($this->isInstanceOf('RuntimeException')));
|
||||
}
|
||||
|
||||
public function testCancelQueryWillReturnRejectedPromiseAndCancelPendingPromiseFromCache()
|
||||
{
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->never())->method('query');
|
||||
|
||||
$pending = new Promise(function () { }, $this->expectCallableOnce());
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn($pending);
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
$promise->cancel();
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnceWith($this->isInstanceOf('RuntimeException')));
|
||||
}
|
||||
|
||||
public function testCancelQueryWillReturnRejectedPromiseAndCancelPendingPromiseFromFallbackExecutorWhenCacheReturnsMiss()
|
||||
{
|
||||
$pending = new Promise(function () { }, $this->expectCallableOnce());
|
||||
$fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$fallback->expects($this->once())->method('query')->willReturn($pending);
|
||||
|
||||
$deferred = new Deferred();
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$cache->expects($this->once())->method('get')->with('reactphp.org:1:1')->willReturn($deferred->promise());
|
||||
|
||||
$executor = new CachingExecutor($fallback, $cache);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query('8.8.8.8', $query);
|
||||
$deferred->resolve(null);
|
||||
$promise->cancel();
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnceWith($this->isInstanceOf('RuntimeException')));
|
||||
}
|
||||
}
|
||||
233
vendor/react/dns/tests/Query/CoopExecutorTest.php
vendored
Executable file
233
vendor/react/dns/tests/Query/CoopExecutorTest.php
vendored
Executable file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
use React\Dns\Query\CoopExecutor;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Promise\Promise;
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Promise\Deferred;
|
||||
|
||||
class CoopExecutorTest extends TestCase
|
||||
{
|
||||
public function testQueryOnceWillPassExactQueryToBaseExecutor()
|
||||
{
|
||||
$pending = new Promise(function () { });
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->with('8.8.8.8', $query)->willReturn($pending);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$connector->query('8.8.8.8', $query);
|
||||
}
|
||||
|
||||
public function testQueryOnceWillResolveWhenBaseExecutorResolves()
|
||||
{
|
||||
$message = new Message();
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn(\React\Promise\resolve($message));
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
|
||||
$promise->then($this->expectCallableOnceWith($message));
|
||||
}
|
||||
|
||||
public function testQueryOnceWillRejectWhenBaseExecutorRejects()
|
||||
{
|
||||
$exception = new RuntimeException();
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn(\React\Promise\reject($exception));
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWith($exception));
|
||||
}
|
||||
|
||||
public function testQueryTwoDifferentQueriesWillPassExactQueryToBaseExecutorTwice()
|
||||
{
|
||||
$pending = new Promise(function () { });
|
||||
$query1 = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$query2 = new Query('reactphp.org', Message::TYPE_AAAA, Message::CLASS_IN);
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->exactly(2))->method('query')->withConsecutive(
|
||||
array('8.8.8.8', $query1),
|
||||
array('8.8.8.8', $query2)
|
||||
)->willReturn($pending);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$connector->query('8.8.8.8', $query1);
|
||||
$connector->query('8.8.8.8', $query2);
|
||||
}
|
||||
|
||||
public function testQueryTwiceWillPassExactQueryToBaseExecutorOnceWhenQueryIsStillPending()
|
||||
{
|
||||
$pending = new Promise(function () { });
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->with('8.8.8.8', $query)->willReturn($pending);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$connector->query('8.8.8.8', $query);
|
||||
$connector->query('8.8.8.8', $query);
|
||||
}
|
||||
|
||||
public function testQueryTwiceWillPassExactQueryToBaseExecutorTwiceWhenFirstQueryIsAlreadyResolved()
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
$pending = new Promise(function () { });
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->exactly(2))->method('query')->with('8.8.8.8', $query)->willReturnOnConsecutiveCalls($deferred->promise(), $pending);
|
||||
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$connector->query('8.8.8.8', $query);
|
||||
|
||||
$deferred->resolve(new Message());
|
||||
|
||||
$connector->query('8.8.8.8', $query);
|
||||
}
|
||||
|
||||
public function testQueryTwiceWillPassExactQueryToBaseExecutorTwiceWhenFirstQueryIsAlreadyRejected()
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
$pending = new Promise(function () { });
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->exactly(2))->method('query')->with('8.8.8.8', $query)->willReturnOnConsecutiveCalls($deferred->promise(), $pending);
|
||||
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$connector->query('8.8.8.8', $query);
|
||||
|
||||
$deferred->reject(new RuntimeException());
|
||||
|
||||
$connector->query('8.8.8.8', $query);
|
||||
}
|
||||
|
||||
public function testCancelQueryWillCancelPromiseFromBaseExecutorAndReject()
|
||||
{
|
||||
$promise = new Promise(function () { }, $this->expectCallableOnce());
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn($promise);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$promise->cancel();
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testCancelOneQueryWhenOtherQueryIsStillPendingWillNotCancelPromiseFromBaseExecutorAndRejectCancelled()
|
||||
{
|
||||
$promise = new Promise(function () { }, $this->expectCallableNever());
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn($promise);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise1 = $connector->query('8.8.8.8', $query);
|
||||
$promise2 = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$promise1->cancel();
|
||||
|
||||
$promise1->then(null, $this->expectCallableOnce());
|
||||
$promise2->then(null, $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testCancelSecondQueryWhenFirstQueryIsStillPendingWillNotCancelPromiseFromBaseExecutorAndRejectCancelled()
|
||||
{
|
||||
$promise = new Promise(function () { }, $this->expectCallableNever());
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn($promise);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise1 = $connector->query('8.8.8.8', $query);
|
||||
$promise2 = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$promise2->cancel();
|
||||
|
||||
$promise2->then(null, $this->expectCallableOnce());
|
||||
$promise1->then(null, $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testCancelAllPendingQueriesWillCancelPromiseFromBaseExecutorAndRejectCancelled()
|
||||
{
|
||||
$promise = new Promise(function () { }, $this->expectCallableOnce());
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn($promise);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise1 = $connector->query('8.8.8.8', $query);
|
||||
$promise2 = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$promise1->cancel();
|
||||
$promise2->cancel();
|
||||
|
||||
$promise1->then(null, $this->expectCallableOnce());
|
||||
$promise2->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testQueryTwiceWillQueryBaseExecutorTwiceIfFirstQueryHasAlreadyBeenCancelledWhenSecondIsStarted()
|
||||
{
|
||||
$promise = new Promise(function () { }, $this->expectCallableOnce());
|
||||
$pending = new Promise(function () { });
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->exactly(2))->method('query')->willReturnOnConsecutiveCalls($promise, $pending);
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise1 = $connector->query('8.8.8.8', $query);
|
||||
$promise1->cancel();
|
||||
|
||||
$promise2 = $connector->query('8.8.8.8', $query);
|
||||
|
||||
$promise1->then(null, $this->expectCallableOnce());
|
||||
|
||||
$promise2->then(null, $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testCancelQueryShouldNotCauseGarbageReferences()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$deferred = new Deferred(function () {
|
||||
throw new \RuntimeException();
|
||||
});
|
||||
|
||||
$base = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$base->expects($this->once())->method('query')->willReturn($deferred->promise());
|
||||
$connector = new CoopExecutor($base);
|
||||
|
||||
gc_collect_cycles();
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $connector->query('8.8.8.8', $query);
|
||||
$promise->cancel();
|
||||
$promise = null;
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
}
|
||||
308
vendor/react/dns/tests/Query/ExecutorTest.php
vendored
Executable file
308
vendor/react/dns/tests/Query/ExecutorTest.php
vendored
Executable file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use Clue\React\Block;
|
||||
use React\Dns\Query\Executor;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
use React\Dns\Protocol\BinaryDumper;
|
||||
use React\Tests\Dns\TestCase;
|
||||
|
||||
class ExecutorTest extends TestCase
|
||||
{
|
||||
private $loop;
|
||||
private $parser;
|
||||
private $dumper;
|
||||
private $executor;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
$this->parser = $this->getMockBuilder('React\Dns\Protocol\Parser')->getMock();
|
||||
$this->dumper = new BinaryDumper();
|
||||
|
||||
$this->executor = new Executor($this->loop, $this->parser, $this->dumper);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function queryShouldCreateUdpRequest()
|
||||
{
|
||||
$timer = $this->createTimerMock();
|
||||
$this->loop
|
||||
->expects($this->any())
|
||||
->method('addTimer')
|
||||
->will($this->returnValue($timer));
|
||||
|
||||
$this->executor = $this->createExecutorMock();
|
||||
$this->executor
|
||||
->expects($this->once())
|
||||
->method('createConnection')
|
||||
->with('8.8.8.8:53', 'udp')
|
||||
->will($this->returnNewConnectionMock(false));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$this->executor->query('8.8.8.8:53', $query);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldRejectIfRequestIsLargerThan512Bytes()
|
||||
{
|
||||
$query = new Query(str_repeat('a', 512).'.igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$this->setExpectedException('RuntimeException', 'DNS query for ' . $query->name . ' failed: Requested transport "tcp" not available, only UDP is supported in this version');
|
||||
Block\await($promise, $this->loop);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldCloseConnectionWhenCancelled()
|
||||
{
|
||||
$conn = $this->createConnectionMock(false);
|
||||
$conn->expects($this->once())->method('close');
|
||||
|
||||
$timer = $this->createTimerMock();
|
||||
$this->loop
|
||||
->expects($this->any())
|
||||
->method('addTimer')
|
||||
->will($this->returnValue($timer));
|
||||
|
||||
$this->executor = $this->createExecutorMock();
|
||||
$this->executor
|
||||
->expects($this->once())
|
||||
->method('createConnection')
|
||||
->with('8.8.8.8:53', 'udp')
|
||||
->will($this->returnValue($conn));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$promise->cancel();
|
||||
|
||||
$this->setExpectedException('React\Dns\Query\CancellationException', 'DNS query for igor.io has been cancelled');
|
||||
Block\await($promise, $this->loop);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldNotStartOrCancelTimerWhenCancelledWithTimeoutIsNull()
|
||||
{
|
||||
$this->loop
|
||||
->expects($this->never())
|
||||
->method('addTimer');
|
||||
|
||||
$this->executor = new Executor($this->loop, $this->parser, $this->dumper, null);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('127.0.0.1:53', $query);
|
||||
|
||||
$promise->cancel();
|
||||
|
||||
$this->setExpectedException('React\Dns\Query\CancellationException', 'DNS query for igor.io has been cancelled');
|
||||
Block\await($promise, $this->loop);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldRejectIfResponseIsTruncated()
|
||||
{
|
||||
$timer = $this->createTimerMock();
|
||||
|
||||
$this->loop
|
||||
->expects($this->any())
|
||||
->method('addTimer')
|
||||
->will($this->returnValue($timer));
|
||||
|
||||
$this->parser
|
||||
->expects($this->once())
|
||||
->method('parseMessage')
|
||||
->will($this->returnTruncatedResponse());
|
||||
|
||||
$this->executor = $this->createExecutorMock();
|
||||
$this->executor
|
||||
->expects($this->once())
|
||||
->method('createConnection')
|
||||
->with('8.8.8.8:53', 'udp')
|
||||
->will($this->returnNewConnectionMock());
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$this->executor->query('8.8.8.8:53', $query);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldFailIfUdpThrow()
|
||||
{
|
||||
$this->loop
|
||||
->expects($this->never())
|
||||
->method('addTimer');
|
||||
|
||||
$this->parser
|
||||
->expects($this->never())
|
||||
->method('parseMessage');
|
||||
|
||||
$this->executor = $this->createExecutorMock();
|
||||
$this->executor
|
||||
->expects($this->once())
|
||||
->method('createConnection')
|
||||
->with('8.8.8.8:53', 'udp')
|
||||
->will($this->throwException(new \Exception('Nope')));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$this->setExpectedException('RuntimeException', 'DNS query for igor.io failed: Nope');
|
||||
Block\await($promise, $this->loop);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldCancelTimerWhenFullResponseIsReceived()
|
||||
{
|
||||
$conn = $this->createConnectionMock();
|
||||
|
||||
$this->parser
|
||||
->expects($this->once())
|
||||
->method('parseMessage')
|
||||
->will($this->returnStandardResponse());
|
||||
|
||||
$this->executor = $this->createExecutorMock();
|
||||
$this->executor
|
||||
->expects($this->at(0))
|
||||
->method('createConnection')
|
||||
->with('8.8.8.8:53', 'udp')
|
||||
->will($this->returnNewConnectionMock());
|
||||
|
||||
|
||||
$timer = $this->createTimerMock();
|
||||
|
||||
$this->loop
|
||||
->expects($this->once())
|
||||
->method('addTimer')
|
||||
->with(5, $this->isInstanceOf('Closure'))
|
||||
->will($this->returnValue($timer));
|
||||
|
||||
$this->loop
|
||||
->expects($this->once())
|
||||
->method('cancelTimer')
|
||||
->with($timer);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$this->executor->query('8.8.8.8:53', $query);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldCloseConnectionOnTimeout()
|
||||
{
|
||||
$this->executor = $this->createExecutorMock();
|
||||
$this->executor
|
||||
->expects($this->at(0))
|
||||
->method('createConnection')
|
||||
->with('8.8.8.8:53', 'udp')
|
||||
->will($this->returnNewConnectionMock(false));
|
||||
|
||||
$timer = $this->createTimerMock();
|
||||
|
||||
$this->loop
|
||||
->expects($this->never())
|
||||
->method('cancelTimer');
|
||||
|
||||
$this->loop
|
||||
->expects($this->once())
|
||||
->method('addTimer')
|
||||
->with(5, $this->isInstanceOf('Closure'))
|
||||
->will($this->returnCallback(function ($time, $callback) use (&$timerCallback, $timer) {
|
||||
$timerCallback = $callback;
|
||||
return $timer;
|
||||
}));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$this->assertNotNull($timerCallback);
|
||||
$timerCallback();
|
||||
|
||||
$this->setExpectedException('React\Dns\Query\TimeoutException', 'DNS query for igor.io timed out');
|
||||
Block\await($promise, $this->loop);
|
||||
}
|
||||
|
||||
private function returnStandardResponse()
|
||||
{
|
||||
$that = $this;
|
||||
$callback = function ($data) use ($that) {
|
||||
$response = new Message();
|
||||
$that->convertMessageToStandardResponse($response);
|
||||
return $response;
|
||||
};
|
||||
|
||||
return $this->returnCallback($callback);
|
||||
}
|
||||
|
||||
private function returnTruncatedResponse()
|
||||
{
|
||||
$that = $this;
|
||||
$callback = function ($data) use ($that) {
|
||||
$response = new Message();
|
||||
$that->convertMessageToTruncatedResponse($response);
|
||||
return $response;
|
||||
};
|
||||
|
||||
return $this->returnCallback($callback);
|
||||
}
|
||||
|
||||
public function convertMessageToStandardResponse(Message $response)
|
||||
{
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN);
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131');
|
||||
$response->prepare();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function convertMessageToTruncatedResponse(Message $response)
|
||||
{
|
||||
$this->convertMessageToStandardResponse($response);
|
||||
$response->header->set('tc', 1);
|
||||
$response->prepare();
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function returnNewConnectionMock($emitData = true)
|
||||
{
|
||||
$conn = $this->createConnectionMock($emitData);
|
||||
|
||||
$callback = function () use ($conn) {
|
||||
return $conn;
|
||||
};
|
||||
|
||||
return $this->returnCallback($callback);
|
||||
}
|
||||
|
||||
private function createConnectionMock($emitData = true)
|
||||
{
|
||||
$conn = $this->getMockBuilder('React\Stream\DuplexStreamInterface')->getMock();
|
||||
$conn
|
||||
->expects($this->any())
|
||||
->method('on')
|
||||
->with('data', $this->isInstanceOf('Closure'))
|
||||
->will($this->returnCallback(function ($name, $callback) use ($emitData) {
|
||||
$emitData && $callback(null);
|
||||
}));
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
private function createTimerMock()
|
||||
{
|
||||
return $this->getMockBuilder(
|
||||
interface_exists('React\EventLoop\TimerInterface') ? 'React\EventLoop\TimerInterface' : 'React\EventLoop\Timer\TimerInterface'
|
||||
)->getMock();
|
||||
}
|
||||
|
||||
private function createExecutorMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Dns\Query\Executor')
|
||||
->setConstructorArgs(array($this->loop, $this->parser, $this->dumper))
|
||||
->setMethods(array('createConnection'))
|
||||
->getMock();
|
||||
}
|
||||
}
|
||||
126
vendor/react/dns/tests/Query/HostsFileExecutorTest.php
vendored
Executable file
126
vendor/react/dns/tests/Query/HostsFileExecutorTest.php
vendored
Executable file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\Query\HostsFileExecutor;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
|
||||
class HostsFileExecutorTest extends TestCase
|
||||
{
|
||||
private $hosts;
|
||||
private $fallback;
|
||||
private $executor;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->hosts = $this->getMockBuilder('React\Dns\Config\HostsFile')->disableOriginalConstructor()->getMock();
|
||||
$this->fallback = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
$this->executor = new HostsFileExecutor($this->hosts, $this->fallback);
|
||||
}
|
||||
|
||||
public function testDoesNotTryToGetIpsForMxQuery()
|
||||
{
|
||||
$this->hosts->expects($this->never())->method('getIpsForHost');
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('google.com', Message::TYPE_MX, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testFallsBackIfNoIpsWereFound()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getIpsForHost')->willReturn(array());
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('google.com', Message::TYPE_A, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testReturnsResponseMessageIfIpsWereFound()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getIpsForHost')->willReturn(array('127.0.0.1'));
|
||||
$this->fallback->expects($this->never())->method('query');
|
||||
|
||||
$ret = $this->executor->query('8.8.8.8', new Query('google.com', Message::TYPE_A, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testFallsBackIfNoIpv4Matches()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getIpsForHost')->willReturn(array('::1'));
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$ret = $this->executor->query('8.8.8.8', new Query('google.com', Message::TYPE_A, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testReturnsResponseMessageIfIpv6AddressesWereFound()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getIpsForHost')->willReturn(array('::1'));
|
||||
$this->fallback->expects($this->never())->method('query');
|
||||
|
||||
$ret = $this->executor->query('8.8.8.8', new Query('google.com', Message::TYPE_AAAA, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testFallsBackIfNoIpv6Matches()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getIpsForHost')->willReturn(array('127.0.0.1'));
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$ret = $this->executor->query('8.8.8.8', new Query('google.com', Message::TYPE_AAAA, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testDoesReturnReverseIpv4Lookup()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getHostsForIp')->with('127.0.0.1')->willReturn(array('localhost'));
|
||||
$this->fallback->expects($this->never())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('1.0.0.127.in-addr.arpa', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testFallsBackIfNoReverseIpv4Matches()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getHostsForIp')->with('127.0.0.1')->willReturn(array());
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('1.0.0.127.in-addr.arpa', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testDoesReturnReverseIpv6Lookup()
|
||||
{
|
||||
$this->hosts->expects($this->once())->method('getHostsForIp')->with('2a02:2e0:3fe:100::6')->willReturn(array('ip6-localhost'));
|
||||
$this->fallback->expects($this->never())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.e.f.3.0.0.e.2.0.2.0.a.2.ip6.arpa', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testFallsBackForInvalidAddress()
|
||||
{
|
||||
$this->hosts->expects($this->never())->method('getHostsForIp');
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('example.com', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testReverseFallsBackForInvalidIpv4Address()
|
||||
{
|
||||
$this->hosts->expects($this->never())->method('getHostsForIp');
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('::1.in-addr.arpa', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testReverseFallsBackForInvalidLengthIpv6Address()
|
||||
{
|
||||
$this->hosts->expects($this->never())->method('getHostsForIp');
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('abcd.ip6.arpa', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
|
||||
public function testReverseFallsBackForInvalidHexIpv6Address()
|
||||
{
|
||||
$this->hosts->expects($this->never())->method('getHostsForIp');
|
||||
$this->fallback->expects($this->once())->method('query');
|
||||
|
||||
$this->executor->query('8.8.8.8', new Query('zZz.ip6.arpa', Message::TYPE_PTR, Message::CLASS_IN, 0));
|
||||
}
|
||||
}
|
||||
83
vendor/react/dns/tests/Query/RecordBagTest.php
vendored
Executable file
83
vendor/react/dns/tests/Query/RecordBagTest.php
vendored
Executable file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\Dns\Query\RecordBag;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
|
||||
class RecordBagTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordBag
|
||||
* @test
|
||||
*/
|
||||
public function emptyBagShouldBeEmpty()
|
||||
{
|
||||
$recordBag = new RecordBag();
|
||||
|
||||
$this->assertSame(array(), $recordBag->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordBag
|
||||
* @test
|
||||
*/
|
||||
public function setShouldSetTheValue()
|
||||
{
|
||||
$currentTime = 1345656451;
|
||||
|
||||
$recordBag = new RecordBag();
|
||||
$recordBag->set($currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600));
|
||||
|
||||
$records = $recordBag->all();
|
||||
$this->assertCount(1, $records);
|
||||
$this->assertSame('igor.io', $records[0]->name);
|
||||
$this->assertSame(Message::TYPE_A, $records[0]->type);
|
||||
$this->assertSame(Message::CLASS_IN, $records[0]->class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordBag
|
||||
* @test
|
||||
*/
|
||||
public function setShouldAcceptMxRecord()
|
||||
{
|
||||
$currentTime = 1345656451;
|
||||
|
||||
$recordBag = new RecordBag();
|
||||
$recordBag->set($currentTime, new Record('igor.io', Message::TYPE_MX, Message::CLASS_IN, 3600, array('priority' => 10, 'target' => 'igor.io')));
|
||||
|
||||
$records = $recordBag->all();
|
||||
$this->assertCount(1, $records);
|
||||
$this->assertSame('igor.io', $records[0]->name);
|
||||
$this->assertSame(Message::TYPE_MX, $records[0]->type);
|
||||
$this->assertSame(Message::CLASS_IN, $records[0]->class);
|
||||
$this->assertSame(array('priority' => 10, 'target' => 'igor.io'), $records[0]->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordBag
|
||||
* @test
|
||||
*/
|
||||
public function setShouldSetManyValues()
|
||||
{
|
||||
$currentTime = 1345656451;
|
||||
|
||||
$recordBag = new RecordBag();
|
||||
$recordBag->set($currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'));
|
||||
$recordBag->set($currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.132'));
|
||||
|
||||
$records = $recordBag->all();
|
||||
$this->assertCount(2, $records);
|
||||
$this->assertSame('igor.io', $records[0]->name);
|
||||
$this->assertSame(Message::TYPE_A, $records[0]->type);
|
||||
$this->assertSame(Message::CLASS_IN, $records[0]->class);
|
||||
$this->assertSame('178.79.169.131', $records[0]->data);
|
||||
$this->assertSame('igor.io', $records[1]->name);
|
||||
$this->assertSame(Message::TYPE_A, $records[1]->type);
|
||||
$this->assertSame(Message::CLASS_IN, $records[1]->class);
|
||||
$this->assertSame('178.79.169.132', $records[1]->data);
|
||||
}
|
||||
}
|
||||
160
vendor/react/dns/tests/Query/RecordCacheTest.php
vendored
Executable file
160
vendor/react/dns/tests/Query/RecordCacheTest.php
vendored
Executable file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\Cache\ArrayCache;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
use React\Dns\Query\RecordCache;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Promise\PromiseInterface;
|
||||
use React\Promise\Promise;
|
||||
|
||||
class RecordCacheTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function lookupOnCacheMissShouldReturnNull()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
|
||||
$base = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$base->expects($this->once())->method('get')->willReturn(\React\Promise\resolve(null));
|
||||
|
||||
$cache = new RecordCache($base);
|
||||
$promise = $cache->lookup($query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\RejectedPromise', $promise);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function storeRecordPendingCacheDoesNotSetCache()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$pending = new Promise(function () { });
|
||||
|
||||
$base = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$base->expects($this->once())->method('get')->willReturn($pending);
|
||||
$base->expects($this->never())->method('set');
|
||||
|
||||
$cache = new RecordCache($base);
|
||||
$cache->storeRecord($query->currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function storeRecordOnCacheMissSetsCache()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
|
||||
$base = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$base->expects($this->once())->method('get')->willReturn(\React\Promise\resolve(null));
|
||||
$base->expects($this->once())->method('set')->with($this->isType('string'), $this->isType('string'));
|
||||
|
||||
$cache = new RecordCache($base);
|
||||
$cache->storeRecord($query->currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function storeRecordShouldMakeLookupSucceed()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
|
||||
$cache = new RecordCache(new ArrayCache());
|
||||
$cache->storeRecord($query->currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'));
|
||||
$promise = $cache->lookup($query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\FulfilledPromise', $promise);
|
||||
$cachedRecords = $this->getPromiseValue($promise);
|
||||
|
||||
$this->assertCount(1, $cachedRecords);
|
||||
$this->assertSame('178.79.169.131', $cachedRecords[0]->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function storeTwoRecordsShouldReturnBoth()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
|
||||
$cache = new RecordCache(new ArrayCache());
|
||||
$cache->storeRecord($query->currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'));
|
||||
$cache->storeRecord($query->currentTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.132'));
|
||||
$promise = $cache->lookup($query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\FulfilledPromise', $promise);
|
||||
$cachedRecords = $this->getPromiseValue($promise);
|
||||
|
||||
$this->assertCount(2, $cachedRecords);
|
||||
$this->assertSame('178.79.169.131', $cachedRecords[0]->data);
|
||||
$this->assertSame('178.79.169.132', $cachedRecords[1]->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function storeResponseMessageShouldStoreAllAnswerValues()
|
||||
{
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
|
||||
$response = new Message();
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131');
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.132');
|
||||
$response->prepare();
|
||||
|
||||
$cache = new RecordCache(new ArrayCache());
|
||||
$cache->storeResponseMessage($query->currentTime, $response);
|
||||
$promise = $cache->lookup($query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\FulfilledPromise', $promise);
|
||||
$cachedRecords = $this->getPromiseValue($promise);
|
||||
|
||||
$this->assertCount(2, $cachedRecords);
|
||||
$this->assertSame('178.79.169.131', $cachedRecords[0]->data);
|
||||
$this->assertSame('178.79.169.132', $cachedRecords[1]->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RecordCache
|
||||
* @test
|
||||
*/
|
||||
public function expireShouldExpireDeadRecords()
|
||||
{
|
||||
$cachedTime = 1345656451;
|
||||
$currentTime = $cachedTime + 3605;
|
||||
|
||||
$cache = new RecordCache(new ArrayCache());
|
||||
$cache->storeRecord($cachedTime, new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'));
|
||||
$cache->expire($currentTime);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, $currentTime);
|
||||
$promise = $cache->lookup($query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\RejectedPromise', $promise);
|
||||
}
|
||||
|
||||
private function getPromiseValue(PromiseInterface $promise)
|
||||
{
|
||||
$capturedValue = null;
|
||||
|
||||
$promise->then(function ($value) use (&$capturedValue) {
|
||||
$capturedValue = $value;
|
||||
});
|
||||
|
||||
return $capturedValue;
|
||||
}
|
||||
}
|
||||
350
vendor/react/dns/tests/Query/RetryExecutorTest.php
vendored
Executable file
350
vendor/react/dns/tests/Query/RetryExecutorTest.php
vendored
Executable file
@@ -0,0 +1,350 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\Query\RetryExecutor;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Query\TimeoutException;
|
||||
use React\Dns\Model\Record;
|
||||
use React\Promise;
|
||||
use React\Promise\Deferred;
|
||||
use React\Dns\Query\CancellationException;
|
||||
|
||||
class RetryExecutorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldDelegateToDecoratedExecutor()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnValue($this->expectPromiseOnce()));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldRetryQueryOnTimeout()
|
||||
{
|
||||
$response = $this->createStandardResponse();
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->exactly(2))
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->onConsecutiveCalls(
|
||||
$this->returnCallback(function ($domain, $query) {
|
||||
return Promise\reject(new TimeoutException("timeout"));
|
||||
}),
|
||||
$this->returnCallback(function ($domain, $query) use ($response) {
|
||||
return Promise\resolve($response);
|
||||
})
|
||||
));
|
||||
|
||||
$callback = $this->createCallableMock();
|
||||
$callback
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->isInstanceOf('React\Dns\Model\Message'));
|
||||
|
||||
$errorback = $this->expectCallableNever();
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query)->then($callback, $errorback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldStopRetryingAfterSomeAttempts()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->exactly(3))
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($domain, $query) {
|
||||
return Promise\reject(new TimeoutException("timeout"));
|
||||
}));
|
||||
|
||||
$callback = $this->expectCallableNever();
|
||||
|
||||
$errorback = $this->createCallableMock();
|
||||
$errorback
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->isInstanceOf('RuntimeException'));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query)->then($callback, $errorback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldForwardNonTimeoutErrors()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($domain, $query) {
|
||||
return Promise\reject(new \Exception);
|
||||
}));
|
||||
|
||||
$callback = $this->expectCallableNever();
|
||||
|
||||
$errorback = $this->createCallableMock();
|
||||
$errorback
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->isInstanceOf('Exception'));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query)->then($callback, $errorback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldCancelQueryOnCancel()
|
||||
{
|
||||
$cancelled = 0;
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($domain, $query) use (&$cancelled) {
|
||||
$deferred = new Deferred(function ($resolve, $reject) use (&$cancelled) {
|
||||
++$cancelled;
|
||||
$reject(new CancellationException('Cancelled'));
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
})
|
||||
);
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $retryExecutor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnce());
|
||||
|
||||
$this->assertEquals(0, $cancelled);
|
||||
$promise->cancel();
|
||||
$this->assertEquals(1, $cancelled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldCancelSecondQueryOnCancel()
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
$cancelled = 0;
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->exactly(2))
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->onConsecutiveCalls(
|
||||
$this->returnValue($deferred->promise()),
|
||||
$this->returnCallback(function ($domain, $query) use (&$cancelled) {
|
||||
$deferred = new Deferred(function ($resolve, $reject) use (&$cancelled) {
|
||||
++$cancelled;
|
||||
$reject(new CancellationException('Cancelled'));
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
})
|
||||
));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $retryExecutor->query('8.8.8.8', $query);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnce());
|
||||
|
||||
// first query will time out after a while and this sends the next query
|
||||
$deferred->reject(new TimeoutException());
|
||||
|
||||
$this->assertEquals(0, $cancelled);
|
||||
$promise->cancel();
|
||||
$this->assertEquals(1, $cancelled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldNotCauseGarbageReferencesOnSuccess()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->willReturn(Promise\resolve($this->createStandardResponse()));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 0);
|
||||
|
||||
gc_collect_cycles();
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query);
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldNotCauseGarbageReferencesOnTimeoutErrors()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->any())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->willReturn(Promise\reject(new TimeoutException("timeout")));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 0);
|
||||
|
||||
gc_collect_cycles();
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query);
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldNotCauseGarbageReferencesOnCancellation()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$deferred = new Deferred(function () {
|
||||
throw new \RuntimeException();
|
||||
});
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->willReturn($deferred->promise());
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 0);
|
||||
|
||||
gc_collect_cycles();
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $retryExecutor->query('8.8.8.8', $query);
|
||||
$promise->cancel();
|
||||
$promise = null;
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers React\Dns\Query\RetryExecutor
|
||||
* @test
|
||||
*/
|
||||
public function queryShouldNotCauseGarbageReferencesOnNonTimeoutErrors()
|
||||
{
|
||||
if (class_exists('React\Promise\When')) {
|
||||
$this->markTestSkipped('Not supported on legacy Promise v1 API');
|
||||
}
|
||||
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with('8.8.8.8', $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($domain, $query) {
|
||||
return Promise\reject(new \Exception);
|
||||
}));
|
||||
|
||||
$retryExecutor = new RetryExecutor($executor, 2);
|
||||
|
||||
gc_collect_cycles();
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$retryExecutor->query('8.8.8.8', $query);
|
||||
|
||||
$this->assertEquals(0, gc_collect_cycles());
|
||||
}
|
||||
|
||||
protected function expectPromiseOnce($return = null)
|
||||
{
|
||||
$mock = $this->createPromiseMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('then')
|
||||
->will($this->returnValue($return));
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function createExecutorMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
}
|
||||
|
||||
protected function createPromiseMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Promise\PromiseInterface')->getMock();
|
||||
}
|
||||
|
||||
protected function createStandardResponse()
|
||||
{
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN);
|
||||
$response->answers[] = new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131');
|
||||
$response->prepare();
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
115
vendor/react/dns/tests/Query/TimeoutExecutorTest.php
vendored
Executable file
115
vendor/react/dns/tests/Query/TimeoutExecutorTest.php
vendored
Executable file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use React\Dns\Query\TimeoutExecutor;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Promise\Deferred;
|
||||
use React\Dns\Query\CancellationException;
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\EventLoop\Factory;
|
||||
use React\Promise;
|
||||
|
||||
class TimeoutExecutorTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->loop = Factory::create();
|
||||
|
||||
$this->wrapped = $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
|
||||
$this->executor = new TimeoutExecutor($this->wrapped, 5.0, $this->loop);
|
||||
}
|
||||
|
||||
public function testCancellingPromiseWillCancelWrapped()
|
||||
{
|
||||
$cancelled = 0;
|
||||
|
||||
$this->wrapped
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->will($this->returnCallback(function ($domain, $query) use (&$cancelled) {
|
||||
$deferred = new Deferred(function ($resolve, $reject) use (&$cancelled) {
|
||||
++$cancelled;
|
||||
$reject(new CancellationException('Cancelled'));
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$this->assertEquals(0, $cancelled);
|
||||
$promise->cancel();
|
||||
$this->assertEquals(1, $cancelled);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testResolvesPromiseWhenWrappedResolves()
|
||||
{
|
||||
$this->wrapped
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->willReturn(Promise\resolve('0.0.0.0'));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$promise->then($this->expectCallableOnce(), $this->expectCallableNever());
|
||||
}
|
||||
|
||||
public function testRejectsPromiseWhenWrappedRejects()
|
||||
{
|
||||
$this->wrapped
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->willReturn(Promise\reject(new \RuntimeException()));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$promise = $this->executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$promise->then($this->expectCallableNever(), $this->expectCallableOnceWith(new \RuntimeException()));
|
||||
}
|
||||
|
||||
public function testWrappedWillBeCancelledOnTimeout()
|
||||
{
|
||||
$this->executor = new TimeoutExecutor($this->wrapped, 0, $this->loop);
|
||||
|
||||
$cancelled = 0;
|
||||
|
||||
$this->wrapped
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->will($this->returnCallback(function ($domain, $query) use (&$cancelled) {
|
||||
$deferred = new Deferred(function ($resolve, $reject) use (&$cancelled) {
|
||||
++$cancelled;
|
||||
$reject(new CancellationException('Cancelled'));
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}));
|
||||
|
||||
$callback = $this->expectCallableNever();
|
||||
|
||||
$errorback = $this->createCallableMock();
|
||||
$errorback
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->logicalAnd(
|
||||
$this->isInstanceOf('React\Dns\Query\TimeoutException'),
|
||||
$this->attribute($this->equalTo('DNS query for igor.io timed out'), 'message')
|
||||
));
|
||||
|
||||
$query = new Query('igor.io', Message::TYPE_A, Message::CLASS_IN, 1345656451);
|
||||
$this->executor->query('8.8.8.8:53', $query)->then($callback, $errorback);
|
||||
|
||||
$this->assertEquals(0, $cancelled);
|
||||
|
||||
$this->loop->run();
|
||||
|
||||
$this->assertEquals(1, $cancelled);
|
||||
}
|
||||
}
|
||||
215
vendor/react/dns/tests/Query/UdpTransportExecutorTest.php
vendored
Executable file
215
vendor/react/dns/tests/Query/UdpTransportExecutorTest.php
vendored
Executable file
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Query;
|
||||
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Protocol\BinaryDumper;
|
||||
use React\Dns\Protocol\Parser;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Query\UdpTransportExecutor;
|
||||
use React\EventLoop\Factory;
|
||||
use React\Tests\Dns\TestCase;
|
||||
|
||||
class UdpTransportExecutorTest extends TestCase
|
||||
{
|
||||
public function testQueryRejectsIfMessageExceedsUdpSize()
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
$loop->expects($this->never())->method('addReadStream');
|
||||
|
||||
$dumper = $this->getMockBuilder('React\Dns\Protocol\BinaryDumper')->getMock();
|
||||
$dumper->expects($this->once())->method('toBinary')->willReturn(str_repeat('.', 513));
|
||||
|
||||
$executor = new UdpTransportExecutor($loop, null, $dumper);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise = $executor->query('8.8.8.8:53', $query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testQueryRejectsIfServerConnectionFails()
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
$loop->expects($this->never())->method('addReadStream');
|
||||
|
||||
$executor = new UdpTransportExecutor($loop);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise = $executor->query('///', $query);
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
/**
|
||||
* @group internet
|
||||
*/
|
||||
public function testQueryRejectsOnCancellation()
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
$loop->expects($this->once())->method('addReadStream');
|
||||
$loop->expects($this->once())->method('removeReadStream');
|
||||
|
||||
$executor = new UdpTransportExecutor($loop);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
$promise = $executor->query('8.8.8.8:53', $query);
|
||||
$promise->cancel();
|
||||
|
||||
$this->assertInstanceOf('React\Promise\PromiseInterface', $promise);
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testQueryKeepsPendingIfServerRejectsNetworkPacket()
|
||||
{
|
||||
$loop = Factory::create();
|
||||
|
||||
$executor = new UdpTransportExecutor($loop);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$wait = true;
|
||||
$promise = $executor->query('127.0.0.1:1', $query)->then(
|
||||
null,
|
||||
function ($e) use (&$wait) {
|
||||
$wait = false;
|
||||
throw $e;
|
||||
}
|
||||
);
|
||||
|
||||
\Clue\React\Block\sleep(0.2, $loop);
|
||||
$this->assertTrue($wait);
|
||||
}
|
||||
|
||||
public function testQueryKeepsPendingIfServerSendInvalidMessage()
|
||||
{
|
||||
$loop = Factory::create();
|
||||
|
||||
$server = stream_socket_server('udp://127.0.0.1:0', $errno, $errstr, STREAM_SERVER_BIND);
|
||||
$loop->addReadStream($server, function ($server) {
|
||||
$data = stream_socket_recvfrom($server, 512, 0, $peer);
|
||||
stream_socket_sendto($server, 'invalid', 0, $peer);
|
||||
});
|
||||
|
||||
$address = stream_socket_get_name($server, false);
|
||||
$executor = new UdpTransportExecutor($loop);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$wait = true;
|
||||
$promise = $executor->query($address, $query)->then(
|
||||
null,
|
||||
function ($e) use (&$wait) {
|
||||
$wait = false;
|
||||
throw $e;
|
||||
}
|
||||
);
|
||||
|
||||
\Clue\React\Block\sleep(0.2, $loop);
|
||||
$this->assertTrue($wait);
|
||||
}
|
||||
|
||||
public function testQueryKeepsPendingIfServerSendInvalidId()
|
||||
{
|
||||
$parser = new Parser();
|
||||
$dumper = new BinaryDumper();
|
||||
|
||||
$loop = Factory::create();
|
||||
|
||||
$server = stream_socket_server('udp://127.0.0.1:0', $errno, $errstr, STREAM_SERVER_BIND);
|
||||
$loop->addReadStream($server, function ($server) use ($parser, $dumper) {
|
||||
$data = stream_socket_recvfrom($server, 512, 0, $peer);
|
||||
|
||||
$message = $parser->parseMessage($data);
|
||||
$message->header->set('id', 0);
|
||||
|
||||
stream_socket_sendto($server, $dumper->toBinary($message), 0, $peer);
|
||||
});
|
||||
|
||||
$address = stream_socket_get_name($server, false);
|
||||
$executor = new UdpTransportExecutor($loop, $parser, $dumper);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$wait = true;
|
||||
$promise = $executor->query($address, $query)->then(
|
||||
null,
|
||||
function ($e) use (&$wait) {
|
||||
$wait = false;
|
||||
throw $e;
|
||||
}
|
||||
);
|
||||
|
||||
\Clue\React\Block\sleep(0.2, $loop);
|
||||
$this->assertTrue($wait);
|
||||
}
|
||||
|
||||
public function testQueryRejectsIfServerSendsTruncatedResponse()
|
||||
{
|
||||
$parser = new Parser();
|
||||
$dumper = new BinaryDumper();
|
||||
|
||||
$loop = Factory::create();
|
||||
|
||||
$server = stream_socket_server('udp://127.0.0.1:0', $errno, $errstr, STREAM_SERVER_BIND);
|
||||
$loop->addReadStream($server, function ($server) use ($parser, $dumper) {
|
||||
$data = stream_socket_recvfrom($server, 512, 0, $peer);
|
||||
|
||||
$message = $parser->parseMessage($data);
|
||||
$message->header->set('tc', 1);
|
||||
|
||||
stream_socket_sendto($server, $dumper->toBinary($message), 0, $peer);
|
||||
});
|
||||
|
||||
$address = stream_socket_get_name($server, false);
|
||||
$executor = new UdpTransportExecutor($loop, $parser, $dumper);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$wait = true;
|
||||
$promise = $executor->query($address, $query)->then(
|
||||
null,
|
||||
function ($e) use (&$wait) {
|
||||
$wait = false;
|
||||
throw $e;
|
||||
}
|
||||
);
|
||||
|
||||
// run loop for short period to ensure we detect connection ICMP rejection error
|
||||
\Clue\React\Block\sleep(0.01, $loop);
|
||||
if ($wait) {
|
||||
\Clue\React\Block\sleep(0.2, $loop);
|
||||
}
|
||||
|
||||
$this->assertFalse($wait);
|
||||
}
|
||||
|
||||
public function testQueryResolvesIfServerSendsValidResponse()
|
||||
{
|
||||
$parser = new Parser();
|
||||
$dumper = new BinaryDumper();
|
||||
|
||||
$loop = Factory::create();
|
||||
|
||||
$server = stream_socket_server('udp://127.0.0.1:0', $errno, $errstr, STREAM_SERVER_BIND);
|
||||
$loop->addReadStream($server, function ($server) use ($parser, $dumper) {
|
||||
$data = stream_socket_recvfrom($server, 512, 0, $peer);
|
||||
|
||||
$message = $parser->parseMessage($data);
|
||||
|
||||
stream_socket_sendto($server, $dumper->toBinary($message), 0, $peer);
|
||||
});
|
||||
|
||||
$address = stream_socket_get_name($server, false);
|
||||
$executor = new UdpTransportExecutor($loop, $parser, $dumper);
|
||||
|
||||
$query = new Query('google.com', Message::TYPE_A, Message::CLASS_IN);
|
||||
|
||||
$promise = $executor->query($address, $query);
|
||||
$response = \Clue\React\Block\await($promise, $loop, 0.2);
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Model\Message', $response);
|
||||
}
|
||||
}
|
||||
120
vendor/react/dns/tests/Resolver/FactoryTest.php
vendored
Executable file
120
vendor/react/dns/tests/Resolver/FactoryTest.php
vendored
Executable file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Resolver;
|
||||
|
||||
use React\Dns\Resolver\Factory;
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\Query\HostsFileExecutor;
|
||||
|
||||
class FactoryTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
public function createShouldCreateResolver()
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
|
||||
$factory = new Factory();
|
||||
$resolver = $factory->create('8.8.8.8:53', $loop);
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function createWithoutPortShouldCreateResolverWithDefaultPort()
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
|
||||
$factory = new Factory();
|
||||
$resolver = $factory->create('8.8.8.8', $loop);
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver);
|
||||
$this->assertSame('8.8.8.8:53', $this->getResolverPrivateMemberValue($resolver, 'nameserver'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function createCachedShouldCreateResolverWithCachingExecutor()
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
|
||||
$factory = new Factory();
|
||||
$resolver = $factory->createCached('8.8.8.8:53', $loop);
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver);
|
||||
$executor = $this->getResolverPrivateExecutor($resolver);
|
||||
$this->assertInstanceOf('React\Dns\Query\CachingExecutor', $executor);
|
||||
$cache = $this->getCachingExecutorPrivateMemberValue($executor, 'cache');
|
||||
$this->assertInstanceOf('React\Cache\ArrayCache', $cache);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function createCachedShouldCreateResolverWithCachingExecutorWithCustomCache()
|
||||
{
|
||||
$cache = $this->getMockBuilder('React\Cache\CacheInterface')->getMock();
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
|
||||
$factory = new Factory();
|
||||
$resolver = $factory->createCached('8.8.8.8:53', $loop, $cache);
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver);
|
||||
$executor = $this->getResolverPrivateExecutor($resolver);
|
||||
$this->assertInstanceOf('React\Dns\Query\CachingExecutor', $executor);
|
||||
$cacheProperty = $this->getCachingExecutorPrivateMemberValue($executor, 'cache');
|
||||
$this->assertSame($cache, $cacheProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider factoryShouldAddDefaultPortProvider
|
||||
*/
|
||||
public function factoryShouldAddDefaultPort($input, $expected)
|
||||
{
|
||||
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
|
||||
|
||||
$factory = new Factory();
|
||||
$resolver = $factory->create($input, $loop);
|
||||
|
||||
$this->assertInstanceOf('React\Dns\Resolver\Resolver', $resolver);
|
||||
$this->assertSame($expected, $this->getResolverPrivateMemberValue($resolver, 'nameserver'));
|
||||
}
|
||||
|
||||
public static function factoryShouldAddDefaultPortProvider()
|
||||
{
|
||||
return array(
|
||||
array('8.8.8.8', '8.8.8.8:53'),
|
||||
array('1.2.3.4:5', '1.2.3.4:5'),
|
||||
array('localhost', 'localhost:53'),
|
||||
array('localhost:1234', 'localhost:1234'),
|
||||
array('::1', '[::1]:53'),
|
||||
array('[::1]:53', '[::1]:53')
|
||||
);
|
||||
}
|
||||
|
||||
private function getResolverPrivateExecutor($resolver)
|
||||
{
|
||||
$executor = $this->getResolverPrivateMemberValue($resolver, 'executor');
|
||||
|
||||
// extract underlying executor that may be wrapped in multiple layers of hosts file executors
|
||||
while ($executor instanceof HostsFileExecutor) {
|
||||
$reflector = new \ReflectionProperty('React\Dns\Query\HostsFileExecutor', 'fallback');
|
||||
$reflector->setAccessible(true);
|
||||
|
||||
$executor = $reflector->getValue($executor);
|
||||
}
|
||||
|
||||
return $executor;
|
||||
}
|
||||
|
||||
private function getResolverPrivateMemberValue($resolver, $field)
|
||||
{
|
||||
$reflector = new \ReflectionProperty('React\Dns\Resolver\Resolver', $field);
|
||||
$reflector->setAccessible(true);
|
||||
return $reflector->getValue($resolver);
|
||||
}
|
||||
|
||||
private function getCachingExecutorPrivateMemberValue($resolver, $field)
|
||||
{
|
||||
$reflector = new \ReflectionProperty('React\Dns\Query\CachingExecutor', $field);
|
||||
$reflector->setAccessible(true);
|
||||
return $reflector->getValue($resolver);
|
||||
}
|
||||
}
|
||||
101
vendor/react/dns/tests/Resolver/ResolveAliasesTest.php
vendored
Executable file
101
vendor/react/dns/tests/Resolver/ResolveAliasesTest.php
vendored
Executable file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Resolver;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use React\Dns\Resolver\Resolver;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
|
||||
class ResolveAliasesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @covers React\Dns\Resolver\Resolver::resolveAliases
|
||||
* @covers React\Dns\Resolver\Resolver::valuesByNameAndType
|
||||
* @dataProvider provideAliasedAnswers
|
||||
*/
|
||||
public function testResolveAliases(array $expectedAnswers, array $answers, $name)
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
|
||||
$answers = $resolver->resolveAliases($answers, $name);
|
||||
|
||||
$this->assertEquals($expectedAnswers, $answers);
|
||||
}
|
||||
|
||||
public function provideAliasedAnswers()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array('178.79.169.131'),
|
||||
array(
|
||||
new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
array(
|
||||
array('178.79.169.131', '178.79.169.132', '178.79.169.133'),
|
||||
array(
|
||||
new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.132'),
|
||||
new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.133'),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
array(
|
||||
array('178.79.169.131'),
|
||||
array(
|
||||
new Record('igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
new Record('foo.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
new Record('bar.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
array(
|
||||
array(),
|
||||
array(
|
||||
new Record('foo.igor.io', Message::TYPE_A, Message::CLASS_IN),
|
||||
new Record('bar.igor.io', Message::TYPE_A, Message::CLASS_IN),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
array(
|
||||
array('178.79.169.131'),
|
||||
array(
|
||||
new Record('igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'foo.igor.io'),
|
||||
new Record('foo.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
array(
|
||||
array('178.79.169.131'),
|
||||
array(
|
||||
new Record('igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'foo.igor.io'),
|
||||
new Record('foo.igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'bar.igor.io'),
|
||||
new Record('bar.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
array(
|
||||
array('178.79.169.131', '178.79.169.132', '178.79.169.133'),
|
||||
array(
|
||||
new Record('igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'foo.igor.io'),
|
||||
new Record('foo.igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'bar.igor.io'),
|
||||
new Record('bar.igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'baz.igor.io'),
|
||||
new Record('bar.igor.io', Message::TYPE_CNAME, Message::CLASS_IN, 3600, 'qux.igor.io'),
|
||||
new Record('baz.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.131'),
|
||||
new Record('baz.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.132'),
|
||||
new Record('qux.igor.io', Message::TYPE_A, Message::CLASS_IN, 3600, '178.79.169.133'),
|
||||
),
|
||||
'igor.io',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function createExecutorMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
}
|
||||
}
|
||||
251
vendor/react/dns/tests/Resolver/ResolverTest.php
vendored
Executable file
251
vendor/react/dns/tests/Resolver/ResolverTest.php
vendored
Executable file
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns\Resolver;
|
||||
|
||||
use React\Dns\Resolver\Resolver;
|
||||
use React\Dns\Query\Query;
|
||||
use React\Dns\Model\Message;
|
||||
use React\Dns\Model\Record;
|
||||
use React\Promise;
|
||||
use React\Tests\Dns\TestCase;
|
||||
use React\Dns\RecordNotFoundException;
|
||||
|
||||
class ResolverTest extends TestCase
|
||||
{
|
||||
/** @test */
|
||||
public function resolveShouldQueryARecords()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
$response->answers[] = new Record($query->name, $query->type, $query->class, 3600, '178.79.169.131');
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolve('igor.io')->then($this->expectCallableOnceWith('178.79.169.131'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveAllShouldQueryGivenRecords()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
$response->answers[] = new Record($query->name, $query->type, $query->class, 3600, '::1');
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then($this->expectCallableOnceWith(array('::1')));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveAllShouldIgnoreRecordsWithOtherTypes()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
$response->answers[] = new Record($query->name, Message::TYPE_TXT, $query->class, 3600, array('ignored'));
|
||||
$response->answers[] = new Record($query->name, $query->type, $query->class, 3600, '::1');
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then($this->expectCallableOnceWith(array('::1')));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveAllShouldReturnMultipleValuesForAlias()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
$response->answers[] = new Record($query->name, Message::TYPE_CNAME, $query->class, 3600, 'example.com');
|
||||
$response->answers[] = new Record('example.com', $query->type, $query->class, 3600, '::1');
|
||||
$response->answers[] = new Record('example.com', $query->type, $query->class, 3600, '::2');
|
||||
$response->prepare();
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolveAll('reactphp.org', Message::TYPE_AAAA)->then(
|
||||
$this->expectCallableOnceWith($this->equalTo(array('::1', '::2')))
|
||||
);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldQueryARecordsAndIgnoreCase()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record('Blog.wyrihaximus.net', $query->type, $query->class);
|
||||
$response->answers[] = new Record('Blog.wyrihaximus.net', $query->type, $query->class, 3600, '178.79.169.131');
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolve('blog.wyrihaximus.net')->then($this->expectCallableOnceWith('178.79.169.131'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function resolveShouldFilterByName()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
$response->answers[] = new Record('foo.bar', $query->type, $query->class, 3600, '178.79.169.131');
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$errback = $this->expectCallableOnceWith($this->isInstanceOf('React\Dns\RecordNotFoundException'));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolve('igor.io')->then($this->expectCallableNever(), $errback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function resolveWithNoAnswersShouldCallErrbackIfGiven()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$errback = $this->expectCallableOnceWith($this->callback(function ($param) {
|
||||
return ($param instanceof RecordNotFoundException && $param->getCode() === 0 && $param->getMessage() === 'DNS query for igor.io did not return a valid answer (NOERROR / NODATA)');
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolve('igor.io')->then($this->expectCallableNever(), $errback);
|
||||
}
|
||||
|
||||
public function provideRcodeErrors()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
Message::RCODE_FORMAT_ERROR,
|
||||
'DNS query for example.com returned an error response (Format Error)',
|
||||
),
|
||||
array(
|
||||
Message::RCODE_SERVER_FAILURE,
|
||||
'DNS query for example.com returned an error response (Server Failure)',
|
||||
),
|
||||
array(
|
||||
Message::RCODE_NAME_ERROR,
|
||||
'DNS query for example.com returned an error response (Non-Existent Domain / NXDOMAIN)'
|
||||
),
|
||||
array(
|
||||
Message::RCODE_NOT_IMPLEMENTED,
|
||||
'DNS query for example.com returned an error response (Not Implemented)'
|
||||
),
|
||||
array(
|
||||
Message::RCODE_REFUSED,
|
||||
'DNS query for example.com returned an error response (Refused)'
|
||||
),
|
||||
array(
|
||||
99,
|
||||
'DNS query for example.com returned an error response (Unknown error response code 99)'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideRcodeErrors
|
||||
*/
|
||||
public function resolveWithRcodeErrorShouldCallErrbackIfGiven($code, $expectedMessage)
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$executor
|
||||
->expects($this->once())
|
||||
->method('query')
|
||||
->with($this->anything(), $this->isInstanceOf('React\Dns\Query\Query'))
|
||||
->will($this->returnCallback(function ($nameserver, $query) use ($code) {
|
||||
$response = new Message();
|
||||
$response->header->set('qr', 1);
|
||||
$response->header->set('rcode', $code);
|
||||
$response->questions[] = new Record($query->name, $query->type, $query->class);
|
||||
|
||||
return Promise\resolve($response);
|
||||
}));
|
||||
|
||||
$errback = $this->expectCallableOnceWith($this->callback(function ($param) use ($code, $expectedMessage) {
|
||||
return ($param instanceof RecordNotFoundException && $param->getCode() === $code && $param->getMessage() === $expectedMessage);
|
||||
}));
|
||||
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
$resolver->resolve('example.com')->then($this->expectCallableNever(), $errback);
|
||||
}
|
||||
|
||||
public function testLegacyExtractAddress()
|
||||
{
|
||||
$executor = $this->createExecutorMock();
|
||||
$resolver = new Resolver('8.8.8.8:53', $executor);
|
||||
|
||||
$query = new Query('reactphp.org', Message::TYPE_A, Message::CLASS_IN);
|
||||
$response = Message::createResponseWithAnswersForQuery($query, array(
|
||||
new Record('reactphp.org', Message::TYPE_A, Message::CLASS_IN, 3600, '1.2.3.4')
|
||||
));
|
||||
|
||||
$ret = $resolver->extractAddress($query, $response);
|
||||
$this->assertEquals('1.2.3.4', $ret);
|
||||
}
|
||||
|
||||
private function createExecutorMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Dns\Query\ExecutorInterface')->getMock();
|
||||
}
|
||||
}
|
||||
61
vendor/react/dns/tests/TestCase.php
vendored
Executable file
61
vendor/react/dns/tests/TestCase.php
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace React\Tests\Dns;
|
||||
|
||||
use PHPUnit\Framework\TestCase as BaseTestCase;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
protected function expectCallableOnce()
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke');
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function expectCallableOnceWith($value)
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($value);
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function expectCallableNever()
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->never())
|
||||
->method('__invoke');
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function createCallableMock()
|
||||
{
|
||||
return $this->getMockBuilder('React\Tests\Dns\CallableStub')->getMock();
|
||||
}
|
||||
|
||||
public function setExpectedException($exception, $exceptionMessage = '', $exceptionCode = null)
|
||||
{
|
||||
if (method_exists($this, 'expectException')) {
|
||||
// PHPUnit 5
|
||||
$this->expectException($exception);
|
||||
if ($exceptionMessage !== '') {
|
||||
$this->expectExceptionMessage($exceptionMessage);
|
||||
}
|
||||
if ($exceptionCode !== null) {
|
||||
$this->expectExceptionCode($exceptionCode);
|
||||
}
|
||||
} else {
|
||||
// legacy PHPUnit 4
|
||||
parent::setExpectedException($exception, $exceptionMessage, $exceptionCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user