Passed
Push — phpstan-tests ( 6a2b78...974220 )
by Michael
61:35 queued 23s
created

DriverManagerTest::testDatabaseUrlShard()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 34
rs 9.584
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\DBAL;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\Connections\MasterSlaveConnection;
9
use Doctrine\DBAL\DBALException;
10
use Doctrine\DBAL\Driver;
11
use Doctrine\DBAL\Driver\PDOMySql\Driver as PDOMySQLDriver;
12
use Doctrine\DBAL\Driver\PDOSqlite\Driver as PDOSqliteDriver;
13
use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver;
14
use Doctrine\DBAL\DriverManager;
15
use Doctrine\DBAL\Platforms\AbstractPlatform;
16
use Doctrine\DBAL\Sharding\PoolingShardConnection;
17
use Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser;
18
use Doctrine\Tests\DbalTestCase;
19
use PDO;
20
use stdClass;
21
use function extension_loaded;
22
use function get_class;
23
use function in_array;
24
use function is_array;
25
26
class DriverManagerTest extends DbalTestCase
27
{
28
    /**
29
     * @requires extension pdo_sqlite
30
     */
31
    public function testInvalidPdoInstance()
32
    {
33
        $this->expectException(DBALException::class);
34
        DriverManager::getConnection(['pdo' => 'test']);
35
    }
36
37
    /**
38
     * @requires extension pdo_sqlite
39
     */
40
    public function testValidPdoInstance()
41
    {
42
        $conn = DriverManager::getConnection([
43
            'pdo' => new PDO('sqlite::memory:'),
44
        ]);
45
46
        self::assertEquals('sqlite', $conn->getDatabasePlatform()->getName());
47
    }
48
49
    /**
50
     * @group DBAL-32
51
     * @requires extension pdo_sqlite
52
     */
53
    public function testPdoInstanceSetErrorMode()
54
    {
55
        $pdo = new PDO('sqlite::memory:');
56
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
57
        $options = ['pdo' => $pdo];
58
59
        DriverManager::getConnection($options);
60
        self::assertEquals(PDO::ERRMODE_EXCEPTION, $pdo->getAttribute(PDO::ATTR_ERRMODE));
61
    }
62
63
    public function testCheckParams()
64
    {
65
        $this->expectException(DBALException::class);
66
67
        DriverManager::getConnection([]);
68
    }
69
70
    public function testInvalidDriver()
71
    {
72
        $this->expectException(DBALException::class);
73
74
        DriverManager::getConnection(['driver' => 'invalid_driver']);
75
    }
76
77
    /**
78
     * @requires extension pdo_sqlite
79
     */
80
    public function testCustomPlatform()
81
    {
82
        $platform = $this->createMock(AbstractPlatform::class);
83
        $options  = [
84
            'pdo'      => new PDO('sqlite::memory:'),
85
            'platform' => $platform,
86
        ];
87
88
        $conn = DriverManager::getConnection($options);
89
        self::assertSame($platform, $conn->getDatabasePlatform());
90
    }
91
92
    /**
93
     * @requires extension pdo_sqlite
94
     */
95
    public function testCustomWrapper()
96
    {
97
        $wrapper      = $this->createMock(Connection::class);
98
        $wrapperClass = get_class($wrapper);
99
100
        $options = [
101
            'pdo' => new PDO('sqlite::memory:'),
102
            'wrapperClass' => $wrapperClass,
103
        ];
104
105
        $conn = DriverManager::getConnection($options);
106
        self::assertInstanceOf($wrapperClass, $conn);
107
    }
108
109
    /**
110
     * @requires extension pdo_sqlite
111
     */
112
    public function testInvalidWrapperClass()
113
    {
114
        $this->expectException(DBALException::class);
115
116
        $options = [
117
            'pdo' => new PDO('sqlite::memory:'),
118
            'wrapperClass' => stdClass::class,
119
        ];
120
121
        DriverManager::getConnection($options);
122
    }
123
124
    public function testInvalidDriverClass()
125
    {
126
        $this->expectException(DBALException::class);
127
128
        $options = ['driverClass' => stdClass::class];
129
130
        DriverManager::getConnection($options);
131
    }
132
133
    public function testValidDriverClass()
134
    {
135
        $options = ['driverClass' => PDOMySQLDriver::class];
136
137
        $conn = DriverManager::getConnection($options);
138
        self::assertInstanceOf(PDOMySQLDriver::class, $conn->getDriver());
139
    }
140
141
    public function testDatabaseUrlMasterSlave()
142
    {
143
        $options = [
144
            'driver' => 'pdo_mysql',
145
            'master' => ['url' => 'mysql://foo:bar@localhost:11211/baz'],
146
            'slaves' => [
147
                'slave1' => ['url' => 'mysql://foo:bar@localhost:11211/baz_slave'],
148
            ],
149
            'wrapperClass' => MasterSlaveConnection::class,
150
        ];
151
152
        $conn = DriverManager::getConnection($options);
153
154
        $params = $conn->getParams();
155
        self::assertInstanceOf(PDOMySQLDriver::class, $conn->getDriver());
156
157
        $expected = [
158
            'user'     => 'foo',
159
            'password' => 'bar',
160
            'host'     => 'localhost',
161
            'port'     => 11211,
162
        ];
163
164
        foreach ($expected as $key => $value) {
165
            self::assertEquals($value, $params['master'][$key]);
166
            self::assertEquals($value, $params['slaves']['slave1'][$key]);
167
        }
168
169
        self::assertEquals('baz', $params['master']['dbname']);
170
        self::assertEquals('baz_slave', $params['slaves']['slave1']['dbname']);
171
    }
172
173
    public function testDatabaseUrlShard()
174
    {
175
        $options = [
176
            'driver' => 'pdo_mysql',
177
            'shardChoser' => MultiTenantShardChoser::class,
178
            'global' => ['url' => 'mysql://foo:bar@localhost:11211/baz'],
179
            'shards' => [
180
                [
181
                    'id' => 1,
182
                    'url' => 'mysql://foo:bar@localhost:11211/baz_slave',
183
                ],
184
            ],
185
            'wrapperClass' => PoolingShardConnection::class,
186
        ];
187
188
        $conn = DriverManager::getConnection($options);
189
190
        $params = $conn->getParams();
191
        self::assertInstanceOf(PDOMySQLDriver::class, $conn->getDriver());
192
193
        $expected = [
194
            'user'     => 'foo',
195
            'password' => 'bar',
196
            'host'     => 'localhost',
197
            'port'     => 11211,
198
        ];
199
200
        foreach ($expected as $key => $value) {
201
            self::assertEquals($value, $params['global'][$key]);
202
            self::assertEquals($value, $params['shards'][0][$key]);
203
        }
204
205
        self::assertEquals('baz', $params['global']['dbname']);
206
        self::assertEquals('baz_slave', $params['shards'][0]['dbname']);
207
    }
208
209
    /**
210
     * @dataProvider databaseUrls
211
     */
212
    public function testDatabaseUrl($url, $expected)
213
    {
214
        $options = is_array($url) ? $url : ['url' => $url];
215
216
        if (isset($options['pdo'])) {
217
            if (! extension_loaded('pdo')) {
218
                $this->markTestSkipped('PDO is not installed');
219
            }
220
221
            $options['pdo'] = $this->createMock(PDO::class);
222
        }
223
224
        $options = is_array($url) ? $url : ['url' => $url];
225
226
        if ($expected === false) {
227
            $this->expectException(DBALException::class);
228
        }
229
230
        $conn = DriverManager::getConnection($options);
231
232
        $params = $conn->getParams();
233
        foreach ($expected as $key => $value) {
234
            if (in_array($key, ['pdo', 'driver', 'driverClass'], true)) {
235
                self::assertInstanceOf($value, $conn->getDriver());
236
            } else {
237
                self::assertEquals($value, $params[$key]);
238
            }
239
        }
240
    }
241
242
    public function databaseUrls()
243
    {
244
        $driver      = $this->createMock(Driver::class);
245
        $driverClass = get_class($driver);
246
247
        return [
248
            'simple URL' => [
249
                'mysql://foo:bar@localhost/baz',
250
                [
251
                    'user'     => 'foo',
252
                    'password' => 'bar',
253
                    'host'     => 'localhost',
254
                    'dbname'   => 'baz',
255
                    'driver'   => PDOMySQLDriver::class,
256
                ],
257
            ],
258
            'simple URL with port' => [
259
                'mysql://foo:bar@localhost:11211/baz',
260
                [
261
                    'user'     => 'foo',
262
                    'password' => 'bar',
263
                    'host'     => 'localhost',
264
                    'port'     => 11211,
265
                    'dbname'   => 'baz',
266
                    'driver'   => PDOMySQLDriver::class,
267
                ],
268
            ],
269
            'sqlite relative URL with host' => [
270
                'sqlite://localhost/foo/dbname.sqlite',
271
                [
272
                    'path'   => 'foo/dbname.sqlite',
273
                    'driver' => PDOSqliteDriver::class,
274
                ],
275
            ],
276
            'sqlite absolute URL with host' => [
277
                'sqlite://localhost//tmp/dbname.sqlite',
278
                [
279
                    'path'   => '/tmp/dbname.sqlite',
280
                    'driver' => PDOSqliteDriver::class,
281
                ],
282
            ],
283
            'sqlite relative URL without host' => [
284
                'sqlite:///foo/dbname.sqlite',
285
                [
286
                    'path'   => 'foo/dbname.sqlite',
287
                    'driver' => PDOSqliteDriver::class,
288
                ],
289
            ],
290
            'sqlite absolute URL without host' => [
291
                'sqlite:////tmp/dbname.sqlite',
292
                [
293
                    'path'   => '/tmp/dbname.sqlite',
294
                    'driver' => PDOSqliteDriver::class,
295
                ],
296
            ],
297
            'sqlite memory' => [
298
                'sqlite:///:memory:',
299
                [
300
                    'memory' => true,
301
                    'driver' => PDOSqliteDriver::class,
302
                ],
303
            ],
304
            'sqlite memory with host' => [
305
                'sqlite://localhost/:memory:',
306
                [
307
                    'memory' => true,
308
                    'driver' => PDOSqliteDriver::class,
309
                ],
310
            ],
311
            'params parsed from URL override individual params' => [
312
                [
313
                    'url'      => 'mysql://foo:bar@localhost/baz',
314
                    'password' => 'lulz',
315
                ],
316
                [
317
                    'user'     => 'foo',
318
                    'password' => 'bar',
319
                    'host'     => 'localhost',
320
                    'dbname'   => 'baz',
321
                    'driver'   => PDOMySQLDriver::class,
322
                ],
323
            ],
324
            'params not parsed from URL but individual params are preserved' => [
325
                [
326
                    'url'  => 'mysql://foo:bar@localhost/baz',
327
                    'port' => 1234,
328
                ],
329
                [
330
                    'user'     => 'foo',
331
                    'password' => 'bar',
332
                    'host'     => 'localhost',
333
                    'port'     => 1234,
334
                    'dbname'   => 'baz',
335
                    'driver'   => PDOMySQLDriver::class,
336
                ],
337
            ],
338
            'query params from URL are used as extra params' => [
339
                'url' => 'mysql://foo:bar@localhost/dbname?charset=UTF-8',
340
                ['charset' => 'UTF-8'],
341
            ],
342
            'simple URL with fallthrough scheme not defined in map' => [
343
                'sqlsrv://foo:bar@localhost/baz',
344
                [
345
                    'user'     => 'foo',
346
                    'password' => 'bar',
347
                    'host'     => 'localhost',
348
                    'dbname'   => 'baz',
349
                    'driver'   => SQLSrvDriver::class,
350
                ],
351
            ],
352
            'simple URL with fallthrough scheme containing underscores fails' => [
353
                'pdo_mysql://foo:bar@localhost/baz',
354
                false,
355
            ],
356
            'simple URL with fallthrough scheme containing dashes works' => [
357
                'pdo-mysql://foo:bar@localhost/baz',
358
                [
359
                    'user'     => 'foo',
360
                    'password' => 'bar',
361
                    'host'     => 'localhost',
362
                    'dbname'   => 'baz',
363
                    'driver'   => PDOMySQLDriver::class,
364
                ],
365
            ],
366
            'simple URL with percent encoding' => [
367
                'mysql://foo%3A:bar%2F@localhost/baz+baz%40',
368
                [
369
                    'user'     => 'foo:',
370
                    'password' => 'bar/',
371
                    'host'     => 'localhost',
372
                    'dbname'   => 'baz+baz@',
373
                    'driver'   => PDOMySQLDriver::class,
374
                ],
375
            ],
376
            'simple URL with percent sign in password' => [
377
                'mysql://foo:bar%25bar@localhost/baz',
378
                [
379
                    'user'     => 'foo',
380
                    'password' => 'bar%bar',
381
                    'host'     => 'localhost',
382
                    'dbname'   => 'baz',
383
                    'driver'   => PDOMySQLDriver::class,
384
                ],
385
            ],
386
387
            // DBAL-1234
388
            'URL without scheme and without any driver information' => [
389
                ['url' => '//foo:bar@localhost/baz'],
390
                false,
391
            ],
392
            'URL without scheme but default PDO driver' => [
393
                [
394
                    'url' => '//foo:bar@localhost/baz',
395
                    'pdo' => true,
396
                ],
397
                false,
398
            ],
399
            'URL without scheme but default driver' => [
400
                [
401
                    'url'    => '//foo:bar@localhost/baz',
402
                    'driver' => 'pdo_mysql',
403
                ],
404
                [
405
                    'user'     => 'foo',
406
                    'password' => 'bar',
407
                    'host'     => 'localhost',
408
                    'dbname'   => 'baz',
409
                    'driver'   => PDOMySQLDriver::class,
410
                ],
411
            ],
412
            'URL without scheme but custom driver' => [
413
                [
414
                    'url'         => '//foo:bar@localhost/baz',
415
                    'driverClass' => $driverClass,
416
                ],
417
                [
418
                    'user'        => 'foo',
419
                    'password'    => 'bar',
420
                    'host'        => 'localhost',
421
                    'dbname'      => 'baz',
422
                    'driverClass' => $driverClass,
423
                ],
424
            ],
425
            'URL without scheme but default PDO driver and default driver' => [
426
                [
427
                    'url'    => '//foo:bar@localhost/baz',
428
                    'pdo'    => true,
429
                    'driver' => 'pdo_mysql',
430
                ],
431
                [
432
                    'user'     => 'foo',
433
                    'password' => 'bar',
434
                    'host'     => 'localhost',
435
                    'dbname'   => 'baz',
436
                    'driver'   => PDOMySQLDriver::class,
437
                ],
438
            ],
439
            'URL without scheme but driver and custom driver' => [
440
                [
441
                    'url'         => '//foo:bar@localhost/baz',
442
                    'driver'      => 'pdo_mysql',
443
                    'driverClass' => $driverClass,
444
                ],
445
                [
446
                    'user'        => 'foo',
447
                    'password'    => 'bar',
448
                    'host'        => 'localhost',
449
                    'dbname'      => 'baz',
450
                    'driverClass' => $driverClass,
451
                ],
452
            ],
453
            'URL with default PDO driver' => [
454
                [
455
                    'url' => 'mysql://foo:bar@localhost/baz',
456
                    'pdo' => true,
457
                ],
458
                [
459
                    'user'     => 'foo',
460
                    'password' => 'bar',
461
                    'host'     => 'localhost',
462
                    'dbname'   => 'baz',
463
                    'driver'   => PDOMySQLDriver::class,
464
                ],
465
            ],
466
            'URL with default driver' => [
467
                [
468
                    'url'    => 'mysql://foo:bar@localhost/baz',
469
                    'driver' => 'sqlite',
470
                ],
471
                [
472
                    'user'     => 'foo',
473
                    'password' => 'bar',
474
                    'host'     => 'localhost',
475
                    'dbname'   => 'baz',
476
                    'driver'   => PDOMySQLDriver::class,
477
                ],
478
            ],
479
            'URL with default custom driver' => [
480
                [
481
                    'url'         => 'mysql://foo:bar@localhost/baz',
482
                    'driverClass' => $driverClass,
483
                ],
484
                [
485
                    'user'     => 'foo',
486
                    'password' => 'bar',
487
                    'host'     => 'localhost',
488
                    'dbname'   => 'baz',
489
                    'driver'   => PDOMySQLDriver::class,
490
                ],
491
            ],
492
            'URL with default PDO driver and default driver' => [
493
                [
494
                    'url'    => 'mysql://foo:bar@localhost/baz',
495
                    'pdo'    => true,
496
                    'driver' => 'sqlite',
497
                ],
498
                [
499
                    'user'     => 'foo',
500
                    'password' => 'bar',
501
                    'host'     => 'localhost',
502
                    'dbname'   => 'baz',
503
                    'driver'   => PDOMySQLDriver::class,
504
                ],
505
            ],
506
            'URL with default driver and default custom driver' => [
507
                [
508
                    'url'         => 'mysql://foo:bar@localhost/baz',
509
                    'driver'      => 'sqlite',
510
                    'driverClass' => $driverClass,
511
                ],
512
                [
513
                    'user'     => 'foo',
514
                    'password' => 'bar',
515
                    'host'     => 'localhost',
516
                    'dbname'   => 'baz',
517
                    'driver'   => PDOMySQLDriver::class,
518
                ],
519
            ],
520
            'URL with default PDO driver and default driver and default custom driver' => [
521
                [
522
                    'url'         => 'mysql://foo:bar@localhost/baz',
523
                    'pdo'         => true,
524
                    'driver'      => 'sqlite',
525
                    'driverClass' => $driverClass,
526
                ],
527
                [
528
                    'user'     => 'foo',
529
                    'password' => 'bar',
530
                    'host'     => 'localhost',
531
                    'dbname'   => 'baz',
532
                    'driver'   => PDOMySQLDriver::class,
533
                ],
534
            ],
535
        ];
536
    }
537
}
538