diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e7d91e..84bbe01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,9 +11,11 @@ jobs: strategy: matrix: os: - - ubuntu-22.04 + - ubuntu-24.04 - windows-2022 php: + - 8.5 + - 8.4 - 8.3 - 8.2 - 8.1 @@ -44,13 +46,13 @@ jobs: PHPUnit-macOS: name: PHPUnit (macOS) - runs-on: macos-12 + runs-on: macos-14 continue-on-error: true steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.5 coverage: xdebug - run: composer install - run: vendor/bin/phpunit --coverage-text diff --git a/CHANGELOG.md b/CHANGELOG.md index db178ca..c58f260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 1.17.0 (2025-11-19) + +* Feature: Improve PHP 8.5+ support by avoiding deprecated `setAccessible()` calls. + (#325 by @W0rma and #330 by @WyriHaximus) + +* Improve test suite and update test environment. + (#326 and #330 by @WyriHaximus) + +## 1.16.0 (2024-07-26) + +* Feature: Improve PHP 8.4+ support by avoiding implicitly nullable type declarations. + (#318 by @clue) + ## 1.15.0 (2023-12-15) * Feature: Full PHP 8.3 compatibility. diff --git a/README.md b/README.md index 18e3d91..092590a 100644 --- a/README.md +++ b/README.md @@ -1494,7 +1494,7 @@ This project follows [SemVer](https://semver.org/). This will install the latest supported version: ```bash -composer require react/socket:^1.15 +composer require react/socket:^1.17 ``` See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. diff --git a/composer.json b/composer.json index 02c184f..b1e1d25 100644 --- a/composer.json +++ b/composer.json @@ -28,16 +28,16 @@ "require": { "php": ">=5.3.0", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "react/dns": "^1.11", + "react/dns": "^1.13", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.6 || ^1.2.1", - "react/stream": "^1.2" + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" }, "require-dev": { "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2", + "react/async": "^4.3 || ^3.3 || ^2", "react/promise-stream": "^1.4", - "react/promise-timer": "^1.10" + "react/promise-timer": "^1.11" }, "autoload": { "psr-4": { diff --git a/src/DnsConnector.php b/src/DnsConnector.php index d2fb2c7..e5fd238 100644 --- a/src/DnsConnector.php +++ b/src/DnsConnector.php @@ -68,7 +68,9 @@ function ($resolve, $reject) use (&$promise, &$resolved, $uri, $connector, $host // avoid garbage references by replacing all closures in call stack. // what a lovely piece of code! $r = new \ReflectionProperty('Exception', 'trace'); - $r->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $r->setAccessible(true); + } $trace = $r->getValue($e); // Exception trace arguments are not available on some PHP 7.4 installs diff --git a/src/FdServer.php b/src/FdServer.php index b1ed777..8e46719 100644 --- a/src/FdServer.php +++ b/src/FdServer.php @@ -75,7 +75,7 @@ final class FdServer extends EventEmitter implements ServerInterface * @throws \InvalidArgumentException if the listening address is invalid * @throws \RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($fd, LoopInterface $loop = null) + public function __construct($fd, $loop = null) { if (\preg_match('#^php://fd/(\d+)$#', $fd, $m)) { $fd = (int) $m[1]; @@ -87,6 +87,10 @@ public function __construct($fd, LoopInterface $loop = null) ); } + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->loop = $loop ?: Loop::get(); $errno = 0; diff --git a/src/HappyEyeBallsConnector.php b/src/HappyEyeBallsConnector.php index 98b1d58..a5511ac 100644 --- a/src/HappyEyeBallsConnector.php +++ b/src/HappyEyeBallsConnector.php @@ -13,15 +13,26 @@ final class HappyEyeBallsConnector implements ConnectorInterface private $connector; private $resolver; - public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ResolverInterface $resolver = null) + /** + * @param ?LoopInterface $loop + * @param ConnectorInterface $connector + * @param ResolverInterface $resolver + */ + public function __construct($loop = null, $connector = null, $resolver = null) { // $connector and $resolver arguments are actually required, marked // optional for technical reasons only. Nullable $loop without default // requires PHP 7.1, null default is also supported in legacy PHP // versions, but required parameters are not allowed after arguments // with null default. Mark all parameters optional and check accordingly. - if ($connector === null || $resolver === null) { - throw new \InvalidArgumentException('Missing required $connector or $resolver argument'); + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + } + if (!$connector instanceof ConnectorInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($connector) expected React\Socket\ConnectorInterface'); + } + if (!$resolver instanceof ResolverInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #3 ($resolver) expected React\Dns\Resolver\ResolverInterface'); } $this->loop = $loop ?: Loop::get(); diff --git a/src/SecureConnector.php b/src/SecureConnector.php index 17c229d..98cc46a 100644 --- a/src/SecureConnector.php +++ b/src/SecureConnector.php @@ -15,8 +15,17 @@ final class SecureConnector implements ConnectorInterface private $streamEncryption; private $context; - public function __construct(ConnectorInterface $connector, LoopInterface $loop = null, array $context = array()) + /** + * @param ConnectorInterface $connector + * @param ?LoopInterface $loop + * @param array $context + */ + public function __construct(ConnectorInterface $connector, $loop = null, array $context = array()) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->connector = $connector; $this->streamEncryption = new StreamEncryption($loop ?: Loop::get(), false); $this->context = $context; @@ -82,7 +91,9 @@ public function connect($uri) // avoid garbage references by replacing all closures in call stack. // what a lovely piece of code! $r = new \ReflectionProperty('Exception', 'trace'); - $r->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $r->setAccessible(true); + } $trace = $r->getValue($e); // Exception trace arguments are not available on some PHP 7.4 installs diff --git a/src/SecureServer.php b/src/SecureServer.php index d0525c9..5a202d2 100644 --- a/src/SecureServer.php +++ b/src/SecureServer.php @@ -122,8 +122,12 @@ final class SecureServer extends EventEmitter implements ServerInterface * @see TcpServer * @link https://www.php.net/manual/en/context.ssl.php for TLS context options */ - public function __construct(ServerInterface $tcp, LoopInterface $loop = null, array $context = array()) + public function __construct(ServerInterface $tcp, $loop = null, array $context = array()) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + } + if (!\function_exists('stream_socket_enable_crypto')) { throw new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'); // @codeCoverageIgnore } diff --git a/src/Server.php b/src/Server.php index 7d4111e..b24c556 100644 --- a/src/Server.php +++ b/src/Server.php @@ -43,14 +43,18 @@ final class Server extends EventEmitter implements ServerInterface * For BC reasons, you can also pass the TCP socket context options as a simple * array without wrapping this in another array under the `tcp` key. * - * @param string|int $uri - * @param LoopInterface $loop - * @param array $context + * @param string|int $uri + * @param ?LoopInterface $loop + * @param array $context * @deprecated 1.9.0 See `SocketServer` instead * @see SocketServer */ - public function __construct($uri, LoopInterface $loop = null, array $context = array()) + public function __construct($uri, $loop = null, array $context = array()) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $loop = $loop ?: Loop::get(); // sanitize TCP context options if not properly wrapped diff --git a/src/SocketServer.php b/src/SocketServer.php index b78dc3a..e987f5f 100644 --- a/src/SocketServer.php +++ b/src/SocketServer.php @@ -31,8 +31,12 @@ final class SocketServer extends EventEmitter implements ServerInterface * @throws \InvalidArgumentException if the listening address is invalid * @throws \RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($uri, array $context = array(), LoopInterface $loop = null) + public function __construct($uri, array $context = array(), $loop = null) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); + } + // apply default options if not explicitly given $context += array( 'tcp' => array(), diff --git a/src/TcpConnector.php b/src/TcpConnector.php index 8cfc7bf..9d2599e 100644 --- a/src/TcpConnector.php +++ b/src/TcpConnector.php @@ -13,8 +13,16 @@ final class TcpConnector implements ConnectorInterface private $loop; private $context; - public function __construct(LoopInterface $loop = null, array $context = array()) + /** + * @param ?LoopInterface $loop + * @param array $context + */ + public function __construct($loop = null, array $context = array()) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->loop = $loop ?: Loop::get(); $this->context = $context; } diff --git a/src/TcpServer.php b/src/TcpServer.php index 235761d..01b2b46 100644 --- a/src/TcpServer.php +++ b/src/TcpServer.php @@ -128,8 +128,12 @@ final class TcpServer extends EventEmitter implements ServerInterface * @throws InvalidArgumentException if the listening address is invalid * @throws RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($uri, LoopInterface $loop = null, array $context = array()) + public function __construct($uri, $loop = null, array $context = array()) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->loop = $loop ?: Loop::get(); // a single port has been given => assume localhost diff --git a/src/TimeoutConnector.php b/src/TimeoutConnector.php index a20ea5a..9ef252f 100644 --- a/src/TimeoutConnector.php +++ b/src/TimeoutConnector.php @@ -12,8 +12,17 @@ final class TimeoutConnector implements ConnectorInterface private $timeout; private $loop; - public function __construct(ConnectorInterface $connector, $timeout, LoopInterface $loop = null) + /** + * @param ConnectorInterface $connector + * @param float $timeout + * @param ?LoopInterface $loop + */ + public function __construct(ConnectorInterface $connector, $timeout, $loop = null) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->connector = $connector; $this->timeout = $timeout; $this->loop = $loop ?: Loop::get(); diff --git a/src/UnixConnector.php b/src/UnixConnector.php index 627d60f..95f932c 100644 --- a/src/UnixConnector.php +++ b/src/UnixConnector.php @@ -18,8 +18,15 @@ final class UnixConnector implements ConnectorInterface { private $loop; - public function __construct(LoopInterface $loop = null) + /** + * @param ?LoopInterface $loop + */ + public function __construct($loop = null) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->loop = $loop ?: Loop::get(); } diff --git a/src/UnixServer.php b/src/UnixServer.php index cc46968..27b014d 100644 --- a/src/UnixServer.php +++ b/src/UnixServer.php @@ -50,8 +50,12 @@ final class UnixServer extends EventEmitter implements ServerInterface * @throws InvalidArgumentException if the listening address is invalid * @throws RuntimeException if listening on this address fails (already in use etc.) */ - public function __construct($path, LoopInterface $loop = null, array $context = array()) + public function __construct($path, $loop = null, array $context = array()) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + } + $this->loop = $loop ?: Loop::get(); if (\strpos($path, '://') === false) { diff --git a/tests/ConnectorTest.php b/tests/ConnectorTest.php index 02982db..ca10b78 100644 --- a/tests/ConnectorTest.php +++ b/tests/ConnectorTest.php @@ -12,11 +12,15 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $connector = new Connector(); $ref = new \ReflectionProperty($connector, 'connectors'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $connectors = $ref->getValue($connector); $ref = new \ReflectionProperty($connectors['tcp'], 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connectors['tcp']); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); @@ -29,11 +33,15 @@ public function testConstructWithLoopAssignsGivenLoop() $connector = new Connector(array(), $loop); $ref = new \ReflectionProperty($connector, 'connectors'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $connectors = $ref->getValue($connector); $ref = new \ReflectionProperty($connectors['tcp'], 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connectors['tcp']); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); @@ -50,7 +58,9 @@ public function testConstructWithContextAssignsGivenContext() )); $ref = new \ReflectionProperty($connector, 'connectors'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $connectors = $ref->getValue($connector); $this->assertSame($tcp, $connectors['tcp']); @@ -67,7 +77,9 @@ public function testConstructWithLegacyContextSignatureAssignsGivenContext() )); $ref = new \ReflectionProperty($connector, 'connectors'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $connectors = $ref->getValue($connector); $this->assertSame($tcp, $connectors['tcp']); @@ -80,11 +92,15 @@ public function testConstructWithLegacyLoopSignatureAssignsGivenLoop() $connector = new Connector($loop); $ref = new \ReflectionProperty($connector, 'connectors'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $connectors = $ref->getValue($connector); $ref = new \ReflectionProperty($connectors['tcp'], 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connectors['tcp']); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); diff --git a/tests/FdServerTest.php b/tests/FdServerTest.php index 7a97ae7..34b1fad 100644 --- a/tests/FdServerTest.php +++ b/tests/FdServerTest.php @@ -50,6 +50,12 @@ public function testCtorThrowsForInvalidUrl() new FdServer('tcp://127.0.0.1:8080', $loop); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + new FdServer(0, 'loop'); + } + public function testCtorThrowsForUnknownFdWithoutCallingCustomErrorHandler() { if (!is_dir('/dev/fd') || defined('HHVM_VERSION')) { diff --git a/tests/FunctionalTcpServerTest.php b/tests/FunctionalTcpServerTest.php index 7575d32..7b46b22 100644 --- a/tests/FunctionalTcpServerTest.php +++ b/tests/FunctionalTcpServerTest.php @@ -331,7 +331,9 @@ public function testServerPassesContextOptionsToSocket() )); $ref = new \ReflectionProperty($server, 'master'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $socket = $ref->getValue($server); $context = stream_context_get_options($socket); @@ -346,7 +348,9 @@ public function testServerPassesDefaultBacklogSizeViaContextOptionsToSocket() $server = new TcpServer(0); $ref = new \ReflectionProperty($server, 'master'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $socket = $ref->getValue($server); $context = stream_context_get_options($socket); diff --git a/tests/HappyEyeBallsConnectionBuilderTest.php b/tests/HappyEyeBallsConnectionBuilderTest.php index 581d883..ce34747 100644 --- a/tests/HappyEyeBallsConnectionBuilderTest.php +++ b/tests/HappyEyeBallsConnectionBuilderTest.php @@ -844,13 +844,17 @@ public function testCheckCallsRejectFunctionImmediateWithoutLeavingDanglingPromi $builder = new HappyEyeBallsConnectionBuilder($loop, $connector, $resolver, $uri, $host, $parts); $ref = new \ReflectionProperty($builder, 'connectQueue'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($builder, array('::1')); $builder->check($this->expectCallableNever(), function () { }); $ref = new \ReflectionProperty($builder, 'connectionPromises'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $promises = $ref->getValue($builder); $this->assertEquals(array(), $promises); @@ -876,7 +880,9 @@ public function testCleanUpCancelsAllPendingConnectionAttempts() $builder = new HappyEyeBallsConnectionBuilder($loop, $connector, $resolver, $uri, $host, $parts); $ref = new \ReflectionProperty($builder, 'connectQueue'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($builder, array('::1', '::1')); $builder->check($this->expectCallableNever(), function () { }); @@ -904,7 +910,9 @@ public function testCleanUpCancelsAllPendingConnectionAttemptsWithoutStartingNew $builder = new HappyEyeBallsConnectionBuilder($loop, $connector, $resolver, $uri, $host, $parts); $ref = new \ReflectionProperty($builder, 'connectQueue'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($builder, array('::1', '::1')); $builder->check($this->expectCallableNever(), function () { }); @@ -927,7 +935,9 @@ public function testMixIpsIntoConnectQueueSometimesAssignsInOriginalOrder() $builder->mixIpsIntoConnectQueue(array('::1', '::2')); $ref = new \ReflectionProperty($builder, 'connectQueue'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $value = $ref->getValue($builder); if ($value === array('::1', '::2')) { @@ -953,7 +963,9 @@ public function testMixIpsIntoConnectQueueSometimesAssignsInReverseOrder() $builder->mixIpsIntoConnectQueue(array('::1', '::2')); $ref = new \ReflectionProperty($builder, 'connectQueue'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $value = $ref->getValue($builder); if ($value === array('::2', '::1')) { diff --git a/tests/HappyEyeBallsConnectorTest.php b/tests/HappyEyeBallsConnectorTest.php index 5301b3b..b8daa72 100644 --- a/tests/HappyEyeBallsConnectorTest.php +++ b/tests/HappyEyeBallsConnectorTest.php @@ -34,21 +34,29 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $connector = new HappyEyeBallsConnector(null, $this->tcp, $this->resolver); $ref = new \ReflectionProperty($connector, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connector); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); } + public function testConstructWithInvalidLoopThrows() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + new HappyEyeBallsConnector('loop', $this->tcp, $this->resolver); + } + public function testConstructWithoutRequiredConnectorThrows() { - $this->setExpectedException('InvalidArgumentException'); + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($connector) expected React\Socket\ConnectorInterface'); new HappyEyeBallsConnector(null, null, $this->resolver); } public function testConstructWithoutRequiredResolverThrows() { - $this->setExpectedException('InvalidArgumentException'); + $this->setExpectedException('InvalidArgumentException', 'Argument #3 ($resolver) expected React\Dns\Resolver\ResolverInterface'); new HappyEyeBallsConnector(null, $this->tcp); } diff --git a/tests/SecureConnectorTest.php b/tests/SecureConnectorTest.php index e81f4a9..c3f6e23 100644 --- a/tests/SecureConnectorTest.php +++ b/tests/SecureConnectorTest.php @@ -26,16 +26,26 @@ public function setUpConnector() $this->connector = new SecureConnector($this->tcp, $this->loop); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + new SecureConnector($this->tcp, 'loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $connector = new SecureConnector($this->tcp); $ref = new \ReflectionProperty($connector, 'streamEncryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $streamEncryption = $ref->getValue($connector); $ref = new \ReflectionProperty($streamEncryption, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($streamEncryption); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); @@ -179,7 +189,9 @@ public function testStreamEncryptionWillBeEnabledAfterConnecting() $encryption->expects($this->once())->method('enable')->with($connection)->willReturn(new \React\Promise\Promise(function () { })); $ref = new \ReflectionProperty($this->connector, 'streamEncryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($this->connector, $encryption); $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('example.com:80'))->willReturn(Promise\resolve($connection)); @@ -196,7 +208,9 @@ public function testConnectionWillBeRejectedIfStreamEncryptionFailsAndClosesConn $encryption->expects($this->once())->method('enable')->willReturn(Promise\reject(new \RuntimeException('TLS error', 123))); $ref = new \ReflectionProperty($this->connector, 'streamEncryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($this->connector, $encryption); $this->tcp->expects($this->once())->method('connect')->with($this->equalTo('example.com:80'))->willReturn(Promise\resolve($connection)); @@ -228,7 +242,9 @@ public function testCancelDuringStreamEncryptionCancelsEncryptionAndClosesConnec $encryption->expects($this->once())->method('enable')->willReturn($pending); $ref = new \ReflectionProperty($this->connector, 'streamEncryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($this->connector, $encryption); $deferred = new Deferred(); @@ -295,7 +311,9 @@ public function testRejectionDuringTlsHandshakeShouldNotCreateAnyGarbageReferenc $encryption->expects($this->once())->method('enable')->willReturn($tls->promise()); $ref = new \ReflectionProperty($this->connector, 'streamEncryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($this->connector, $encryption); $promise = $this->connector->connect('example.com:80'); diff --git a/tests/SecureServerTest.php b/tests/SecureServerTest.php index a6ddcf2..7aa812b 100644 --- a/tests/SecureServerTest.php +++ b/tests/SecureServerTest.php @@ -18,6 +18,14 @@ public function setUpSkipTest() } } + public function testCtorThrowsForInvalidLoop() + { + $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); + + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + new SecureServer($tcp, 'loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock(); @@ -25,11 +33,15 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $server = new SecureServer($tcp); $ref = new \ReflectionProperty($server, 'encryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $encryption = $ref->getValue($server); $ref = new \ReflectionProperty($encryption, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($encryption); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); @@ -129,11 +141,15 @@ public function testConnectionWillTryToEnableEncryptionAndWaitForHandshake() $encryption->expects($this->once())->method('enable')->willReturn($pending); $ref = new \ReflectionProperty($server, 'encryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($server, $encryption); $ref = new \ReflectionProperty($server, 'context'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($server, array()); $server->on('error', $this->expectCallableNever()); @@ -160,11 +176,15 @@ public function testConnectionWillBeClosedWithErrorIfEnablingEncryptionFails() $encryption->expects($this->once())->method('enable')->willReturn(\React\Promise\reject($error)); $ref = new \ReflectionProperty($server, 'encryption'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($server, $encryption); $ref = new \ReflectionProperty($server, 'context'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $ref->setValue($server, array()); $error = null; diff --git a/tests/ServerTest.php b/tests/ServerTest.php index f69e6cb..00f583e 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -17,11 +17,15 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $server = new Server(0); $ref = new \ReflectionProperty($server, 'server'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $tcp = $ref->getValue($server); $ref = new \ReflectionProperty($tcp, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($tcp); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); @@ -44,6 +48,12 @@ public function testConstructorThrowsForInvalidUri() $server = new Server('invalid URI', $loop); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + new Server('127.0.0.1:0', 'loop'); + } + public function testConstructorCreatesExpectedTcpServer() { $server = new Server(0); @@ -109,7 +119,9 @@ public function testEmitsErrorWhenUnderlyingTcpServerEmitsError() $server = new Server(0); $ref = new \ReflectionProperty($server, 'server'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $tcp = $ref->getvalue($server); $error = new \RuntimeException(); diff --git a/tests/SocketServerTest.php b/tests/SocketServerTest.php index c7cee8e..d24154d 100644 --- a/tests/SocketServerTest.php +++ b/tests/SocketServerTest.php @@ -18,11 +18,15 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $socket->close(); $ref = new \ReflectionProperty($socket, 'server'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $tcp = $ref->getValue($socket); $ref = new \ReflectionProperty($tcp, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($tcp); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); @@ -65,6 +69,12 @@ public function testConstructorWithInvalidUriWithSchemaAndPortOnlyThrows() new SocketServer('tcp://0'); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); + new SocketServer('127.0.0.1:0', array(), 'loop'); + } + public function testConstructorCreatesExpectedTcpServer() { $socket = new SocketServer('127.0.0.1:0', array()); @@ -145,7 +155,9 @@ public function testEmitsErrorWhenUnderlyingTcpServerEmitsError() $socket = new SocketServer('127.0.0.1:0', array()); $ref = new \ReflectionProperty($socket, 'server'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $tcp = $ref->getvalue($socket); $error = new \RuntimeException(); diff --git a/tests/TcpConnectorTest.php b/tests/TcpConnectorTest.php index fb6f871..5b1016d 100644 --- a/tests/TcpConnectorTest.php +++ b/tests/TcpConnectorTest.php @@ -12,12 +12,20 @@ class TcpConnectorTest extends TestCase { const TIMEOUT = 5.0; + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + new TcpConnector('loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $connector = new TcpConnector(); $ref = new \ReflectionProperty($connector, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connector); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); diff --git a/tests/TcpServerTest.php b/tests/TcpServerTest.php index 8908d1c..e2aa2fe 100644 --- a/tests/TcpServerTest.php +++ b/tests/TcpServerTest.php @@ -26,12 +26,20 @@ public function setUpServer() $this->port = parse_url($this->server->getAddress(), PHP_URL_PORT); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + new TcpServer(0, 'loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $server = new TcpServer(0); $ref = new \ReflectionProperty($server, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($server); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); diff --git a/tests/TimeoutConnectorTest.php b/tests/TimeoutConnectorTest.php index fc218c4..df5a240 100644 --- a/tests/TimeoutConnectorTest.php +++ b/tests/TimeoutConnectorTest.php @@ -9,6 +9,14 @@ class TimeoutConnectorTest extends TestCase { + public function testCtorThrowsForInvalidLoop() + { + $base = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); + + $this->setExpectedException('InvalidArgumentException', 'Argument #3 ($loop) expected null|React\EventLoop\LoopInterface'); + new TimeoutConnector($base, 0.001, 'loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $base = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); @@ -16,7 +24,9 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $connector = new TimeoutConnector($base, 0.01); $ref = new \ReflectionProperty($connector, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connector); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); diff --git a/tests/UnixConnectorTest.php b/tests/UnixConnectorTest.php index d7e314a..fcb57c5 100644 --- a/tests/UnixConnectorTest.php +++ b/tests/UnixConnectorTest.php @@ -19,12 +19,20 @@ public function setUpConnector() $this->connector = new UnixConnector($this->loop); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + new UnixConnector('loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $connector = new UnixConnector(); $ref = new \ReflectionProperty($connector, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($connector); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); diff --git a/tests/UnixServerTest.php b/tests/UnixServerTest.php index c148de4..f962b92 100644 --- a/tests/UnixServerTest.php +++ b/tests/UnixServerTest.php @@ -29,6 +29,12 @@ public function setUpServer() $this->server = new UnixServer($this->uds); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface'); + new UnixServer($this->getRandomSocketUri(), 'loop'); + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { unlink(str_replace('unix://', '', $this->uds)); @@ -37,7 +43,9 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $server = new UnixServer($this->uds); $ref = new \ReflectionProperty($server, 'loop'); - $ref->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $ref->setAccessible(true); + } $loop = $ref->getValue($server); $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop);