Skip to content

Commit

Permalink
Enhance StreamConnection
Browse files Browse the repository at this point in the history
Also, fixes edge case error when StreamConnection::open()
was returning null instead of the Greeting object:

TypeError: Return value of Tarantool\Client\Connection\StreamConnection::open() must be an instance of Tarantool\Client\Connection\Greeting, null returned
  • Loading branch information
rybakit committed May 20, 2020
1 parent afc89bd commit 10bad0c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 11 deletions.
15 changes: 4 additions & 11 deletions src/Connection/StreamConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,9 @@ public static function create(string $uri, array $options = []) : self
: self::createTcp($uri, $options);
}

/**
* @see https://github.com/vimeo/psalm/issues/3021
* @psalm-suppress InvalidNullableReturnType
*/
public function open() : Greeting
{
if (\is_resource($this->stream)) {
/** @see https://github.com/vimeo/psalm/issues/3021 */
/** @psalm-suppress NullableReturnStatement */
if ($this->greeting) {
return $this->greeting;
}

Expand Down Expand Up @@ -125,7 +119,7 @@ public function open() : Greeting

public function close() : void
{
if (\is_resource($this->stream)) {
if ($this->stream) {
/** @psalm-suppress InvalidPropertyAssignmentValue */
\fclose($this->stream);
}
Expand All @@ -136,13 +130,12 @@ public function close() : void

public function isClosed() : bool
{
return !\is_resource($this->stream);
return !$this->stream;
}

public function send(string $data) : string
{
/** @psalm-suppress PossiblyNullArgument */
if (!\fwrite($this->stream, $data)) {
if (!$this->stream || !\fwrite($this->stream, $data)) {
throw new CommunicationFailed('Unable to write request');
}

Expand Down
33 changes: 33 additions & 0 deletions tests/Integration/Connection/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@

namespace Tarantool\Client\Tests\Integration\Connection;

use Tarantool\Client\Exception\CommunicationFailed;
use Tarantool\Client\Exception\ConnectionFailed;
use Tarantool\Client\Exception\UnexpectedResponse;
use Tarantool\Client\Request\PingRequest;
use Tarantool\Client\Schema\Criteria;
use Tarantool\Client\Schema\Operations;
use Tarantool\Client\Tests\GreetingDataProvider;
use Tarantool\Client\Tests\Integration\ClientBuilder;
use Tarantool\Client\Tests\Integration\FakeServer\FakeServerBuilder;
use Tarantool\Client\Tests\Integration\FakeServer\Handler\AtConnectionHandler;
use Tarantool\Client\Tests\Integration\FakeServer\Handler\WriteHandler;
use Tarantool\Client\Tests\Integration\TestCase;

final class ConnectionTest extends TestCase
Expand Down Expand Up @@ -181,4 +186,32 @@ public function testUnexpectedResponse() : void

self::fail(UnexpectedResponse::class.' was not thrown');
}

public function testOpenConnectionHandlesTheMissingGreetingCorrectly() : void
{
$clientBuilder = ClientBuilder::createFromEnvForTheFakeServer();

FakeServerBuilder::create(
new AtConnectionHandler(1, new WriteHandler('')),
new AtConnectionHandler(2, new WriteHandler(GreetingDataProvider::generateGreeting()))
)
->setUri($clientBuilder->getUri())
->start();

$client = $clientBuilder->build();
$connection = $client->getHandler()->getConnection();

try {
$connection->open();
self::fail('Connection not established');
} catch (CommunicationFailed $e) {
self::assertSame('Unable to read greeting', $e->getMessage());
// at that point the connection was successfully established,
// but the greeting message was not read
}

// the second call should correctly handle
// the missing greeting from the previous call
$connection->open();
}
}
38 changes: 38 additions & 0 deletions tests/Integration/FakeServer/Handler/AtConnectionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/**
* This file is part of the Tarantool Client package.
*
* (c) Eugene Leonovich <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Tarantool\Client\Tests\Integration\FakeServer\Handler;

class AtConnectionHandler implements Handler
{
private $atConnectionNumber;
private $handler;
private $connectionCount = 0;

public function __construct(int $atConnectionNumber, Handler $handler)
{
$this->atConnectionNumber = $atConnectionNumber;
$this->handler = $handler;
}

public function __invoke($conn, string $sid) : ?bool
{
++$this->connectionCount;

if ($this->connectionCount === $this->atConnectionNumber) {
return ($this->handler)($conn, $sid);
}

return null;
}
}

0 comments on commit 10bad0c

Please sign in to comment.