This commit is contained in:
2022-10-23 01:39:27 +02:00
parent 8c17aab483
commit 1929b84685
4130 changed files with 479334 additions and 0 deletions

47
vendor/react/socket/tests/ConnectionTest.php vendored Executable file
View File

@@ -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));
}
}

128
vendor/react/socket/tests/ConnectorTest.php vendored Executable file
View File

@@ -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');
}
}

111
vendor/react/socket/tests/DnsConnectorTest.php vendored Executable file
View File

@@ -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());
}
}

View File

@@ -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'));
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

328
vendor/react/socket/tests/IntegrationTest.php vendored Executable file
View File

@@ -0,0 +1,328 @@
<?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 testCancellingPendingConnectionWithoutTimeoutShouldNotCreateAnyGarbageReferences()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
$loop = Factory::create();
$connector = new Connector($loop, array('timeout' => false));
gc_collect_cycles();
$promise = $connector->connect('8.8.8.8:80');
$promise->cancel();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testCancellingPendingConnectionShouldNotCreateAnyGarbageReferences()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
$loop = Factory::create();
$connector = new Connector($loop);
gc_collect_cycles();
$promise = $connector->connect('8.8.8.8:80');
$promise->cancel();
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForRejectedConnectionShouldNotCreateAnyGarbageReferences()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
$loop = Factory::create();
$connector = new Connector($loop, array('timeout' => false));
gc_collect_cycles();
$wait = true;
$promise = $connector->connect('127.0.0.1:1')->then(
null,
function ($e) use (&$wait) {
$wait = false;
throw $e;
}
);
// run loop for short period to ensure we detect connection refused error
Block\sleep(0.01, $loop);
if ($wait) {
Block\sleep(0.2, $loop);
if ($wait) {
$this->fail('Connection attempt did not fail');
}
}
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
/**
* @requires PHP 7
*/
public function testWaitingForConnectionTimeoutShouldNotCreateAnyGarbageReferences()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
$loop = Factory::create();
$connector = new Connector($loop, array('timeout' => 0.001));
gc_collect_cycles();
$wait = true;
$promise = $connector->connect('google.com:80')->then(
null,
function ($e) use (&$wait) {
$wait = false;
throw $e;
}
);
// run loop for short period to ensure we detect connection timeout error
Block\sleep(0.01, $loop);
if ($wait) {
Block\sleep(0.2, $loop);
if ($wait) {
$this->fail('Connection attempt did not fail');
}
}
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForInvalidDnsConnectionShouldNotCreateAnyGarbageReferences()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
$loop = Factory::create();
$connector = new Connector($loop, array('timeout' => false));
gc_collect_cycles();
$wait = true;
$promise = $connector->connect('example.invalid:80')->then(
null,
function ($e) use (&$wait) {
$wait = false;
throw $e;
}
);
// run loop for short period to ensure we detect DNS error
Block\sleep(0.01, $loop);
if ($wait) {
Block\sleep(0.2, $loop);
if ($wait) {
$this->fail('Connection attempt did not fail');
}
}
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
public function testWaitingForSuccessfullyClosedConnectionShouldNotCreateAnyGarbageReferences()
{
if (class_exists('React\Promise\When')) {
$this->markTestSkipped('Not supported on legacy Promise v1 API');
}
$loop = Factory::create();
$connector = new Connector($loop, array('timeout' => false));
gc_collect_cycles();
$promise = $connector->connect('google.com:80')->then(
function ($conn) {
$conn->close();
}
);
Block\await($promise, $loop, self::TIMEOUT);
unset($promise);
$this->assertEquals(0, gc_collect_cycles());
}
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);
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}

View File

@@ -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()));
});
});
}
}

105
vendor/react/socket/tests/SecureServerTest.php vendored Executable file
View File

@@ -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')));
}
}

173
vendor/react/socket/tests/ServerTest.php vendored Executable file
View File

@@ -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';
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace React\Tests\Socket\Stub;
class CallableStub
{
public function __invoke()
{
}
}

View File

@@ -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';
}
}

18
vendor/react/socket/tests/Stub/ServerStub.php vendored Executable file
View File

@@ -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()
{
}
}

260
vendor/react/socket/tests/TcpConnectorTest.php vendored Executable file
View File

@@ -0,0 +1,260 @@
<?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);
$server->on('connection', $this->expectCallableNever());
$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();
// ensure that this was a valid resource during the removeWriteStream() call
$this->assertTrue($valid);
// ensure that this resource should now be closed after the cancel() call
$this->assertInternalType('resource', $resource);
$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);
}
}

285
vendor/react/socket/tests/TcpServerTest.php vendored Executable file
View File

@@ -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);
}
}

101
vendor/react/socket/tests/TestCase.php vendored Executable file
View File

@@ -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);
}
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

283
vendor/react/socket/tests/UnixServerTest.php vendored Executable file
View File

@@ -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);
}
}