diff options
Diffstat (limited to 'assets/php/vendor/react/socket/tests')
22 files changed, 3203 insertions, 0 deletions
diff --git a/assets/php/vendor/react/socket/tests/ConnectionTest.php b/assets/php/vendor/react/socket/tests/ConnectionTest.php new file mode 100644 index 0000000..d3563df --- /dev/null +++ b/assets/php/vendor/react/socket/tests/ConnectionTest.php @@ -0,0 +1,47 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\Connection; + +class ConnectionTest extends TestCase +{ + public function testCloseConnectionWillCloseSocketResource() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM does not support socket operation on test memory stream'); + } + + $resource = fopen('php://memory', 'r+'); + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $connection = new Connection($resource, $loop); + $connection->close(); + + $this->assertFalse(is_resource($resource)); + } + + public function testCloseConnectionWillRemoveResourceFromLoopBeforeClosingResource() + { + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM does not support socket operation on test memory stream'); + } + + $resource = fopen('php://memory', 'r+'); + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addWriteStream')->with($resource); + + $onRemove = null; + $loop->expects($this->once())->method('removeWriteStream')->with($this->callback(function ($param) use (&$onRemove) { + $onRemove = is_resource($param); + return true; + })); + + $connection = new Connection($resource, $loop); + $connection->write('test'); + $connection->close(); + + $this->assertTrue($onRemove); + $this->assertFalse(is_resource($resource)); + } +} diff --git a/assets/php/vendor/react/socket/tests/ConnectorTest.php b/assets/php/vendor/react/socket/tests/ConnectorTest.php new file mode 100644 index 0000000..c8eb19b --- /dev/null +++ b/assets/php/vendor/react/socket/tests/ConnectorTest.php @@ -0,0 +1,128 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\Connector; +use React\Promise\Promise; + +class ConnectorTest extends TestCase +{ + public function testConnectorUsesTcpAsDefaultScheme() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function () { }); + $tcp = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $tcp->expects($this->once())->method('connect')->with('127.0.0.1:80')->willReturn($promise); + + $connector = new Connector($loop, array( + 'tcp' => $tcp + )); + + $connector->connect('127.0.0.1:80'); + } + + public function testConnectorPassedThroughHostnameIfDnsIsDisabled() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function () { }); + $tcp = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $tcp->expects($this->once())->method('connect')->with('tcp://google.com:80')->willReturn($promise); + + $connector = new Connector($loop, array( + 'tcp' => $tcp, + 'dns' => false + )); + + $connector->connect('tcp://google.com:80'); + } + + public function testConnectorWithUnknownSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop); + + $promise = $connector->connect('unknown://google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledTcpDefaultSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'tcp' => false + )); + + $promise = $connector->connect('google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledTcpSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'tcp' => false + )); + + $promise = $connector->connect('tcp://google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledTlsSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'tls' => false + )); + + $promise = $connector->connect('tls://google.com:443'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorWithDisabledUnixSchemeAlwaysFails() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new Connector($loop, array( + 'unix' => false + )); + + $promise = $connector->connect('unix://demo.sock'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testConnectorUsesGivenResolverInstance() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function () { }); + $resolver = $this->getMockBuilder('React\Dns\Resolver\Resolver')->disableOriginalConstructor()->getMock(); + $resolver->expects($this->once())->method('resolve')->with('google.com')->willReturn($promise); + + $connector = new Connector($loop, array( + 'dns' => $resolver + )); + + $connector->connect('google.com:80'); + } + + public function testConnectorUsesResolvedHostnameIfDnsIsUsed() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $promise = new Promise(function ($resolve) { $resolve('127.0.0.1'); }); + $resolver = $this->getMockBuilder('React\Dns\Resolver\Resolver')->disableOriginalConstructor()->getMock(); + $resolver->expects($this->once())->method('resolve')->with('google.com')->willReturn($promise); + + $promise = new Promise(function () { }); + $tcp = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $tcp->expects($this->once())->method('connect')->with('tcp://127.0.0.1:80?hostname=google.com')->willReturn($promise); + + $connector = new Connector($loop, array( + 'tcp' => $tcp, + 'dns' => $resolver + )); + + $connector->connect('tcp://google.com:80'); + } +} diff --git a/assets/php/vendor/react/socket/tests/DnsConnectorTest.php b/assets/php/vendor/react/socket/tests/DnsConnectorTest.php new file mode 100644 index 0000000..3c94c39 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/DnsConnectorTest.php @@ -0,0 +1,111 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\DnsConnector; +use React\Promise; + +class DnsConnectorTest extends TestCase +{ + private $tcp; + private $resolver; + private $connector; + + public function setUp() + { + $this->tcp = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $this->resolver = $this->getMockBuilder('React\Dns\Resolver\Resolver')->disableOriginalConstructor()->getMock(); + + $this->connector = new DnsConnector($this->tcp, $this->resolver); + } + + public function testPassByResolverIfGivenIp() + { + $this->resolver->expects($this->never())->method('resolve'); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('127.0.0.1:80'))->will($this->returnValue(Promise\reject())); + + $this->connector->connect('127.0.0.1:80'); + } + + public function testPassThroughResolverIfGivenHost() + { + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('google.com'))->will($this->returnValue(Promise\resolve('1.2.3.4'))); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('1.2.3.4:80?hostname=google.com'))->will($this->returnValue(Promise\reject())); + + $this->connector->connect('google.com:80'); + } + + public function testPassThroughResolverIfGivenHostWhichResolvesToIpv6() + { + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('google.com'))->will($this->returnValue(Promise\resolve('::1'))); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('[::1]:80?hostname=google.com'))->will($this->returnValue(Promise\reject())); + + $this->connector->connect('google.com:80'); + } + + public function testPassByResolverIfGivenCompleteUri() + { + $this->resolver->expects($this->never())->method('resolve'); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('scheme://127.0.0.1:80/path?query#fragment'))->will($this->returnValue(Promise\reject())); + + $this->connector->connect('scheme://127.0.0.1:80/path?query#fragment'); + } + + public function testPassThroughResolverIfGivenCompleteUri() + { + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('google.com'))->will($this->returnValue(Promise\resolve('1.2.3.4'))); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('scheme://1.2.3.4:80/path?query&hostname=google.com#fragment'))->will($this->returnValue(Promise\reject())); + + $this->connector->connect('scheme://google.com:80/path?query#fragment'); + } + + public function testPassThroughResolverIfGivenExplicitHost() + { + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('google.com'))->will($this->returnValue(Promise\resolve('1.2.3.4'))); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('scheme://1.2.3.4:80/?hostname=google.de'))->will($this->returnValue(Promise\reject())); + + $this->connector->connect('scheme://google.com:80/?hostname=google.de'); + } + + public function testRejectsImmediatelyIfUriIsInvalid() + { + $this->resolver->expects($this->never())->method('resolve'); + $this->tcp->expects($this->never())->method('connect'); + + $promise = $this->connector->connect('////'); + + $promise->then($this->expectCallableNever(), $this->expectCallableOnce()); + } + + public function testSkipConnectionIfDnsFails() + { + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('example.invalid'))->will($this->returnValue(Promise\reject())); + $this->tcp->expects($this->never())->method('connect'); + + $this->connector->connect('example.invalid:80'); + } + + public function testCancelDuringDnsCancelsDnsAndDoesNotStartTcpConnection() + { + $pending = new Promise\Promise(function () { }, $this->expectCallableOnce()); + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('example.com'))->will($this->returnValue($pending)); + $this->tcp->expects($this->never())->method('connect'); + + $promise = $this->connector->connect('example.com:80'); + $promise->cancel(); + + $promise->then($this->expectCallableNever(), $this->expectCallableOnce()); + } + + public function testCancelDuringTcpConnectionCancelsTcpConnection() + { + $pending = new Promise\Promise(function () { }, function () { throw new \Exception(); }); + $this->resolver->expects($this->once())->method('resolve')->with($this->equalTo('example.com'))->will($this->returnValue(Promise\resolve('1.2.3.4'))); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('1.2.3.4:80?hostname=example.com'))->will($this->returnValue($pending)); + + $promise = $this->connector->connect('example.com:80'); + $promise->cancel(); + + $promise->then($this->expectCallableNever(), $this->expectCallableOnce()); + } +} diff --git a/assets/php/vendor/react/socket/tests/FixedUriConnectorTest.php b/assets/php/vendor/react/socket/tests/FixedUriConnectorTest.php new file mode 100644 index 0000000..f42d74f --- /dev/null +++ b/assets/php/vendor/react/socket/tests/FixedUriConnectorTest.php @@ -0,0 +1,19 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\FixedUriConnector; +use React\Tests\Socket\TestCase; + +class FixedUriConnectorTest extends TestCase +{ + public function testWillInvokeGivenConnector() + { + $base = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $base->expects($this->once())->method('connect')->with('test')->willReturn('ret'); + + $connector = new FixedUriConnector('test', $base); + + $this->assertEquals('ret', $connector->connect('ignored')); + } +} diff --git a/assets/php/vendor/react/socket/tests/FunctionalConnectorTest.php b/assets/php/vendor/react/socket/tests/FunctionalConnectorTest.php new file mode 100644 index 0000000..6611352 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/FunctionalConnectorTest.php @@ -0,0 +1,32 @@ +<?php + +namespace React\Tests\Socket; + +use Clue\React\Block; +use React\EventLoop\Factory; +use React\Socket\Connector; +use React\Socket\TcpServer; + +class FunctionalConnectorTest extends TestCase +{ + const TIMEOUT = 1.0; + + /** @test */ + public function connectionToTcpServerShouldSucceedWithLocalhost() + { + $loop = Factory::create(); + + $server = new TcpServer(9998, $loop); + $server->on('connection', $this->expectCallableOnce()); + $server->on('connection', array($server, 'close')); + + $connector = new Connector($loop); + + $connection = Block\await($connector->connect('localhost:9998'), $loop, self::TIMEOUT); + + $this->assertInstanceOf('React\Socket\ConnectionInterface', $connection); + + $connection->close(); + $server->close(); + } +} diff --git a/assets/php/vendor/react/socket/tests/FunctionalSecureServerTest.php b/assets/php/vendor/react/socket/tests/FunctionalSecureServerTest.php new file mode 100644 index 0000000..78a59d0 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/FunctionalSecureServerTest.php @@ -0,0 +1,438 @@ +<?php + +namespace React\Tests\Socket; + +use React\EventLoop\Factory; +use React\Socket\SecureServer; +use React\Socket\ConnectionInterface; +use React\Socket\TcpServer; +use React\Socket\TcpConnector; +use React\Socket\SecureConnector; +use Clue\React\Block; + +class FunctionalSecureServerTest extends TestCase +{ + const TIMEOUT = 0.5; + + public function setUp() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + } + + public function testEmitsConnectionForNewConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + Block\await($promise, $loop, self::TIMEOUT); + } + + public function testWritesDataToConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $server->on('connection', function (ConnectionInterface $conn) { + $conn->write('foo'); + }); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $local = Block\await($promise, $loop, self::TIMEOUT); + /* @var $local ConnectionInterface */ + + $local->on('data', $this->expectCallableOnceWith('foo')); + + Block\sleep(self::TIMEOUT, $loop); + } + + public function testWritesDataInMultipleChunksToConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $server->on('connection', function (ConnectionInterface $conn) { + $conn->write(str_repeat('*', 400000)); + }); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $local = Block\await($promise, $loop, self::TIMEOUT); + /* @var $local React\Stream\Stream */ + + $received = 0; + $local->on('data', function ($chunk) use (&$received) { + $received += strlen($chunk); + }); + + Block\sleep(self::TIMEOUT, $loop); + + $this->assertEquals(400000, $received); + } + + public function testWritesMoreDataInMultipleChunksToConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $server->on('connection', function (ConnectionInterface $conn) { + $conn->write(str_repeat('*', 2000000)); + }); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $local = Block\await($promise, $loop, self::TIMEOUT); + /* @var $local React\Stream\Stream */ + + $received = 0; + $local->on('data', function ($chunk) use (&$received) { + $received += strlen($chunk); + }); + + Block\sleep(self::TIMEOUT, $loop); + + $this->assertEquals(2000000, $received); + } + + public function testEmitsDataFromConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $once = $this->expectCallableOnceWith('foo'); + $server->on('connection', function (ConnectionInterface $conn) use ($once) { + $conn->on('data', $once); + }); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $local = Block\await($promise, $loop, self::TIMEOUT); + /* @var $local React\Stream\Stream */ + + $local->write("foo"); + + Block\sleep(self::TIMEOUT, $loop); + } + + public function testEmitsDataInMultipleChunksFromConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $received = 0; + $server->on('connection', function (ConnectionInterface $conn) use (&$received) { + $conn->on('data', function ($chunk) use (&$received) { + $received += strlen($chunk); + }); + }); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $local = Block\await($promise, $loop, self::TIMEOUT); + /* @var $local React\Stream\Stream */ + + $local->write(str_repeat('*', 400000)); + + Block\sleep(self::TIMEOUT, $loop); + + $this->assertEquals(400000, $received); + } + + public function testPipesDataBackInMultipleChunksFromConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableOnce()); + + $server->on('connection', function (ConnectionInterface $conn) use (&$received) { + $conn->pipe($conn); + }); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $local = Block\await($promise, $loop, self::TIMEOUT); + /* @var $local React\Stream\Stream */ + + $received = 0; + $local->on('data', function ($chunk) use (&$received) { + $received += strlen($chunk); + }); + + $local->write(str_repeat('*', 400000)); + + Block\sleep(self::TIMEOUT, $loop); + + $this->assertEquals(400000, $received); + } + + /** + * @requires PHP 5.6 + */ + public function testEmitsConnectionForNewTlsv11Connection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_SERVER + )); + $server->on('connection', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false, + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT + )); + $promise = $connector->connect($server->getAddress()); + + Block\await($promise, $loop, self::TIMEOUT); + } + + /** + * @requires PHP 5.6 + */ + public function testEmitsErrorForClientWithTlsVersionMismatch() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_SERVER|STREAM_CRYPTO_METHOD_TLSv1_2_SERVER + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false, + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT + )); + $promise = $connector->connect($server->getAddress()); + + $this->setExpectedException('RuntimeException', 'handshake'); + Block\await($promise, $loop, self::TIMEOUT); + } + + public function testEmitsConnectionForNewConnectionWithEncryptedCertificate() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost_swordfish.pem', + 'passphrase' => 'swordfish' + )); + $server->on('connection', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + Block\await($promise, $loop, self::TIMEOUT); + } + + public function testEmitsErrorForServerWithInvalidCertificate() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => 'invalid.pem' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $this->setExpectedException('RuntimeException', 'handshake'); + Block\await($promise, $loop, self::TIMEOUT); + } + + public function testEmitsErrorForServerWithEncryptedCertificateMissingPassphrase() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost_swordfish.pem' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $this->setExpectedException('RuntimeException', 'handshake'); + Block\await($promise, $loop, self::TIMEOUT); + } + + public function testEmitsErrorForServerWithEncryptedCertificateWithInvalidPassphrase() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost_swordfish.pem', + 'passphrase' => 'nope' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + + $this->setExpectedException('RuntimeException', 'handshake'); + Block\await($promise, $loop, self::TIMEOUT); + } + + public function testEmitsErrorForConnectionWithPeerVerification() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => true + )); + $promise = $connector->connect($server->getAddress()); + + $promise->then(null, $this->expectCallableOnce()); + Block\sleep(self::TIMEOUT, $loop); + } + + public function testEmitsErrorIfConnectionIsCancelled() + { + if (PHP_OS !== 'Linux') { + $this->markTestSkipped('Linux only (OS is ' . PHP_OS . ')'); + } + + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new SecureConnector(new TcpConnector($loop), $loop, array( + 'verify_peer' => false + )); + $promise = $connector->connect($server->getAddress()); + $promise->cancel(); + + $promise->then(null, $this->expectCallableOnce()); + Block\sleep(self::TIMEOUT, $loop); + } + + public function testEmitsNothingIfConnectionIsIdle() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableNever()); + + $connector = new TcpConnector($loop); + $promise = $connector->connect(str_replace('tls://', '', $server->getAddress())); + + $promise->then($this->expectCallableOnce()); + Block\sleep(self::TIMEOUT, $loop); + } + + public function testEmitsErrorIfConnectionIsNotSecureHandshake() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new SecureServer($server, $loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $server->on('connection', $this->expectCallableNever()); + $server->on('error', $this->expectCallableOnce()); + + $connector = new TcpConnector($loop); + $promise = $connector->connect(str_replace('tls://', '', $server->getAddress())); + + $promise->then(function (ConnectionInterface $stream) { + $stream->write("GET / HTTP/1.0\r\n\r\n"); + }); + + Block\sleep(self::TIMEOUT, $loop); + } +} diff --git a/assets/php/vendor/react/socket/tests/FunctionalTcpServerTest.php b/assets/php/vendor/react/socket/tests/FunctionalTcpServerTest.php new file mode 100644 index 0000000..ec7855e --- /dev/null +++ b/assets/php/vendor/react/socket/tests/FunctionalTcpServerTest.php @@ -0,0 +1,324 @@ +<?php + +namespace React\Tests\Socket; + +use React\EventLoop\Factory; +use React\Socket\TcpServer; +use React\Socket\ConnectionInterface; +use React\Socket\TcpConnector; +use Clue\React\Block; + +class FunctionalTcpServerTest extends TestCase +{ + public function testEmitsConnectionForNewConnection() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server->on('connection', $this->expectCallableOnce()); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + } + + public function testEmitsNoConnectionForNewConnectionWhenPaused() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server->on('connection', $this->expectCallableNever()); + $server->pause(); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + } + + public function testEmitsConnectionForNewConnectionWhenResumedAfterPause() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server->on('connection', $this->expectCallableOnce()); + $server->pause(); + $server->resume(); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + } + + public function testEmitsConnectionWithRemoteIp() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $peer = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$peer) { + $peer = $conn->getRemoteAddress(); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertContains('127.0.0.1:', $peer); + } + + public function testEmitsConnectionWithLocalIp() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $local = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$local) { + $local = $conn->getLocalAddress(); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertContains('127.0.0.1:', $local); + $this->assertEquals($server->getAddress(), $local); + } + + public function testEmitsConnectionWithLocalIpDespiteListeningOnAll() + { + $loop = Factory::create(); + + $server = new TcpServer('0.0.0.0:0', $loop); + $local = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$local) { + $local = $conn->getLocalAddress(); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertContains('127.0.0.1:', $local); + } + + public function testEmitsConnectionWithRemoteIpAfterConnectionIsClosedByPeer() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $peer = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$peer) { + $conn->on('close', function () use ($conn, &$peer) { + $peer = $conn->getRemoteAddress(); + }); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $client = Block\await($promise, $loop, 0.1); + $client->end(); + + Block\sleep(0.1, $loop); + + $this->assertContains('127.0.0.1:', $peer); + } + + public function testEmitsConnectionWithRemoteNullAddressAfterConnectionIsClosedLocally() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $peer = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$peer) { + $conn->close(); + $peer = $conn->getRemoteAddress(); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertNull($peer); + } + + public function testEmitsConnectionEvenIfConnectionIsCancelled() + { + if (PHP_OS !== 'Linux') { + $this->markTestSkipped('Linux only (OS is ' . PHP_OS . ')'); + } + + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server->on('connection', $this->expectCallableOnce()); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + $promise->cancel(); + + $promise->then(null, $this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + } + + public function testEmitsConnectionForNewIpv6Connection() + { + $loop = Factory::create(); + + try { + $server = new TcpServer('[::1]:0', $loop); + } catch (\RuntimeException $e) { + $this->markTestSkipped('Unable to start IPv6 server socket (not available on your platform?)'); + } + + $server->on('connection', $this->expectCallableOnce()); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + } + + public function testEmitsConnectionWithRemoteIpv6() + { + $loop = Factory::create(); + + try { + $server = new TcpServer('[::1]:0', $loop); + } catch (\RuntimeException $e) { + $this->markTestSkipped('Unable to start IPv6 server socket (not available on your platform?)'); + } + + $peer = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$peer) { + $peer = $conn->getRemoteAddress(); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertContains('[::1]:', $peer); + } + + public function testEmitsConnectionWithLocalIpv6() + { + $loop = Factory::create(); + + try { + $server = new TcpServer('[::1]:0', $loop); + } catch (\RuntimeException $e) { + $this->markTestSkipped('Unable to start IPv6 server socket (not available on your platform?)'); + } + + $local = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$local) { + $local = $conn->getLocalAddress(); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertContains('[::1]:', $local); + $this->assertEquals($server->getAddress(), $local); + } + + public function testEmitsConnectionWithInheritedContextOptions() + { + if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.13', '<')) { + // https://3v4l.org/hB4Tc + $this->markTestSkipped('Not supported on legacy HHVM < 3.13'); + } + + $loop = Factory::create(); + + $server = new TcpServer(0, $loop, array( + 'backlog' => 4 + )); + + $all = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$all) { + $all = stream_context_get_options($conn->stream); + }); + + $connector = new TcpConnector($loop); + $promise = $connector->connect($server->getAddress()); + + $promise->then($this->expectCallableOnce()); + + Block\sleep(0.1, $loop); + + $this->assertEquals(array('socket' => array('backlog' => 4)), $all); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnInvalidUri() + { + $loop = Factory::create(); + + new TcpServer('///', $loop); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnUriWithoutPort() + { + $loop = Factory::create(); + + new TcpServer('127.0.0.1', $loop); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnUriWithWrongScheme() + { + $loop = Factory::create(); + + new TcpServer('udp://127.0.0.1:0', $loop); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testFailsToListenOnUriWIthHostname() + { + $loop = Factory::create(); + + new TcpServer('localhost:8080', $loop); + } +} diff --git a/assets/php/vendor/react/socket/tests/IntegrationTest.php b/assets/php/vendor/react/socket/tests/IntegrationTest.php new file mode 100644 index 0000000..24dbe37 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/IntegrationTest.php @@ -0,0 +1,171 @@ +<?php + +namespace React\Tests\Socket; + +use Clue\React\Block; +use React\Dns\Resolver\Factory as ResolverFactory; +use React\EventLoop\Factory; +use React\Socket\Connector; +use React\Socket\DnsConnector; +use React\Socket\SecureConnector; +use React\Socket\TcpConnector; + +/** @group internet */ +class IntegrationTest extends TestCase +{ + const TIMEOUT = 5.0; + + /** @test */ + public function gettingStuffFromGoogleShouldWork() + { + $loop = Factory::create(); + $connector = new Connector($loop); + + $conn = Block\await($connector->connect('google.com:80'), $loop); + + $this->assertContains(':80', $conn->getRemoteAddress()); + $this->assertNotEquals('google.com:80', $conn->getRemoteAddress()); + + $conn->write("GET / HTTP/1.0\r\n\r\n"); + + $response = $this->buffer($conn, $loop, self::TIMEOUT); + + $this->assertRegExp('#^HTTP/1\.0#', $response); + } + + /** @test */ + public function gettingEncryptedStuffFromGoogleShouldWork() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = Factory::create(); + $secureConnector = new Connector($loop); + + $conn = Block\await($secureConnector->connect('tls://google.com:443'), $loop); + + $conn->write("GET / HTTP/1.0\r\n\r\n"); + + $response = $this->buffer($conn, $loop, self::TIMEOUT); + + $this->assertRegExp('#^HTTP/1\.0#', $response); + } + + /** @test */ + public function gettingEncryptedStuffFromGoogleShouldWorkIfHostIsResolvedFirst() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = Factory::create(); + + $factory = new ResolverFactory(); + $dns = $factory->create('8.8.8.8', $loop); + + $connector = new DnsConnector( + new SecureConnector( + new TcpConnector($loop), + $loop + ), + $dns + ); + + $conn = Block\await($connector->connect('google.com:443'), $loop); + + $conn->write("GET / HTTP/1.0\r\n\r\n"); + + $response = $this->buffer($conn, $loop, self::TIMEOUT); + + $this->assertRegExp('#^HTTP/1\.0#', $response); + } + + /** @test */ + public function gettingPlaintextStuffFromEncryptedGoogleShouldNotWork() + { + $loop = Factory::create(); + $connector = new Connector($loop); + + $conn = Block\await($connector->connect('google.com:443'), $loop); + + $this->assertContains(':443', $conn->getRemoteAddress()); + $this->assertNotEquals('google.com:443', $conn->getRemoteAddress()); + + $conn->write("GET / HTTP/1.0\r\n\r\n"); + + $response = $this->buffer($conn, $loop, self::TIMEOUT); + + $this->assertNotRegExp('#^HTTP/1\.0#', $response); + } + + public function testConnectingFailsIfDnsUsesInvalidResolver() + { + $loop = Factory::create(); + + $factory = new ResolverFactory(); + $dns = $factory->create('demo.invalid', $loop); + + $connector = new Connector($loop, array( + 'dns' => $dns + )); + + $this->setExpectedException('RuntimeException'); + Block\await($connector->connect('google.com:80'), $loop, self::TIMEOUT); + } + + public function testConnectingFailsIfTimeoutIsTooSmall() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = Factory::create(); + + $connector = new Connector($loop, array( + 'timeout' => 0.001 + )); + + $this->setExpectedException('RuntimeException'); + Block\await($connector->connect('google.com:80'), $loop, self::TIMEOUT); + } + + public function testSelfSignedRejectsIfVerificationIsEnabled() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = Factory::create(); + + $connector = new Connector($loop, array( + 'tls' => array( + 'verify_peer' => true + ) + )); + + $this->setExpectedException('RuntimeException'); + Block\await($connector->connect('tls://self-signed.badssl.com:443'), $loop, self::TIMEOUT); + } + + public function testSelfSignedResolvesIfVerificationIsDisabled() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = Factory::create(); + + $connector = new Connector($loop, array( + 'tls' => array( + 'verify_peer' => false + ) + )); + + $conn = Block\await($connector->connect('tls://self-signed.badssl.com:443'), $loop, self::TIMEOUT); + $conn->close(); + + // if we reach this, then everything is good + $this->assertNull(null); + } +} diff --git a/assets/php/vendor/react/socket/tests/LimitingServerTest.php b/assets/php/vendor/react/socket/tests/LimitingServerTest.php new file mode 100644 index 0000000..2cc9a58 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/LimitingServerTest.php @@ -0,0 +1,195 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\LimitingServer; +use React\Socket\TcpServer; +use React\EventLoop\Factory; +use Clue\React\Block; + +class LimitingServerTest extends TestCase +{ + public function testGetAddressWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('getAddress')->willReturn('127.0.0.1:1234'); + + $server = new LimitingServer($tcp, 100); + + $this->assertEquals('127.0.0.1:1234', $server->getAddress()); + } + + public function testPauseWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('pause'); + + $server = new LimitingServer($tcp, 100); + + $server->pause(); + } + + public function testPauseTwiceWillBePassedThroughToTcpServerOnce() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('pause'); + + $server = new LimitingServer($tcp, 100); + + $server->pause(); + $server->pause(); + } + + public function testResumeWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('resume'); + + $server = new LimitingServer($tcp, 100); + + $server->pause(); + $server->resume(); + } + + public function testResumeTwiceWillBePassedThroughToTcpServerOnce() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('resume'); + + $server = new LimitingServer($tcp, 100); + + $server->pause(); + $server->resume(); + $server->resume(); + } + + public function testCloseWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('close'); + + $server = new LimitingServer($tcp, 100); + + $server->close(); + } + + public function testSocketErrorWillBeForwarded() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $tcp = new TcpServer(0, $loop); + + $server = new LimitingServer($tcp, 100); + + $server->on('error', $this->expectCallableOnce()); + + $tcp->emit('error', array(new \RuntimeException('test'))); + } + + public function testSocketConnectionWillBeForwarded() + { + $connection = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $tcp = new TcpServer(0, $loop); + + $server = new LimitingServer($tcp, 100); + $server->on('connection', $this->expectCallableOnceWith($connection)); + $server->on('error', $this->expectCallableNever()); + + $tcp->emit('connection', array($connection)); + + $this->assertEquals(array($connection), $server->getConnections()); + } + + public function testSocketConnectionWillBeClosedOnceLimitIsReached() + { + $first = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $first->expects($this->never())->method('close'); + $second = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $second->expects($this->once())->method('close'); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $tcp = new TcpServer(0, $loop); + + $server = new LimitingServer($tcp, 1); + $server->on('connection', $this->expectCallableOnceWith($first)); + $server->on('error', $this->expectCallableOnce()); + + $tcp->emit('connection', array($first)); + $tcp->emit('connection', array($second)); + } + + public function testPausingServerWillBePausedOnceLimitIsReached() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addReadStream'); + $loop->expects($this->once())->method('removeReadStream'); + + $tcp = new TcpServer(0, $loop); + + $connection = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + + $server = new LimitingServer($tcp, 1, true); + + $tcp->emit('connection', array($connection)); + } + + public function testSocketDisconnectionWillRemoveFromList() + { + $loop = Factory::create(); + + $tcp = new TcpServer(0, $loop); + + $socket = stream_socket_client($tcp->getAddress()); + fclose($socket); + + $server = new LimitingServer($tcp, 100); + $server->on('connection', $this->expectCallableOnce()); + $server->on('error', $this->expectCallableNever()); + + Block\sleep(0.1, $loop); + + $this->assertEquals(array(), $server->getConnections()); + } + + public function testPausingServerWillEmitOnlyOneButAcceptTwoConnectionsDueToOperatingSystem() + { + $loop = Factory::create(); + + $server = new TcpServer(0, $loop); + $server = new LimitingServer($server, 1, true); + $server->on('connection', $this->expectCallableOnce()); + $server->on('error', $this->expectCallableNever()); + + $first = stream_socket_client($server->getAddress()); + $second = stream_socket_client($server->getAddress()); + + Block\sleep(0.1, $loop); + + fclose($first); + fclose($second); + } + + public function testPausingServerWillEmitTwoConnectionsFromBacklog() + { + $loop = Factory::create(); + + $twice = $this->createCallableMock(); + $twice->expects($this->exactly(2))->method('__invoke'); + + $server = new TcpServer(0, $loop); + $server = new LimitingServer($server, 1, true); + $server->on('connection', $twice); + $server->on('error', $this->expectCallableNever()); + + $first = stream_socket_client($server->getAddress()); + fclose($first); + $second = stream_socket_client($server->getAddress()); + fclose($second); + + Block\sleep(0.1, $loop); + } +} diff --git a/assets/php/vendor/react/socket/tests/SecureConnectorTest.php b/assets/php/vendor/react/socket/tests/SecureConnectorTest.php new file mode 100644 index 0000000..0b3a702 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/SecureConnectorTest.php @@ -0,0 +1,74 @@ +<?php + +namespace React\Tests\Socket; + +use React\Promise; +use React\Socket\SecureConnector; + +class SecureConnectorTest extends TestCase +{ + private $loop; + private $tcp; + private $connector; + + public function setUp() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $this->tcp = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $this->connector = new SecureConnector($this->tcp, $this->loop); + } + + public function testConnectionWillWaitForTcpConnection() + { + $pending = new Promise\Promise(function () { }); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('example.com:80'))->will($this->returnValue($pending)); + + $promise = $this->connector->connect('example.com:80'); + + $this->assertInstanceOf('React\Promise\PromiseInterface', $promise); + } + + public function testConnectionWithCompleteUriWillBePassedThroughExpectForScheme() + { + $pending = new Promise\Promise(function () { }); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('example.com:80/path?query#fragment'))->will($this->returnValue($pending)); + + $this->connector->connect('tls://example.com:80/path?query#fragment'); + } + + public function testConnectionToInvalidSchemeWillReject() + { + $this->tcp->expects($this->never())->method('connect'); + + $promise = $this->connector->connect('tcp://example.com:80'); + + $promise->then(null, $this->expectCallableOnce()); + } + + public function testCancelDuringTcpConnectionCancelsTcpConnection() + { + $pending = new Promise\Promise(function () { }, function () { throw new \Exception(); }); + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('example.com:80'))->will($this->returnValue($pending)); + + $promise = $this->connector->connect('example.com:80'); + $promise->cancel(); + + $promise->then($this->expectCallableNever(), $this->expectCallableOnce()); + } + + public function testConnectionWillBeClosedAndRejectedIfConnectioIsNoStream() + { + $connection = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $connection->expects($this->once())->method('close'); + + $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('example.com:80'))->willReturn(Promise\resolve($connection)); + + $promise = $this->connector->connect('example.com:80'); + + $promise->then($this->expectCallableNever(), $this->expectCallableOnce()); + } +} diff --git a/assets/php/vendor/react/socket/tests/SecureIntegrationTest.php b/assets/php/vendor/react/socket/tests/SecureIntegrationTest.php new file mode 100644 index 0000000..8c9ba14 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/SecureIntegrationTest.php @@ -0,0 +1,204 @@ +<?php + +namespace React\Tests\Socket; + +use React\EventLoop\Factory as LoopFactory; +use React\Socket\TcpServer; +use React\Socket\SecureServer; +use React\Socket\TcpConnector; +use React\Socket\SecureConnector; +use Clue\React\Block; +use React\Promise\Promise; +use Evenement\EventEmitterInterface; +use React\Promise\Deferred; +use React\Socket\ConnectionInterface; + +class SecureIntegrationTest extends TestCase +{ + const TIMEOUT = 0.5; + + private $loop; + private $server; + private $connector; + private $address; + + public function setUp() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $this->loop = LoopFactory::create(); + $this->server = new TcpServer(0, $this->loop); + $this->server = new SecureServer($this->server, $this->loop, array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + )); + $this->address = $this->server->getAddress(); + $this->connector = new SecureConnector(new TcpConnector($this->loop), $this->loop, array('verify_peer' => false)); + } + + public function tearDown() + { + if ($this->server !== null) { + $this->server->close(); + $this->server = null; + } + } + + public function testConnectToServer() + { + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + $client->close(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testConnectToServerEmitsConnection() + { + $promiseServer = $this->createPromiseForEvent($this->server, 'connection', $this->expectCallableOnce()); + + $promiseClient = $this->connector->connect($this->address); + + list($_, $client) = Block\awaitAll(array($promiseServer, $promiseClient), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + $client->close(); + } + + public function testSendSmallDataToServerReceivesOneChunk() + { + // server expects one connection which emits one data event + $received = new Deferred(); + $this->server->on('connection', function (ConnectionInterface $peer) use ($received) { + $peer->on('data', function ($chunk) use ($received) { + $received->resolve($chunk); + }); + }); + + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + $client->write('hello'); + + // await server to report one "data" event + $data = Block\await($received->promise(), $this->loop, self::TIMEOUT); + + $client->close(); + + $this->assertEquals('hello', $data); + } + + public function testSendDataWithEndToServerReceivesAllData() + { + $disconnected = new Deferred(); + $this->server->on('connection', function (ConnectionInterface $peer) use ($disconnected) { + $received = ''; + $peer->on('data', function ($chunk) use (&$received) { + $received .= $chunk; + }); + $peer->on('close', function () use (&$received, $disconnected) { + $disconnected->resolve($received); + }); + }); + + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + $data = str_repeat('a', 200000); + $client->end($data); + + // await server to report connection "close" event + $received = Block\await($disconnected->promise(), $this->loop, self::TIMEOUT); + + $this->assertEquals($data, $received); + } + + public function testSendDataWithoutEndingToServerReceivesAllData() + { + $received = ''; + $this->server->on('connection', function (ConnectionInterface $peer) use (&$received) { + $peer->on('data', function ($chunk) use (&$received) { + $received .= $chunk; + }); + }); + + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + $data = str_repeat('d', 200000); + $client->write($data); + + // buffer incoming data for 0.1s (should be plenty of time) + Block\sleep(0.1, $this->loop); + + $client->close(); + + $this->assertEquals($data, $received); + } + + public function testConnectToServerWhichSendsSmallDataReceivesOneChunk() + { + $this->server->on('connection', function (ConnectionInterface $peer) { + $peer->write('hello'); + }); + + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + // await client to report one "data" event + $receive = $this->createPromiseForEvent($client, 'data', $this->expectCallableOnceWith('hello')); + Block\await($receive, $this->loop, self::TIMEOUT); + + $client->close(); + } + + public function testConnectToServerWhichSendsDataWithEndReceivesAllData() + { + $data = str_repeat('b', 100000); + $this->server->on('connection', function (ConnectionInterface $peer) use ($data) { + $peer->end($data); + }); + + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + // await data from client until it closes + $received = $this->buffer($client, $this->loop, self::TIMEOUT); + + $this->assertEquals($data, $received); + } + + public function testConnectToServerWhichSendsDataWithoutEndingReceivesAllData() + { + $data = str_repeat('c', 100000); + $this->server->on('connection', function (ConnectionInterface $peer) use ($data) { + $peer->write($data); + }); + + $client = Block\await($this->connector->connect($this->address), $this->loop, self::TIMEOUT); + /* @var $client ConnectionInterface */ + + // buffer incoming data for 0.1s (should be plenty of time) + $received = ''; + $client->on('data', function ($chunk) use (&$received) { + $received .= $chunk; + }); + Block\sleep(0.1, $this->loop); + + $client->close(); + + $this->assertEquals($data, $received); + } + + private function createPromiseForEvent(EventEmitterInterface $emitter, $event, $fn) + { + return new Promise(function ($resolve) use ($emitter, $event, $fn) { + $emitter->on($event, function () use ($resolve, $fn) { + $resolve(call_user_func_array($fn, func_get_args())); + }); + }); + } +} diff --git a/assets/php/vendor/react/socket/tests/SecureServerTest.php b/assets/php/vendor/react/socket/tests/SecureServerTest.php new file mode 100644 index 0000000..92c641f --- /dev/null +++ b/assets/php/vendor/react/socket/tests/SecureServerTest.php @@ -0,0 +1,105 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\SecureServer; +use React\Socket\TcpServer; + +class SecureServerTest extends TestCase +{ + public function setUp() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + } + + public function testGetAddressWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('getAddress')->willReturn('tcp://127.0.0.1:1234'); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $server = new SecureServer($tcp, $loop, array()); + + $this->assertEquals('tls://127.0.0.1:1234', $server->getAddress()); + } + + public function testGetAddressWillReturnNullIfTcpServerReturnsNull() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('getAddress')->willReturn(null); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $server = new SecureServer($tcp, $loop, array()); + + $this->assertNull($server->getAddress()); + } + + public function testPauseWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('pause'); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $server = new SecureServer($tcp, $loop, array()); + + $server->pause(); + } + + public function testResumeWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('resume'); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $server = new SecureServer($tcp, $loop, array()); + + $server->resume(); + } + + public function testCloseWillBePassedThroughToTcpServer() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + $tcp->expects($this->once())->method('close'); + + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $server = new SecureServer($tcp, $loop, array()); + + $server->close(); + } + + public function testConnectionWillBeEndedWithErrorIfItIsNotAStream() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $tcp = new TcpServer(0, $loop); + + $connection = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock(); + $connection->expects($this->once())->method('end'); + + $server = new SecureServer($tcp, $loop, array()); + + $server->on('error', $this->expectCallableOnce()); + + $tcp->emit('connection', array($connection)); + } + + public function testSocketErrorWillBeForwarded() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $tcp = new TcpServer(0, $loop); + + $server = new SecureServer($tcp, $loop, array()); + + $server->on('error', $this->expectCallableOnce()); + + $tcp->emit('error', array(new \RuntimeException('test'))); + } +} diff --git a/assets/php/vendor/react/socket/tests/ServerTest.php b/assets/php/vendor/react/socket/tests/ServerTest.php new file mode 100644 index 0000000..14fdb2c --- /dev/null +++ b/assets/php/vendor/react/socket/tests/ServerTest.php @@ -0,0 +1,173 @@ +<?php + +namespace React\Tests\Socket; + +use React\EventLoop\Factory; +use React\Socket\Server; +use React\Socket\TcpConnector; +use React\Socket\UnixConnector; +use Clue\React\Block; +use React\Socket\ConnectionInterface; + +class ServerTest extends TestCase +{ + const TIMEOUT = 0.1; + + public function testCreateServerWithZeroPortAssignsRandomPort() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + $this->assertNotEquals(0, $server->getAddress()); + $server->close(); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorThrowsForInvalidUri() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $server = new Server('invalid URI', $loop); + } + + public function testConstructorCreatesExpectedTcpServer() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + + $connector = new TcpConnector($loop); + $connector->connect($server->getAddress()) + ->then($this->expectCallableOnce(), $this->expectCallableNever()); + + $connection = Block\await($connector->connect($server->getAddress()), $loop, self::TIMEOUT); + + $connection->close(); + $server->close(); + } + + public function testConstructorCreatesExpectedUnixServer() + { + $loop = Factory::create(); + + $server = new Server($this->getRandomSocketUri(), $loop); + + $connector = new UnixConnector($loop); + $connector->connect($server->getAddress()) + ->then($this->expectCallableOnce(), $this->expectCallableNever()); + + $connection = Block\await($connector->connect($server->getAddress()), $loop, self::TIMEOUT); + + $connection->close(); + $server->close(); + } + + public function testEmitsConnectionForNewConnection() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + $server->on('connection', $this->expectCallableOnce()); + + $client = stream_socket_client($server->getAddress()); + + Block\sleep(0.1, $loop); + } + + public function testDoesNotEmitConnectionForNewConnectionToPausedServer() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + $server->pause(); + $server->on('connection', $this->expectCallableNever()); + + $client = stream_socket_client($server->getAddress()); + + Block\sleep(0.1, $loop); + } + + public function testDoesEmitConnectionForNewConnectionToResumedServer() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + $server->pause(); + $server->on('connection', $this->expectCallableOnce()); + + $client = stream_socket_client($server->getAddress()); + + Block\sleep(0.1, $loop); + + $server->resume(); + Block\sleep(0.1, $loop); + } + + public function testDoesNotAllowConnectionToClosedServer() + { + $loop = Factory::create(); + + $server = new Server(0, $loop); + $server->on('connection', $this->expectCallableNever()); + $address = $server->getAddress(); + $server->close(); + + $client = @stream_socket_client($address); + + Block\sleep(0.1, $loop); + + $this->assertFalse($client); + } + + public function testEmitsConnectionWithInheritedContextOptions() + { + if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.13', '<')) { + // https://3v4l.org/hB4Tc + $this->markTestSkipped('Not supported on legacy HHVM < 3.13'); + } + + $loop = Factory::create(); + + $server = new Server(0, $loop, array( + 'backlog' => 4 + )); + + $all = null; + $server->on('connection', function (ConnectionInterface $conn) use (&$all) { + $all = stream_context_get_options($conn->stream); + }); + + $client = stream_socket_client($server->getAddress()); + + Block\sleep(0.1, $loop); + + $this->assertEquals(array('socket' => array('backlog' => 4)), $all); + } + + public function testDoesNotEmitSecureConnectionForNewPlainConnection() + { + if (!function_exists('stream_socket_enable_crypto')) { + $this->markTestSkipped('Not supported on your platform (outdated HHVM?)'); + } + + $loop = Factory::create(); + + $server = new Server('tls://127.0.0.1:0', $loop, array( + 'tls' => array( + 'local_cert' => __DIR__ . '/../examples/localhost.pem' + ) + )); + $server->on('connection', $this->expectCallableNever()); + + $client = stream_socket_client(str_replace('tls://', '', $server->getAddress())); + + Block\sleep(0.1, $loop); + } + + private function getRandomSocketUri() + { + return "unix://" . sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid(rand(), true) . '.sock'; + } +} diff --git a/assets/php/vendor/react/socket/tests/Stub/CallableStub.php b/assets/php/vendor/react/socket/tests/Stub/CallableStub.php new file mode 100644 index 0000000..1b197eb --- /dev/null +++ b/assets/php/vendor/react/socket/tests/Stub/CallableStub.php @@ -0,0 +1,10 @@ +<?php + +namespace React\Tests\Socket\Stub; + +class CallableStub +{ + public function __invoke() + { + } +} diff --git a/assets/php/vendor/react/socket/tests/Stub/ConnectionStub.php b/assets/php/vendor/react/socket/tests/Stub/ConnectionStub.php new file mode 100644 index 0000000..844b2ad --- /dev/null +++ b/assets/php/vendor/react/socket/tests/Stub/ConnectionStub.php @@ -0,0 +1,63 @@ +<?php + +namespace React\Tests\Socket\Stub; + +use Evenement\EventEmitter; +use React\Socket\ConnectionInterface; +use React\Stream\WritableStreamInterface; +use React\Stream\Util; + +class ConnectionStub extends EventEmitter implements ConnectionInterface +{ + private $data = ''; + + public function isReadable() + { + return true; + } + + public function isWritable() + { + return true; + } + + public function pause() + { + } + + public function resume() + { + } + + public function pipe(WritableStreamInterface $dest, array $options = array()) + { + Util::pipe($this, $dest, $options); + + return $dest; + } + + public function write($data) + { + $this->data .= $data; + + return true; + } + + public function end($data = null) + { + } + + public function close() + { + } + + public function getData() + { + return $this->data; + } + + public function getRemoteAddress() + { + return '127.0.0.1'; + } +} diff --git a/assets/php/vendor/react/socket/tests/Stub/ServerStub.php b/assets/php/vendor/react/socket/tests/Stub/ServerStub.php new file mode 100644 index 0000000..d9e74f4 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/Stub/ServerStub.php @@ -0,0 +1,18 @@ +<?php + +namespace React\Tests\Socket\Stub; + +use Evenement\EventEmitter; +use React\Socket\ServerInterface; + +class ServerStub extends EventEmitter implements ServerInterface +{ + public function getAddress() + { + return '127.0.0.1:80'; + } + + public function close() + { + } +} diff --git a/assets/php/vendor/react/socket/tests/TcpConnectorTest.php b/assets/php/vendor/react/socket/tests/TcpConnectorTest.php new file mode 100644 index 0000000..e3575a7 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/TcpConnectorTest.php @@ -0,0 +1,255 @@ +<?php + +namespace React\Tests\Socket; + +use Clue\React\Block; +use React\EventLoop\Factory; +use React\Socket\ConnectionInterface; +use React\Socket\TcpConnector; +use React\Socket\TcpServer; + +class TcpConnectorTest extends TestCase +{ + const TIMEOUT = 0.1; + + /** @test */ + public function connectionToEmptyPortShouldFail() + { + $loop = Factory::create(); + + $connector = new TcpConnector($loop); + $connector->connect('127.0.0.1:9999') + ->then($this->expectCallableNever(), $this->expectCallableOnce()); + + $loop->run(); + } + + /** @test */ + public function connectionToTcpServerShouldAddResourceToLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new TcpConnector($loop); + + $server = new TcpServer(0, $loop); + + $valid = false; + $loop->expects($this->once())->method('addWriteStream')->with($this->callback(function ($arg) use (&$valid) { + $valid = is_resource($arg); + return true; + })); + $connector->connect($server->getAddress()); + + $this->assertTrue($valid); + } + + /** @test */ + public function connectionToTcpServerShouldSucceed() + { + $loop = Factory::create(); + + $server = new TcpServer(9999, $loop); + $server->on('connection', $this->expectCallableOnce()); + $server->on('connection', array($server, 'close')); + + $connector = new TcpConnector($loop); + + $connection = Block\await($connector->connect('127.0.0.1:9999'), $loop, self::TIMEOUT); + + $this->assertInstanceOf('React\Socket\ConnectionInterface', $connection); + + $connection->close(); + } + + /** @test */ + public function connectionToTcpServerShouldSucceedWithRemoteAdressSameAsTarget() + { + $loop = Factory::create(); + + $server = new TcpServer(9999, $loop); + $server->on('connection', array($server, 'close')); + + $connector = new TcpConnector($loop); + + $connection = Block\await($connector->connect('127.0.0.1:9999'), $loop, self::TIMEOUT); + /* @var $connection ConnectionInterface */ + + $this->assertEquals('tcp://127.0.0.1:9999', $connection->getRemoteAddress()); + + $connection->close(); + } + + /** @test */ + public function connectionToTcpServerShouldSucceedWithLocalAdressOnLocalhost() + { + $loop = Factory::create(); + + $server = new TcpServer(9999, $loop); + $server->on('connection', array($server, 'close')); + + $connector = new TcpConnector($loop); + + $connection = Block\await($connector->connect('127.0.0.1:9999'), $loop, self::TIMEOUT); + /* @var $connection ConnectionInterface */ + + $this->assertContains('tcp://127.0.0.1:', $connection->getLocalAddress()); + $this->assertNotEquals('tcp://127.0.0.1:9999', $connection->getLocalAddress()); + + $connection->close(); + } + + /** @test */ + public function connectionToTcpServerShouldSucceedWithNullAddressesAfterConnectionClosed() + { + $loop = Factory::create(); + + $server = new TcpServer(9999, $loop); + $server->on('connection', array($server, 'close')); + + $connector = new TcpConnector($loop); + + $connection = Block\await($connector->connect('127.0.0.1:9999'), $loop, self::TIMEOUT); + /* @var $connection ConnectionInterface */ + + $connection->close(); + + $this->assertNull($connection->getRemoteAddress()); + $this->assertNull($connection->getLocalAddress()); + } + + /** @test */ + public function connectionToTcpServerWillCloseWhenOtherSideCloses() + { + $loop = Factory::create(); + + // immediately close connection and server once connection is in + $server = new TcpServer(0, $loop); + $server->on('connection', function (ConnectionInterface $conn) use ($server) { + $conn->close(); + $server->close(); + }); + + $once = $this->expectCallableOnce(); + $connector = new TcpConnector($loop); + $connector->connect($server->getAddress())->then(function (ConnectionInterface $conn) use ($once) { + $conn->write('hello'); + $conn->on('close', $once); + }); + + $loop->run(); + } + + /** @test */ + public function connectionToEmptyIp6PortShouldFail() + { + $loop = Factory::create(); + + $connector = new TcpConnector($loop); + $connector + ->connect('[::1]:9999') + ->then($this->expectCallableNever(), $this->expectCallableOnce()); + + $loop->run(); + } + + /** @test */ + public function connectionToIp6TcpServerShouldSucceed() + { + $loop = Factory::create(); + + try { + $server = new TcpServer('[::1]:9999', $loop); + } catch (\Exception $e) { + $this->markTestSkipped('Unable to start IPv6 server socket (IPv6 not supported on this system?)'); + } + + $server->on('connection', $this->expectCallableOnce()); + $server->on('connection', array($server, 'close')); + + $connector = new TcpConnector($loop); + + $connection = Block\await($connector->connect('[::1]:9999'), $loop, self::TIMEOUT); + /* @var $connection ConnectionInterface */ + + $this->assertEquals('tcp://[::1]:9999', $connection->getRemoteAddress()); + + $this->assertContains('tcp://[::1]:', $connection->getLocalAddress()); + $this->assertNotEquals('tcp://[::1]:9999', $connection->getLocalAddress()); + + $connection->close(); + } + + /** @test */ + public function connectionToHostnameShouldFailImmediately() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $connector = new TcpConnector($loop); + $connector->connect('www.google.com:80')->then( + $this->expectCallableNever(), + $this->expectCallableOnce() + ); + } + + /** @test */ + public function connectionToInvalidPortShouldFailImmediately() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $connector = new TcpConnector($loop); + $connector->connect('255.255.255.255:12345678')->then( + $this->expectCallableNever(), + $this->expectCallableOnce() + ); + } + + /** @test */ + public function connectionToInvalidSchemeShouldFailImmediately() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + + $connector = new TcpConnector($loop); + $connector->connect('tls://google.com:443')->then( + $this->expectCallableNever(), + $this->expectCallableOnce() + ); + } + + /** @test */ + public function cancellingConnectionShouldRemoveResourceFromLoopAndCloseResource() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $connector = new TcpConnector($loop); + + $server = new TcpServer(0, $loop); + + $loop->expects($this->once())->method('addWriteStream'); + $promise = $connector->connect($server->getAddress()); + + $resource = null; + $valid = false; + $loop->expects($this->once())->method('removeWriteStream')->with($this->callback(function ($arg) use (&$resource, &$valid) { + $resource = $arg; + $valid = is_resource($arg); + return true; + })); + $promise->cancel(); + + $this->assertTrue($valid); + $this->assertFalse(is_resource($resource)); + } + + /** @test */ + public function cancellingConnectionShouldRejectPromise() + { + $loop = Factory::create(); + $connector = new TcpConnector($loop); + + $server = new TcpServer(0, $loop); + + $promise = $connector->connect($server->getAddress()); + $promise->cancel(); + + $this->setExpectedException('RuntimeException', 'Cancelled'); + Block\await($promise, $loop); + } +} diff --git a/assets/php/vendor/react/socket/tests/TcpServerTest.php b/assets/php/vendor/react/socket/tests/TcpServerTest.php new file mode 100644 index 0000000..72b3c28 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/TcpServerTest.php @@ -0,0 +1,285 @@ +<?php + +namespace React\Tests\Socket; + +use Clue\React\Block; +use React\EventLoop\Factory; +use React\Socket\TcpServer; +use React\Stream\DuplexResourceStream; + +class TcpServerTest extends TestCase +{ + private $loop; + private $server; + private $port; + + private function createLoop() + { + return Factory::create(); + } + + /** + * @covers React\Socket\TcpServer::__construct + * @covers React\Socket\TcpServer::getAddress + */ + public function setUp() + { + $this->loop = $this->createLoop(); + $this->server = new TcpServer(0, $this->loop); + + $this->port = parse_url($this->server->getAddress(), PHP_URL_PORT); + } + + /** + * @covers React\Socket\TcpServer::handleConnection + */ + public function testConnection() + { + $client = stream_socket_client('tcp://localhost:'.$this->port); + + $this->server->on('connection', $this->expectCallableOnce()); + + $this->tick(); + } + + /** + * @covers React\Socket\TcpServer::handleConnection + */ + public function testConnectionWithManyClients() + { + $client1 = stream_socket_client('tcp://localhost:'.$this->port); + $client2 = stream_socket_client('tcp://localhost:'.$this->port); + $client3 = stream_socket_client('tcp://localhost:'.$this->port); + + $this->server->on('connection', $this->expectCallableExactly(3)); + $this->tick(); + $this->tick(); + $this->tick(); + } + + public function testDataEventWillNotBeEmittedWhenClientSendsNoData() + { + $client = stream_socket_client('tcp://localhost:'.$this->port); + + $mock = $this->expectCallableNever(); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('data', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testDataWillBeEmittedWithDataClientSends() + { + $client = stream_socket_client('tcp://localhost:'.$this->port); + + fwrite($client, "foo\n"); + + $mock = $this->expectCallableOnceWith("foo\n"); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('data', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testDataWillBeEmittedEvenWhenClientShutsDownAfterSending() + { + $client = stream_socket_client('tcp://localhost:' . $this->port); + fwrite($client, "foo\n"); + stream_socket_shutdown($client, STREAM_SHUT_WR); + + $mock = $this->expectCallableOnceWith("foo\n"); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('data', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testLoopWillEndWhenServerIsClosed() + { + // explicitly unset server because we already call close() + $this->server->close(); + $this->server = null; + + $this->loop->run(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testCloseTwiceIsNoOp() + { + $this->server->close(); + $this->server->close(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testGetAddressAfterCloseReturnsNull() + { + $this->server->close(); + $this->assertNull($this->server->getAddress()); + } + + public function testLoopWillEndWhenServerIsClosedAfterSingleConnection() + { + $client = stream_socket_client('tcp://localhost:' . $this->port); + + // explicitly unset server because we only accept a single connection + // and then already call close() + $server = $this->server; + $this->server = null; + + $server->on('connection', function ($conn) use ($server) { + $conn->close(); + $server->close(); + }); + + $this->loop->run(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testDataWillBeEmittedInMultipleChunksWhenClientSendsExcessiveAmounts() + { + $client = stream_socket_client('tcp://localhost:' . $this->port); + $stream = new DuplexResourceStream($client, $this->loop); + + $bytes = 1024 * 1024; + $stream->end(str_repeat('*', $bytes)); + + $mock = $this->expectCallableOnce(); + + // explicitly unset server because we only accept a single connection + // and then already call close() + $server = $this->server; + $this->server = null; + + $received = 0; + $server->on('connection', function ($conn) use ($mock, &$received, $server) { + // count number of bytes received + $conn->on('data', function ($data) use (&$received) { + $received += strlen($data); + }); + + $conn->on('end', $mock); + + // do not await any further connections in order to let the loop terminate + $server->close(); + }); + + $this->loop->run(); + + $this->assertEquals($bytes, $received); + } + + public function testConnectionDoesNotEndWhenClientDoesNotClose() + { + $client = stream_socket_client('tcp://localhost:'.$this->port); + + $mock = $this->expectCallableNever(); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('end', $mock); + }); + $this->tick(); + $this->tick(); + } + + /** + * @covers React\Socket\Connection::end + */ + public function testConnectionDoesEndWhenClientCloses() + { + $client = stream_socket_client('tcp://localhost:'.$this->port); + + fclose($client); + + $mock = $this->expectCallableOnce(); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('end', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testCtorAddsResourceToLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addReadStream'); + + $server = new TcpServer(0, $loop); + } + + public function testResumeWithoutPauseIsNoOp() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addReadStream'); + + $server = new TcpServer(0, $loop); + $server->resume(); + } + + public function testPauseRemovesResourceFromLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream'); + + $server = new TcpServer(0, $loop); + $server->pause(); + } + + public function testPauseAfterPauseIsNoOp() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream'); + + $server = new TcpServer(0, $loop); + $server->pause(); + $server->pause(); + } + + public function testCloseRemovesResourceFromLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream'); + + $server = new TcpServer(0, $loop); + $server->close(); + } + + /** + * @expectedException RuntimeException + */ + public function testListenOnBusyPortThrows() + { + if (DIRECTORY_SEPARATOR === '\\') { + $this->markTestSkipped('Windows supports listening on same port multiple times'); + } + + $another = new TcpServer($this->port, $this->loop); + } + + /** + * @covers React\Socket\TcpServer::close + */ + public function tearDown() + { + if ($this->server) { + $this->server->close(); + } + } + + private function tick() + { + Block\sleep(0, $this->loop); + } +} diff --git a/assets/php/vendor/react/socket/tests/TestCase.php b/assets/php/vendor/react/socket/tests/TestCase.php new file mode 100644 index 0000000..e87fc2f --- /dev/null +++ b/assets/php/vendor/react/socket/tests/TestCase.php @@ -0,0 +1,101 @@ +<?php + +namespace React\Tests\Socket; + +use React\Stream\ReadableStreamInterface; +use React\EventLoop\LoopInterface; +use Clue\React\Block; +use React\Promise\Promise; +use PHPUnit\Framework\TestCase as BaseTestCase; + +class TestCase extends BaseTestCase +{ + protected function expectCallableExactly($amount) + { + $mock = $this->createCallableMock(); + $mock + ->expects($this->exactly($amount)) + ->method('__invoke'); + + return $mock; + } + + 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\Socket\Stub\CallableStub')->getMock(); + } + + protected function buffer(ReadableStreamInterface $stream, LoopInterface $loop, $timeout) + { + if (!$stream->isReadable()) { + return ''; + } + + return Block\await(new Promise( + function ($resolve, $reject) use ($stream) { + $buffer = ''; + $stream->on('data', function ($chunk) use (&$buffer) { + $buffer .= $chunk; + }); + + $stream->on('error', $reject); + + $stream->on('close', function () use (&$buffer, $resolve) { + $resolve($buffer); + }); + }, + function () use ($stream) { + $stream->close(); + throw new \RuntimeException(); + } + ), $loop, $timeout); + } + + 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); + } + } +} diff --git a/assets/php/vendor/react/socket/tests/TimeoutConnectorTest.php b/assets/php/vendor/react/socket/tests/TimeoutConnectorTest.php new file mode 100644 index 0000000..64787d9 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/TimeoutConnectorTest.php @@ -0,0 +1,103 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\TimeoutConnector; +use React\Promise; +use React\EventLoop\Factory; + +class TimeoutConnectorTest extends TestCase +{ + public function testRejectsOnTimeout() + { + $promise = new Promise\Promise(function () { }); + + $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $connector->expects($this->once())->method('connect')->with('google.com:80')->will($this->returnValue($promise)); + + $loop = Factory::create(); + + $timeout = new TimeoutConnector($connector, 0.01, $loop); + + $timeout->connect('google.com:80')->then( + $this->expectCallableNever(), + $this->expectCallableOnce() + ); + + $loop->run(); + } + + public function testRejectsWhenConnectorRejects() + { + $promise = Promise\reject(new \RuntimeException()); + + $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $connector->expects($this->once())->method('connect')->with('google.com:80')->will($this->returnValue($promise)); + + $loop = Factory::create(); + + $timeout = new TimeoutConnector($connector, 5.0, $loop); + + $timeout->connect('google.com:80')->then( + $this->expectCallableNever(), + $this->expectCallableOnce() + ); + + $loop->run(); + } + + public function testResolvesWhenConnectorResolves() + { + $promise = Promise\resolve(); + + $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $connector->expects($this->once())->method('connect')->with('google.com:80')->will($this->returnValue($promise)); + + $loop = Factory::create(); + + $timeout = new TimeoutConnector($connector, 5.0, $loop); + + $timeout->connect('google.com:80')->then( + $this->expectCallableOnce(), + $this->expectCallableNever() + ); + + $loop->run(); + } + + public function testRejectsAndCancelsPendingPromiseOnTimeout() + { + $promise = new Promise\Promise(function () { }, $this->expectCallableOnce()); + + $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $connector->expects($this->once())->method('connect')->with('google.com:80')->will($this->returnValue($promise)); + + $loop = Factory::create(); + + $timeout = new TimeoutConnector($connector, 0.01, $loop); + + $timeout->connect('google.com:80')->then( + $this->expectCallableNever(), + $this->expectCallableOnce() + ); + + $loop->run(); + } + + public function testCancelsPendingPromiseOnCancel() + { + $promise = new Promise\Promise(function () { }, function () { throw new \Exception(); }); + + $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + $connector->expects($this->once())->method('connect')->with('google.com:80')->will($this->returnValue($promise)); + + $loop = Factory::create(); + + $timeout = new TimeoutConnector($connector, 0.01, $loop); + + $out = $timeout->connect('google.com:80'); + $out->cancel(); + + $out->then($this->expectCallableNever(), $this->expectCallableOnce()); + } +} diff --git a/assets/php/vendor/react/socket/tests/UnixConnectorTest.php b/assets/php/vendor/react/socket/tests/UnixConnectorTest.php new file mode 100644 index 0000000..1564064 --- /dev/null +++ b/assets/php/vendor/react/socket/tests/UnixConnectorTest.php @@ -0,0 +1,64 @@ +<?php + +namespace React\Tests\Socket; + +use React\Socket\ConnectionInterface; +use React\Socket\UnixConnector; + +class UnixConnectorTest extends TestCase +{ + private $loop; + private $connector; + + public function setUp() + { + $this->loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $this->connector = new UnixConnector($this->loop); + } + + public function testInvalid() + { + $promise = $this->connector->connect('google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testInvalidScheme() + { + $promise = $this->connector->connect('tcp://google.com:80'); + $promise->then(null, $this->expectCallableOnce()); + } + + public function testValid() + { + // random unix domain socket path + $path = sys_get_temp_dir() . '/test' . uniqid() . '.sock'; + + // temporarily create unix domain socket server to connect to + $server = stream_socket_server('unix://' . $path, $errno, $errstr); + + // skip test if we can not create a test server (Windows etc.) + if (!$server) { + $this->markTestSkipped('Unable to create socket "' . $path . '": ' . $errstr . '(' . $errno .')'); + return; + } + + // tests succeeds if we get notified of successful connection + $promise = $this->connector->connect($path); + $promise->then($this->expectCallableOnce()); + + // remember remote and local address of this connection and close again + $remote = $local = false; + $promise->then(function(ConnectionInterface $conn) use (&$remote, &$local) { + $remote = $conn->getRemoteAddress(); + $local = $conn->getLocalAddress(); + $conn->close(); + }); + + // clean up server + fclose($server); + unlink($path); + + $this->assertNull($local); + $this->assertEquals('unix://' . $path, $remote); + } +} diff --git a/assets/php/vendor/react/socket/tests/UnixServerTest.php b/assets/php/vendor/react/socket/tests/UnixServerTest.php new file mode 100644 index 0000000..10f7e4f --- /dev/null +++ b/assets/php/vendor/react/socket/tests/UnixServerTest.php @@ -0,0 +1,283 @@ +<?php + +namespace React\Tests\Socket; + +use Clue\React\Block; +use React\EventLoop\Factory; +use React\Socket\UnixServer; +use React\Stream\DuplexResourceStream; + +class UnixServerTest extends TestCase +{ + private $loop; + private $server; + private $uds; + + /** + * @covers React\Socket\UnixServer::__construct + * @covers React\Socket\UnixServer::getAddress + */ + public function setUp() + { + $this->loop = Factory::create(); + $this->uds = $this->getRandomSocketUri(); + $this->server = new UnixServer($this->uds, $this->loop); + } + + /** + * @covers React\Socket\UnixServer::handleConnection + */ + public function testConnection() + { + $client = stream_socket_client($this->uds); + + $this->server->on('connection', $this->expectCallableOnce()); + $this->tick(); + } + + /** + * @covers React\Socket\UnixServer::handleConnection + */ + public function testConnectionWithManyClients() + { + $client1 = stream_socket_client($this->uds); + $client2 = stream_socket_client($this->uds); + $client3 = stream_socket_client($this->uds); + + $this->server->on('connection', $this->expectCallableExactly(3)); + $this->tick(); + $this->tick(); + $this->tick(); + } + + public function testDataEventWillNotBeEmittedWhenClientSendsNoData() + { + $client = stream_socket_client($this->uds); + + $mock = $this->expectCallableNever(); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('data', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testDataWillBeEmittedWithDataClientSends() + { + $client = stream_socket_client($this->uds); + + fwrite($client, "foo\n"); + + $mock = $this->expectCallableOnceWith("foo\n"); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('data', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testDataWillBeEmittedEvenWhenClientShutsDownAfterSending() + { + $client = stream_socket_client($this->uds); + fwrite($client, "foo\n"); + stream_socket_shutdown($client, STREAM_SHUT_WR); + + $mock = $this->expectCallableOnceWith("foo\n"); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('data', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testLoopWillEndWhenServerIsClosed() + { + // explicitly unset server because we already call close() + $this->server->close(); + $this->server = null; + + $this->loop->run(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testCloseTwiceIsNoOp() + { + $this->server->close(); + $this->server->close(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testGetAddressAfterCloseReturnsNull() + { + $this->server->close(); + $this->assertNull($this->server->getAddress()); + } + + public function testLoopWillEndWhenServerIsClosedAfterSingleConnection() + { + $client = stream_socket_client($this->uds); + + // explicitly unset server because we only accept a single connection + // and then already call close() + $server = $this->server; + $this->server = null; + + $server->on('connection', function ($conn) use ($server) { + $conn->close(); + $server->close(); + }); + + $this->loop->run(); + + // if we reach this, then everything is good + $this->assertNull(null); + } + + public function testDataWillBeEmittedInMultipleChunksWhenClientSendsExcessiveAmounts() + { + $client = stream_socket_client($this->uds); + $stream = new DuplexResourceStream($client, $this->loop); + + $bytes = 1024 * 1024; + $stream->end(str_repeat('*', $bytes)); + + $mock = $this->expectCallableOnce(); + + // explicitly unset server because we only accept a single connection + // and then already call close() + $server = $this->server; + $this->server = null; + + $received = 0; + $server->on('connection', function ($conn) use ($mock, &$received, $server) { + // count number of bytes received + $conn->on('data', function ($data) use (&$received) { + $received += strlen($data); + }); + + $conn->on('end', $mock); + + // do not await any further connections in order to let the loop terminate + $server->close(); + }); + + $this->loop->run(); + + $this->assertEquals($bytes, $received); + } + + public function testConnectionDoesNotEndWhenClientDoesNotClose() + { + $client = stream_socket_client($this->uds); + + $mock = $this->expectCallableNever(); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('end', $mock); + }); + $this->tick(); + $this->tick(); + } + + /** + * @covers React\Socket\Connection::end + */ + public function testConnectionDoesEndWhenClientCloses() + { + $client = stream_socket_client($this->uds); + + fclose($client); + + $mock = $this->expectCallableOnce(); + + $this->server->on('connection', function ($conn) use ($mock) { + $conn->on('end', $mock); + }); + $this->tick(); + $this->tick(); + } + + public function testCtorAddsResourceToLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addReadStream'); + + $server = new UnixServer($this->getRandomSocketUri(), $loop); + } + + public function testResumeWithoutPauseIsNoOp() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('addReadStream'); + + $server = new UnixServer($this->getRandomSocketUri(), $loop); + $server->resume(); + } + + public function testPauseRemovesResourceFromLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream'); + + $server = new UnixServer($this->getRandomSocketUri(), $loop); + $server->pause(); + } + + public function testPauseAfterPauseIsNoOp() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream'); + + $server = new UnixServer($this->getRandomSocketUri(), $loop); + $server->pause(); + $server->pause(); + } + + public function testCloseRemovesResourceFromLoop() + { + $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); + $loop->expects($this->once())->method('removeReadStream'); + + $server = new UnixServer($this->getRandomSocketUri(), $loop); + $server->close(); + } + + /** + * @expectedException RuntimeException + */ + public function testListenOnBusyPortThrows() + { + if (DIRECTORY_SEPARATOR === '\\') { + $this->markTestSkipped('Windows supports listening on same port multiple times'); + } + + $another = new UnixServer($this->uds, $this->loop); + } + + /** + * @covers React\Socket\UnixServer::close + */ + public function tearDown() + { + if ($this->server) { + $this->server->close(); + } + } + + private function getRandomSocketUri() + { + return "unix://" . sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid(rand(), true) . '.sock'; + } + + private function tick() + { + Block\sleep(0, $this->loop); + } +} |