Passed
Branch main (45b422)
by Andreas
01:40
created

ServerPoolTest::testGuzzleClientOptionTest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
c 0
b 0
f 0
rs 9.408
cc 2
nc 2
nop 2
1
<?php
2
/**
3
 * Licensed to CRATE Technology GmbH("Crate") under one or more contributor
4
 * license agreements.  See the NOTICE file distributed with this work for
5
 * additional information regarding copyright ownership.  Crate licenses
6
 * this file to you under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.  You may
8
 * obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
15
 * License for the specific language governing permissions and limitations
16
 * under the License.
17
 *
18
 * However, if you have executed another commercial license agreement
19
 * with Crate these terms will supersede the license and you may use the
20
 * software solely pursuant to the terms of the relevant commercial agreement.
21
 */
22
23
declare(strict_types=1);
24
25
namespace CrateTest\PDO\Http;
26
27
use Crate\PDO\Exception\RuntimeException;
28
use Crate\PDO\Http\ServerPool;
29
use Crate\PDO\PDO;
30
use Crate\Stdlib\Collection;
31
use GuzzleHttp\Client;
32
use GuzzleHttp\ClientInterface;
33
use GuzzleHttp\Exception\BadResponseException;
34
use GuzzleHttp\Exception\ConnectException;
35
use GuzzleHttp\Psr7\Request;
36
use GuzzleHttp\Psr7\Response;
37
use GuzzleHttp\RequestOptions;
38
use PHPUnit\Framework\MockObject\MockObject;
39
use PHPUnit\Framework\TestCase;
40
41
final class ServerPoolTest extends TestCase
42
{
43
    /**
44
     * @var PDO
45
     */
46
    private $pdo;
47
48
    /**
49
     * @var Client|MockObject
50
     */
51
    private $client;
52
53
    /**
54
     * @var ServerPool
55
     */
56
    private $serverPool;
57
58
    protected function setUp(): void
59
    {
60
        $this->client = $this->createMock(ClientInterface::class);
61
62
        $this->serverPool = new ServerPool(['localhost:4200', 'localhost:4200'], $this->client);
63
64
        $this->pdo = new PDO('crate:localhost:4200');
65
        $this->pdo->setServer($this->serverPool);
66
    }
67
68
    public function pdoOptions()
69
    {
70
        return [
71
            [
72
                [
73
                    PDO::ATTR_TIMEOUT               => 10,
74
                    PDO::CRATE_ATTR_DEFAULT_SCHEMA  => 'default',
75
                    PDO::CRATE_ATTR_HTTP_BASIC_AUTH => ['foo', 'bar'],
76
                ],
77
                [
78
                    RequestOptions::TIMEOUT         => 10,
79
                    RequestOptions::CONNECT_TIMEOUT => 10,
80
                    RequestOptions::AUTH            => ['foo', 'bar'],
81
                    RequestOptions::HEADERS         => [
82
                        'Default-Schema' => 'default',
83
                    ],
84
                ],
85
            ],
86
            [
87
                [
88
                    PDO::CRATE_ATTR_SSL_MODE => PDO::CRATE_ATTR_SSL_MODE_ENABLED_BUT_WITHOUT_HOST_VERIFICATION,
89
                ],
90
                [
91
                    RequestOptions::VERIFY => false,
92
                    'base_uri'             => 'https://localhost:4200',
93
                ],
94
            ],
95
            [
96
                [
97
                    PDO::CRATE_ATTR_SSL_MODE => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
98
                ],
99
                [
100
                    'base_uri' => 'https://localhost:4200',
101
                ],
102
            ],
103
            [
104
                [
105
                    PDO::CRATE_ATTR_SSL_MODE    => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
106
                    PDO::CRATE_ATTR_SSL_CA_PATH => 'foo.pem',
107
                ],
108
                [
109
                    'base_uri'             => 'https://localhost:4200',
110
                    RequestOptions::VERIFY => 'foo.pem',
111
                ],
112
            ],
113
            [
114
                [
115
                    PDO::CRATE_ATTR_SSL_MODE        => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
116
                    PDO::CRATE_ATTR_SSL_CA_PATH     => 'foo.pem',
117
                    PDO::CRATE_ATTR_SSL_CA_PASSWORD => 'foo',
118
                ],
119
                [
120
                    'base_uri'             => 'https://localhost:4200',
121
                    RequestOptions::VERIFY => ['foo.pem', 'foo'],
122
                ],
123
            ],
124
            [
125
                [
126
                    PDO::CRATE_ATTR_SSL_MODE     => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
127
                    PDO::CRATE_ATTR_SSL_KEY_PATH => 'foo.pem',
128
                ],
129
                [
130
                    'base_uri'              => 'https://localhost:4200',
131
                    RequestOptions::SSL_KEY => 'foo.pem',
132
                ],
133
            ],
134
            [
135
                [
136
                    PDO::CRATE_ATTR_SSL_MODE         => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
137
                    PDO::CRATE_ATTR_SSL_KEY_PATH     => 'foo.pem',
138
                    PDO::CRATE_ATTR_SSL_KEY_PASSWORD => 'foo',
139
                ],
140
                [
141
                    'base_uri'              => 'https://localhost:4200',
142
                    RequestOptions::SSL_KEY => ['foo.pem', 'foo'],
143
                ],
144
            ],
145
            [
146
                [
147
                    PDO::CRATE_ATTR_SSL_MODE      => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
148
                    PDO::CRATE_ATTR_SSL_CERT_PATH => 'foo.pem',
149
                ],
150
                [
151
                    'base_uri'           => 'https://localhost:4200',
152
                    RequestOptions::CERT => 'foo.pem',
153
                ],
154
            ],
155
            [
156
                [
157
                    PDO::CRATE_ATTR_SSL_MODE          => PDO::CRATE_ATTR_SSL_MODE_REQUIRED,
158
                    PDO::CRATE_ATTR_SSL_CERT_PATH     => 'foo.pem',
159
                    PDO::CRATE_ATTR_SSL_CERT_PASSWORD => 'foo',
160
                ],
161
                [
162
                    'base_uri'           => 'https://localhost:4200',
163
                    RequestOptions::CERT => ['foo.pem', 'foo'],
164
                ],
165
            ],
166
        ];
167
    }
168
169
    /**
170
     * @dataProvider pdoOptions
171
     *
172
     * @param array $options
173
     * @param array $expected
174
     */
175
    public function testGuzzleClientOptionTest(array $options, array $expected)
176
    {
177
        foreach ($options as $attr => $val) {
178
            $this->pdo->setAttribute($attr, $val);
179
        }
180
181
        $expectedWithDefaults = array_merge([
182
            RequestOptions::TIMEOUT         => 0.0,
183
            RequestOptions::CONNECT_TIMEOUT => 0.0,
184
            RequestOptions::JSON            => [
185
                'stmt' => 'query',
186
                'args' => [],
187
            ],
188
189
            RequestOptions::HEADERS => [
190
                'Default-Schema' => 'doc',
191
            ],
192
193
            RequestOptions::AUTH => null,
194
            'base_uri'           => 'http://localhost:4200',
195
        ], $expected);
196
197
        $body = json_encode(['rows' => [], 'cols' => [], 'duration' => 0, 'rowcount' => 0]);
198
199
        $this->client
200
            ->expects($this->once())
201
            ->method('request')
202
            ->with('POST', '/_sql', $expectedWithDefaults)
203
            ->willReturn(new Response(200, [], $body));
204
205
        $this->serverPool->execute('query', []);
206
    }
207
208
    public function testExecuteWithNoRespondingServers()
209
    {
210
        $this->client
211
            ->expects($this->any())
212
            ->method('request')
213
            ->willThrowException(new ConnectException('helloWorld', new Request('post', 'localhost')));
214
215
        $this->expectException(ConnectException::class);
216
        $this->serverPool->execute('helloWorld', []);
217
    }
218
219
    public function testExecuteWithFirstFailing()
220
    {
221
        $body = json_encode(['rows' => [], 'cols' => [], 'duration' => 0, 'rowcount' => 0]);
222
223
        $this->client
224
            ->expects($this->at(0))
225
            ->method('request')
226
            ->willThrowException(new ConnectException('helloWorld', new Request('post', 'localhost')));
227
228
        $this->client
229
            ->expects($this->at(1))
230
            ->method('request')
231
            ->willReturn(new Response(200, [], $body));
232
233
        $this->assertInstanceOf(Collection::class, $this->serverPool->execute('helloWorld', []));
234
    }
235
236
    public function testWithBadRequest()
237
    {
238
        $body = json_encode(['error' => ['code' => 1337, 'message' => 'invalid sql, u fool.']]);
239
240
        $request  = new Request('post', 'localhost');
241
        $response = new Response(400, [], $body);
242
243
        $this->client
244
            ->expects($this->once())
245
            ->method('request')
246
            ->willThrowException(new BadResponseException('error', $request, $response));
247
248
        $this->expectException(RuntimeException::class);
249
        $this->serverPool->execute('helloWorld', []);
250
    }
251
}
252