Passed
Push — master ( 66c616...00643e )
by Eugene
03:07
created

ConnectionTest::testConnectTimedOut()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 33
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 4
eloc 19
nc 6
nop 0
dl 0
loc 33
rs 9.6333
c 2
b 0
f 1
1
<?php
2
3
/**
4
 * This file is part of the Tarantool Client package.
5
 *
6
 * (c) Eugene Leonovich <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Tarantool\Client\Tests\Integration\Connection;
15
16
use Tarantool\Client\Exception\ConnectionFailed;
17
use Tarantool\Client\Exception\UnexpectedResponse;
18
use Tarantool\Client\Request\PingRequest;
19
use Tarantool\Client\Schema\Criteria;
20
use Tarantool\Client\Schema\Operations;
21
use Tarantool\Client\Tests\Integration\ClientBuilder;
22
use Tarantool\Client\Tests\Integration\TestCase;
23
24
final class ConnectionTest extends TestCase
25
{
26
    /**
27
     * @dataProvider provideAutoConnectData
28
     * @doesNotPerformAssertions
29
     *
30
     * @eval create_space('test_auto_connect'):create_index('primary', {type = 'tree', parts = {1, 'unsigned'}})
31
     */
32
    public function testAutoConnect(string $methodName, array $methodArgs, ?string $space = null) : void
33
    {
34
        $object = $space ? $this->client->getSpace($space) : $this->client;
35
        $this->client->getHandler()->getConnection()->close();
36
37
        $object->$methodName(...$methodArgs);
38
    }
39
40
    public function provideAutoConnectData() : iterable
41
    {
42
        return [
43
            ['ping', []],
44
            ['call', ['box.stat']],
45
            ['evaluate', ['return 1']],
46
47
            ['select', [Criteria::key([42])], 'test_auto_connect'],
48
            ['insert', [[time()]], 'test_auto_connect'],
49
            ['replace', [[1, 2]], 'test_auto_connect'],
50
            ['update', [[1], Operations::add(1, 2)], 'test_auto_connect'],
51
            ['delete', [[1]], 'test_auto_connect'],
52
        ];
53
    }
54
55
    public function testMultipleConnect() : void
56
    {
57
        $conn = $this->client->getHandler()->getConnection();
58
59
        self::assertTrue($conn->isClosed());
60
61
        $conn->open();
62
        self::assertFalse($conn->isClosed());
63
64
        $conn->open();
65
        self::assertFalse($conn->isClosed());
66
    }
67
68
    public function tesMultipleDisconnect() : void
69
    {
70
        $conn = $this->client->getHandler()->getConnection();
71
72
        $conn->open();
73
        self::assertFalse($conn->isClosed());
74
75
        $conn->close();
76
        self::assertTrue($conn->isClosed());
77
78
        $conn->close();
79
        self::assertTrue($conn->isClosed());
80
    }
81
82
    public function testReturnSameGreeting() : void
83
    {
84
        $conn = $this->client->getHandler()->getConnection();
85
86
        $greeting1 = $conn->open();
87
        $greeting2 = $conn->open();
88
89
        self::assertSame($greeting1, $greeting2);
90
    }
91
92
    public function testReturnNewGreeting() : void
93
    {
94
        $conn = $this->client->getHandler()->getConnection();
95
96
        $greeting1 = $conn->open();
97
        $conn->close();
98
        $greeting2 = $conn->open();
99
100
        self::assertNotSame($greeting1, $greeting2);
101
    }
102
103
    public function testConnectInvalidHost() : void
104
    {
105
        $builder = ClientBuilder::createFromEnv()
106
            ->setHost('invalid_host');
107
108
        if (!$builder->isTcpConnection()) {
109
            self::markTestSkipped(sprintf('For the tcp connections only (current: "%s")', $builder->getUri()));
110
        }
111
112
        $client = $builder->build();
113
114
        $this->expectException(ConnectionFailed::class);
115
        $client->ping();
116
    }
117
118
    public function testConnectInvalidPort() : void
119
    {
120
        $builder = ClientBuilder::createFromEnv()
121
            ->setPort(123456);
122
123
        if (!$builder->isTcpConnection()) {
124
            self::markTestSkipped(sprintf('For the tcp connections only (current: "%s")', $builder->getUri()));
125
        }
126
127
        $client = $builder->build();
128
129
        $this->expectException(ConnectionFailed::class);
130
        $client->ping();
131
    }
132
133
    public function testConnectTimedOut() : void
134
    {
135
        $connectTimeout = 2;
136
        $builder = ClientBuilder::createFromEnv();
137
138
        // http://stackoverflow.com/q/100841/1160901
139
        $builder->setHost($host = '10.255.255.1');
140
        $builder->setConnectionOptions(['connect_timeout' => $connectTimeout]);
141
142
        if (!$builder->isTcpConnection()) {
143
            self::markTestSkipped(sprintf('For the tcp connections only (current: "%s")', $builder->getUri()));
144
        }
145
146
        $client = $builder->build();
147
148
        $start = microtime(true);
149
150
        try {
151
            $client->ping();
152
        } catch (ConnectionFailed $e) {
153
            if (false !== strpos($e->getMessage(), 'No route to host')) {
154
                self::markTestSkipped(sprintf('Unable to route to host %s.', $host));
155
            }
156
157
            $time = microtime(true) - $start;
158
            self::assertRegExp('/Failed to connect to .+?: (Connection|Operation) timed out\./', $e->getMessage());
159
            self::assertGreaterThanOrEqual($connectTimeout, $time);
160
            self::assertLessThanOrEqual($connectTimeout + 0.1, $time);
161
162
            return;
163
        }
164
165
        self::fail();
166
    }
167
168
    public function testUnexpectedResponse() : void
169
    {
170
        $client = ClientBuilder::createFromEnv()->build();
171
        $connection = self::triggerUnexpectedResponse($client->getHandler(), new PingRequest());
172
173
        // Tarantool will answer with the ping response
174
        try {
175
            $client->evaluate('return 42');
176
        } catch (UnexpectedResponse $e) {
177
            self::assertTrue($connection->isClosed());
178
179
            return;
180
        }
181
182
        self::fail(UnexpectedResponse::class.' was not thrown.');
183
    }
184
}
185