Passed
Push — master ( 68b04b...f7f8f7 )
by Eugene
02:12
created

DsnTest::testGetNonFloat()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
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\Unit;
15
16
use PHPUnit\Framework\TestCase;
17
use Tarantool\Client\Dsn;
18
19
final class DsnTest extends TestCase
20
{
21
    /**
22
     * @dataProvider provideValidTcpDsns
23
     */
24
    public function testParseValidTcpDsn(string $dsn, array $expectedResult) : void
25
    {
26
        $dsn = Dsn::parse($dsn);
27
        self::assertSame($expectedResult['uri'], $dsn->getConnectionUri());
28
        self::assertSame($expectedResult['host'], $dsn->getHost());
29
        self::assertSame($expectedResult['port'], $dsn->getPort());
30
        self::assertNull($dsn->getPath());
31
        self::assertTrue($dsn->isTcp());
32
33
        if (isset($expectedResult['username'])) {
34
            self::assertSame($expectedResult['username'], $dsn->getUsername());
35
            self::assertSame($expectedResult['password'] ?? '', $dsn->getPassword());
36
        }
37
    }
38
39
    public function provideValidTcpDsns() : iterable
40
    {
41
        return [
42
            ['tcp://127.0.0.1', ['uri' => 'tcp://127.0.0.1:3301', 'host' => '127.0.0.1', 'port' => 3301]],
43
            ['tcp://localhost', ['uri' => 'tcp://localhost:3301', 'host' => 'localhost', 'port' => 3301]],
44
            ['tcp://f%40%40:b%40r@localhost', ['uri' => 'tcp://localhost:3301', 'host' => 'localhost', 'port' => 3301, 'username' => 'f@@', 'password' => 'b@r']],
45
            ['tcp://foo.bar:1234', ['uri' => 'tcp://foo.bar:1234', 'host' => 'foo.bar', 'port' => 1234]],
46
            ['tcp://foo.bar:1234/?opt=42', ['uri' => 'tcp://foo.bar:1234', 'host' => 'foo.bar', 'port' => 1234]],
47
            ['tcp://foo.bar.baz.com', ['uri' => 'tcp://foo.bar.baz.com:3301', 'host' => 'foo.bar.baz.com', 'port' => 3301]],
48
            ['tcp://foo:[email protected]:1234/?opt=42', ['uri' => 'tcp://baz.com:1234', 'host' => 'baz.com', 'port' => 1234, 'username' => 'foo', 'password' => 'bar']],
49
            ['tcp://[fe80::1]', ['uri' => 'tcp://[fe80::1]:3301', 'host' => '[fe80::1]', 'port' => 3301]],
50
            ['tcp://[fe80::1]:1234', ['uri' => 'tcp://[fe80::1]:1234', 'host' => '[fe80::1]', 'port' => 1234]],
51
            ['tcp://[de:ad:be:ef::ca:fe]:1234', ['uri' => 'tcp://[de:ad:be:ef::ca:fe]:1234', 'host' => '[de:ad:be:ef::ca:fe]', 'port' => 1234]],
52
            ['tcp://foo@[de:ad:be:ef::ca:fe]:1234', ['uri' => 'tcp://[de:ad:be:ef::ca:fe]:1234', 'host' => '[de:ad:be:ef::ca:fe]', 'port' => 1234, 'username' => 'foo', 'password' => '']],
53
        ];
54
    }
55
56
    /**
57
     * @dataProvider provideValidUdsDsns
58
     */
59
    public function testParseValidUdsDsn(string $dsn, array $expected) : void
60
    {
61
        $dsn = Dsn::parse($dsn);
62
        self::assertSame($expected['uri'], $dsn->getConnectionUri());
63
        self::assertNull($dsn->getHost());
64
        self::assertNull($dsn->getPort());
65
        self::assertSame($expected['path'], $dsn->getPath());
66
        self::assertFalse($dsn->isTcp());
67
68
        if (isset($expected['username'])) {
69
            self::assertSame($expected['username'], $dsn->getUsername());
70
            self::assertSame($expected['password'] ?? '', $dsn->getPassword());
71
        }
72
    }
73
74
    public function provideValidUdsDsns() : iterable
75
    {
76
        return [
77
            ['unix:///path/to/socket.sock', ['uri' => 'unix:///path/to/socket.sock', 'path' => '/path/to/socket.sock']],
78
            ['unix:///path/to/socket.sock?opt=42', ['uri' => 'unix:///path/to/socket.sock', 'path' => '/path/to/socket.sock']],
79
            ['unix://foo@/path/to/socket.sock', ['uri' => 'unix:///path/to/socket.sock', 'path' => '/path/to/socket.sock', 'username' => 'foo', 'password' => '']],
80
            ['unix://foo:bar@/path/to/socket.sock', ['uri' => 'unix:///path/to/socket.sock', 'path' => '/path/to/socket.sock', 'username' => 'foo', 'password' => 'bar']],
81
            ['unix://foo:bar@/path/to/socket.sock?opt=42', ['uri' => 'unix:///path/to/socket.sock', 'path' => '/path/to/socket.sock', 'username' => 'foo', 'password' => 'bar']],
82
            ['unix://f%40%40:b%40r@%2fsocket.sock', ['uri' => 'unix://%2fsocket.sock', 'path' => '/socket.sock', 'username' => 'f@@', 'password' => 'b@r']],
83
        ];
84
    }
85
86
    /**
87
     * @dataProvider provideInvalidDsns
88
     */
89
    public function testParseInvalidDsn(string $nonDsn) : void
90
    {
91
        $this->expectException(\InvalidArgumentException::class);
92
        $this->expectExceptionMessage(sprintf('Unable to parse DSN "%s"', $nonDsn));
93
        Dsn::parse($nonDsn);
94
    }
95
96
    public function provideInvalidDsns() : iterable
97
    {
98
        return [
99
            [''],
100
            ['foobar'],
101
            ['tcp:'],
102
            ['tcp:host'],
103
            ['tcp:/'],
104
            ['tcp:/host'],
105
            ['tcp://'],
106
            ['tcp://host/path'],
107
            ['tcp:////'],
108
            ['unix:'],
109
            ['unix:/'],
110
            ['unix:/path'],
111
            ['unix://'],
112
            ['unix://foo.bar:3030/path'],
113
            ['unix:////'],
114
            ['http://host'],
115
            ['file:///path'],
116
        ];
117
    }
118
119
    /**
120
     * @dataProvider provideStringOptions
121
     */
122
    public function testGetString(string $dsn, string $option, ?string $expectedValue) : void
123
    {
124
        $dsn = Dsn::parse($dsn);
125
        self::assertSame($expectedValue, $dsn->getString($option));
126
    }
127
128
    public function provideStringOptions() : iterable
129
    {
130
        return [
131
            ['tcp://host/?foo=bar', 'foo', 'bar'],
132
            ['tcp://host/?foo=b%40r', 'foo', 'b@r'],
133
            ['tcp://host/?foo=', 'foo', ''],
134
            ['tcp://host/?foo=42', 'foo', '42'],
135
            ['tcp://host/?foo=%25', 'foo', '%'],
136
            ['tcp://host/?foo=%2525', 'foo', '%25'],
137
            ['tcp://host', 'foo', null],
138
            ['unix:///socket.sock/?foo=bar', 'foo', 'bar'],
139
            ['unix:///socket.sock/?foo=b%40r', 'foo', 'b@r'],
140
            ['unix:///socket.sock/?foo=', 'foo', ''],
141
            ['unix:///socket.sock/?foo=42', 'foo', '42'],
142
            ['unix:///socket.sock/?foo=%25', 'foo', '%'],
143
            ['unix:///socket.sock/?foo=%2525', 'foo', '%25'],
144
            ['unix:///socket.sock', 'foo', null],
145
        ];
146
    }
147
148
    public function testGetStringDefault() : void
149
    {
150
        $dsn = Dsn::parse('tcp://host/?foo=bar');
151
        self::assertSame('qux', $dsn->getString('baz', 'qux'));
152
    }
153
154
    /**
155
     * @dataProvider provideIntOptions
156
     */
157
    public function testGetInt(string $dsn, string $option, $expectedValue) : void
158
    {
159
        $dsn = Dsn::parse($dsn);
160
        self::assertSame($expectedValue, $dsn->getInt($option));
161
    }
162
163
    public function provideIntOptions() : iterable
164
    {
165
        return [
166
            ['tcp://host/?foo=42', 'foo', 42],
167
            ['tcp://host/?foo=0', 'foo', 0],
168
            ['tcp://host', 'foo', null],
169
            ['unix:///socket.sock/?foo=42', 'foo', 42],
170
            ['unix:///socket.sock/?foo=0', 'foo', 0],
171
            ['unix:///socket.sock', 'foo', null],
172
        ];
173
    }
174
175
    public function testGetIntDefault() : void
176
    {
177
        $dsn = Dsn::parse('tcp://host/?foo=2');
178
        self::assertSame(42, $dsn->getInt('baz', 42));
179
    }
180
181
    /**
182
     * @dataProvider provideNonIntOptions
183
     */
184
    public function testGetNonInt(string $dsn, string $option) : void
185
    {
186
        $dsn = Dsn::parse($dsn);
187
188
        $this->expectException(\TypeError::class);
189
        $this->expectExceptionMessage('DSN option "foo" must be of type int');
190
        $dsn->getInt($option);
191
    }
192
193
    public function provideNonIntOptions() : iterable
194
    {
195
        return [
196
            ['tcp://host/?foo=bar', 'foo'],
197
            ['tcp://host/?foo=4.2', 'foo'],
198
            ['tcp://host/?foo=true', 'foo'],
199
            ['tcp://host/?foo=', 'foo'],
200
            ['unix:///socket.sock/?foo=bar', 'foo'],
201
            ['unix:///socket.sock/?foo=4.2', 'foo'],
202
            ['unix:///socket.sock/?foo=true', 'foo'],
203
            ['unix:///socket.sock/?foo=', 'foo'],
204
        ];
205
    }
206
207
    /**
208
     * @dataProvider provideFloatOptions
209
     */
210
    public function testGetFloat(string $dsn, string $option, $expectedValue) : void
211
    {
212
        $dsn = Dsn::parse($dsn);
213
        self::assertSame($expectedValue, $dsn->getFloat($option));
214
    }
215
216
    public function provideFloatOptions() : iterable
217
    {
218
        return [
219
            ['tcp://host/?foo=42', 'foo', 42.0],
220
            ['tcp://host/?foo=42.3', 'foo', 42.3],
221
            ['tcp://host/?foo=0', 'foo', 0.0],
222
            ['tcp://host', 'foo', null],
223
            ['unix:///socket.sock/?foo=42', 'foo', 42.0],
224
            ['unix:///socket.sock/?foo=0', 'foo', 0.0],
225
            ['unix:///socket.sock/?foo=0.1', 'foo', 0.1],
226
            ['unix:///socket.sock', 'foo', null],
227
        ];
228
    }
229
230
    public function testGetFloatDefault() : void
231
    {
232
        $dsn = Dsn::parse('tcp://host/?foo=2');
233
        self::assertSame(42.3, $dsn->getFloat('baz', 42.3));
234
    }
235
236
    /**
237
     * @dataProvider provideNonFloatOptions
238
     */
239
    public function testGetNonFloat(string $dsn, string $option) : void
240
    {
241
        $dsn = Dsn::parse($dsn);
242
243
        $this->expectException(\TypeError::class);
244
        $this->expectExceptionMessage('DSN option "foo" must be of type float');
245
        $dsn->getFloat($option);
246
    }
247
248
    public function provideNonFloatOptions() : iterable
249
    {
250
        return [
251
            ['tcp://host/?foo=bar', 'foo'],
252
            ['tcp://host/?foo=true', 'foo'],
253
            ['tcp://host/?foo=', 'foo'],
254
            ['unix:///socket.sock/?foo=bar', 'foo'],
255
            ['unix:///socket.sock/?foo=true', 'foo'],
256
            ['unix:///socket.sock/?foo=', 'foo'],
257
        ];
258
    }
259
260
    /**
261
     * @dataProvider provideBoolOptions
262
     */
263
    public function testGetBool(string $dsn, string $option, ?bool $expectedValue) : void
264
    {
265
        $dsn = Dsn::parse($dsn);
266
        self::assertSame($expectedValue, $dsn->getBool($option));
267
    }
268
269
    public function provideBoolOptions() : iterable
270
    {
271
        return [
272
            ['tcp://host/?foo=true', 'foo', true],
273
            ['tcp://host/?foo=false', 'foo', false],
274
            ['tcp://host/?foo=on', 'foo', true],
275
            ['tcp://host/?foo=off', 'foo', false],
276
            ['tcp://host/?foo=1', 'foo', true],
277
            ['tcp://host/?foo=0', 'foo', false],
278
            ['tcp://host/?foo=', 'foo', false],
279
            ['tcp://host', 'foo', null],
280
            ['unix:///socket.sock/?foo=true', 'foo', true],
281
            ['unix:///socket.sock/?foo=false', 'foo', false],
282
            ['unix:///socket.sock/?foo=on', 'foo', true],
283
            ['unix:///socket.sock/?foo=off', 'foo', false],
284
            ['unix:///socket.sock/?foo=1', 'foo', true],
285
            ['unix:///socket.sock/?foo=0', 'foo', false],
286
            ['unix:///socket.sock/?foo=', 'foo', false],
287
            ['unix:///socket.sock', 'foo', null],
288
        ];
289
    }
290
291
    public function testGetBoolDefault() : void
292
    {
293
        $dsn = Dsn::parse('tcp://host/?foo=0');
294
        self::assertTrue($dsn->getBool('baz', true));
295
    }
296
297
    /**
298
     * @dataProvider provideNonBoolOptions
299
     */
300
    public function testGetNonBool(string $dsn, string $option) : void
301
    {
302
        $dsn = Dsn::parse($dsn);
303
304
        $this->expectException(\TypeError::class);
305
        $this->expectExceptionMessage('DSN option "foo" must be of type bool');
306
        $dsn->getBool($option);
307
    }
308
309
    public function provideNonBoolOptions() : iterable
310
    {
311
        return [
312
            ['tcp://host/?foo=bar', 'foo'],
313
            ['tcp://host/?foo=42', 'foo'],
314
            ['unix:///socket.sock/?foo=bar', 'foo'],
315
            ['unix:///socket.sock/?foo=42', 'foo'],
316
        ];
317
    }
318
}
319