init
This commit is contained in:
80
vendor/clue/http-proxy-react/tests/AbstractTestCase.php
vendored
Executable file
80
vendor/clue/http-proxy-react/tests/AbstractTestCase.php
vendored
Executable file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Clue\React\HttpProxy;
|
||||
|
||||
use PHPUnit_Framework_TestCase;
|
||||
|
||||
abstract class AbstractTestCase extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected function expectCallableNever()
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->never())
|
||||
->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($this->equalTo($value));
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
protected function expectCallableOnceWithExceptionCode($code)
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->callback(function ($e) use ($code) {
|
||||
return $e->getCode() === $code;
|
||||
}));
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
|
||||
protected function expectCallableOnceParameter($type)
|
||||
{
|
||||
$mock = $this->createCallableMock();
|
||||
$mock
|
||||
->expects($this->once())
|
||||
->method('__invoke')
|
||||
->with($this->isInstanceOf($type));
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @link https://github.com/reactphp/react/blob/master/tests/React/Tests/Socket/TestCase.php (taken from reactphp/react)
|
||||
*/
|
||||
protected function createCallableMock()
|
||||
{
|
||||
return $this->getMockBuilder('Tests\\Clue\\React\\HttpProxy\\CallableStub')->getMock();
|
||||
}
|
||||
}
|
||||
|
||||
class CallableStub
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
75
vendor/clue/http-proxy-react/tests/FunctionalTest.php
vendored
Executable file
75
vendor/clue/http-proxy-react/tests/FunctionalTest.php
vendored
Executable file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Clue\React\HttpProxy;
|
||||
|
||||
use React\EventLoop\Factory;
|
||||
use Clue\React\HttpProxy\ProxyConnector;
|
||||
use React\Socket\TcpConnector;
|
||||
use React\Socket\DnsConnector;
|
||||
use Clue\React\Block;
|
||||
use React\Socket\SecureConnector;
|
||||
|
||||
/** @group internet */
|
||||
class FunctionalTest extends AbstractTestCase
|
||||
{
|
||||
private $loop;
|
||||
private $tcpConnector;
|
||||
private $dnsConnector;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->loop = Factory::create();
|
||||
|
||||
$this->tcpConnector = new TcpConnector($this->loop);
|
||||
|
||||
$f = new \React\Dns\Resolver\Factory();
|
||||
$resolver = $f->create('8.8.8.8', $this->loop);
|
||||
|
||||
$this->dnsConnector = new DnsConnector($this->tcpConnector, $resolver);
|
||||
}
|
||||
|
||||
public function testNonListeningSocketRejectsConnection()
|
||||
{
|
||||
$proxy = new ProxyConnector('127.0.0.1:9999', $this->dnsConnector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$this->setExpectedException('RuntimeException', 'Unable to connect to proxy', SOCKET_ECONNREFUSED);
|
||||
Block\await($promise, $this->loop, 3.0);
|
||||
}
|
||||
|
||||
public function testPlainGoogleDoesNotAcceptConnectMethod()
|
||||
{
|
||||
$proxy = new ProxyConnector('google.com', $this->dnsConnector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$this->setExpectedException('RuntimeException', '405 (Method Not Allowed)', SOCKET_ECONNREFUSED);
|
||||
Block\await($promise, $this->loop, 3.0);
|
||||
}
|
||||
|
||||
public function testSecureGoogleDoesNotAcceptConnectMethod()
|
||||
{
|
||||
if (!function_exists('stream_socket_enable_crypto')) {
|
||||
$this->markTestSkipped('TLS not supported on really old platforms (HHVM < 3.8)');
|
||||
}
|
||||
|
||||
$secure = new SecureConnector($this->dnsConnector, $this->loop);
|
||||
$proxy = new ProxyConnector('https://google.com:443', $secure);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$this->setExpectedException('RuntimeException', '405 (Method Not Allowed)', SOCKET_ECONNREFUSED);
|
||||
Block\await($promise, $this->loop, 3.0);
|
||||
}
|
||||
|
||||
public function testSecureGoogleDoesNotAcceptPlainStream()
|
||||
{
|
||||
$proxy = new ProxyConnector('google.com:443', $this->dnsConnector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$this->setExpectedException('RuntimeException', 'Connection to proxy lost', SOCKET_ECONNRESET);
|
||||
Block\await($promise, $this->loop, 3.0);
|
||||
}
|
||||
}
|
||||
333
vendor/clue/http-proxy-react/tests/ProxyConnectorTest.php
vendored
Executable file
333
vendor/clue/http-proxy-react/tests/ProxyConnectorTest.php
vendored
Executable file
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Clue\React\HttpProxy;
|
||||
|
||||
use Clue\React\HttpProxy\ProxyConnector;
|
||||
use React\Promise\Promise;
|
||||
use React\Socket\ConnectionInterface;
|
||||
|
||||
class ProxyConnectorTest extends AbstractTestCase
|
||||
{
|
||||
private $connector;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidProxy()
|
||||
{
|
||||
new ProxyConnector('///', $this->connector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidProxyScheme()
|
||||
{
|
||||
new ProxyConnector('ftp://example.com', $this->connector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testInvalidHttpsUnixScheme()
|
||||
{
|
||||
new ProxyConnector('https+unix:///tmp/proxy.sock', $this->connector);
|
||||
}
|
||||
|
||||
public function testCreatesConnectionToHttpPort()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
$this->connector->expects($this->once())->method('connect')->with('tcp://proxy.example.com:80?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testCreatesConnectionToHttpPortAndPassesThroughUriComponents()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
$this->connector->expects($this->once())->method('connect')->with('tcp://proxy.example.com:80/path?foo=bar&hostname=google.com#segment')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80/path?foo=bar#segment');
|
||||
}
|
||||
|
||||
public function testCreatesConnectionToHttpPortAndObeysExplicitHostname()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
$this->connector->expects($this->once())->method('connect')->with('tcp://proxy.example.com:80?hostname=www.google.com')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80?hostname=www.google.com');
|
||||
}
|
||||
|
||||
public function testCreatesConnectionToHttpsPort()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
$this->connector->expects($this->once())->method('connect')->with('tls://proxy.example.com:443?hostname=google.com')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('https://proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testCreatesConnectionToUnixPath()
|
||||
{
|
||||
$promise = new Promise(function () { });
|
||||
$this->connector->expects($this->once())->method('connect')->with('unix:///tmp/proxy.sock')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('http+unix:///tmp/proxy.sock', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testCancelPromiseWillCancelPendingConnection()
|
||||
{
|
||||
$promise = new Promise(function () { }, $this->expectCallableOnce());
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$this->assertInstanceOf('React\Promise\CancellablePromiseInterface', $promise);
|
||||
|
||||
$promise->cancel();
|
||||
}
|
||||
|
||||
public function testWillWriteToOpenConnection()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
$stream->expects($this->once())->method('write')->with("CONNECT google.com:80 HTTP/1.1\r\nHost: google.com:80\r\n\r\n");
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testWillProxyAuthorizationHeaderIfProxyUriContainsAuthentication()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
$stream->expects($this->once())->method('write')->with("CONNECT google.com:80 HTTP/1.1\r\nHost: google.com:80\r\nProxy-Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('user:pass@proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testWillProxyAuthorizationHeaderIfProxyUriContainsOnlyUsernameWithoutPassword()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
$stream->expects($this->once())->method('write')->with("CONNECT google.com:80 HTTP/1.1\r\nHost: google.com:80\r\nProxy-Authorization: Basic dXNlcjo=\r\n\r\n");
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('user@proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testWillProxyAuthorizationHeaderIfProxyUriContainsAuthenticationWithPercentEncoding()
|
||||
{
|
||||
$user = 'h@llÖ';
|
||||
$pass = '%secret?';
|
||||
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
$stream->expects($this->once())->method('write')->with("CONNECT google.com:80 HTTP/1.1\r\nHost: google.com:80\r\nProxy-Authorization: Basic " . base64_encode($user . ':' . $pass) . "\r\n\r\n");
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector(rawurlencode($user) . ':' . rawurlencode($pass) . '@proxy.example.com', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testWillProxyAuthorizationHeaderIfUnixProxyUriContainsAuthentication()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
$stream->expects($this->once())->method('write')->with("CONNECT google.com:80 HTTP/1.1\r\nHost: google.com:80\r\nProxy-Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->with('unix:///tmp/proxy.sock')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('http+unix://user:pass@/tmp/proxy.sock', $this->connector);
|
||||
|
||||
$proxy->connect('google.com:80');
|
||||
}
|
||||
|
||||
public function testRejectsInvalidUri()
|
||||
{
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('///');
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testRejectsUriWithNonTcpScheme()
|
||||
{
|
||||
$this->connector->expects($this->never())->method('connect');
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('tls://google.com:80');
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testRejectsIfConnectorRejects()
|
||||
{
|
||||
$promise = \React\Promise\reject(new \RuntimeException());
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$promise->then(null, $this->expectCallableOnce());
|
||||
}
|
||||
|
||||
public function testRejectsAndClosesIfStreamWritesNonHttp()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$stream->expects($this->once())->method('close');
|
||||
$stream->emit('data', array("invalid\r\n\r\n"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EBADMSG));
|
||||
}
|
||||
|
||||
public function testRejectsAndClosesIfStreamWritesTooMuchData()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$stream->expects($this->once())->method('close');
|
||||
$stream->emit('data', array(str_repeat('*', 100000)));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EMSGSIZE));
|
||||
}
|
||||
|
||||
public function testRejectsAndClosesIfStreamReturnsProyAuthenticationRequired()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$stream->expects($this->once())->method('close');
|
||||
$stream->emit('data', array("HTTP/1.1 407 Proxy Authentication Required\r\n\r\n"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_EACCES));
|
||||
}
|
||||
|
||||
public function testRejectsAndClosesIfStreamReturnsNonSuccess()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$stream->expects($this->once())->method('close');
|
||||
$stream->emit('data', array("HTTP/1.1 403 Not allowed\r\n\r\n"));
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNREFUSED));
|
||||
}
|
||||
|
||||
public function testResolvesIfStreamReturnsSuccess()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$promise->then($this->expectCallableOnce('React\Stream\Stream'));
|
||||
$never = $this->expectCallableNever();
|
||||
$promise->then(function (ConnectionInterface $stream) use ($never) {
|
||||
$stream->on('data', $never);
|
||||
});
|
||||
|
||||
$stream->emit('data', array("HTTP/1.1 200 OK\r\n\r\n"));
|
||||
}
|
||||
|
||||
public function testResolvesIfStreamReturnsSuccessAndEmitsExcessiveData()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$once = $this->expectCallableOnceWith('hello!');
|
||||
$promise->then(function (ConnectionInterface $stream) use ($once) {
|
||||
$stream->on('data', $once);
|
||||
});
|
||||
|
||||
$stream->emit('data', array("HTTP/1.1 200 OK\r\n\r\nhello!"));
|
||||
}
|
||||
|
||||
public function testCancelPromiseWillCloseOpenConnectionAndReject()
|
||||
{
|
||||
$stream = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->setMethods(array('close', 'write'))->getMock();
|
||||
$stream->expects($this->once())->method('close');
|
||||
|
||||
$promise = \React\Promise\resolve($stream);
|
||||
$this->connector->expects($this->once())->method('connect')->willReturn($promise);
|
||||
|
||||
$proxy = new ProxyConnector('proxy.example.com', $this->connector);
|
||||
|
||||
$promise = $proxy->connect('google.com:80');
|
||||
|
||||
$this->assertInstanceOf('React\Promise\CancellablePromiseInterface', $promise);
|
||||
|
||||
$promise->cancel();
|
||||
|
||||
$promise->then(null, $this->expectCallableOnceWithExceptionCode(SOCKET_ECONNABORTED));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user