Failed Conditions
Push — master ( ac0e13...24dbc4 )
by Sergei
22s queued 15s
created

ConnectionTest   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 831
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 413
dl 0
loc 831
rs 9.36
c 2
b 0
f 0
wmc 38

38 Methods

Rating   Name   Duplication   Size   Complexity  
A testUpdateWithDifferentColumnsInDataAndIdentifiers() 0 37 1
A testSetRollbackOnlyNoActiveTransactionThrowsException() 0 4 1
A testFetchAssoc() 0 34 1
A testUpdateWithIsNull() 0 35 1
A testEmptyInsert() 0 9 1
A testFetchArray() 0 34 1
A testCallConnectOnce() 0 12 1
A testCommitWithNoActiveTransactionThrowsException() 0 4 1
A testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() 0 8 1
A testEventManagerPassedToPlatform() 0 18 1
A testIsAutoCommit() 0 3 1
A getExecuteUpdateMockConnection() 0 16 1
A testIsRollbackOnlyNoActiveTransactionThrowsException() 0 4 1
A testFetchAll() 0 33 1
A testGetDriver() 0 3 1
A testDebugSQLStack() 0 5 1
A testNoTransactionActiveByDefault() 0 3 1
A testDeleteWithIsNull() 0 21 1
A testUpdateWithSameColumnInDataAndIdentifiers() 0 36 1
A testCommitStartsTransactionInNoAutoCommitMode() 0 15 1
A testShouldNotPassPlatformInParamsToTheQueryCacheProfileInExecuteCacheQuery() 0 34 1
A testConnectionParamsArePassedToTheQueryCacheProfileInExecuteCacheQuery() 0 35 1
A setUp() 0 3 1
A resultProvider() 0 3 1
A testConnectStartsTransactionInNoAutoCommitMode() 0 17 1
A testExecuteCacheQueryStripsPlatformFromConnectionParamsBeforeGeneratingCacheKeys() 0 46 1
A testRollBackStartsTransactionInNoAutoCommitMode() 0 15 1
A testRethrowsOriginalExceptionOnDeterminingPlatformWhenConnectingToNonExistentDatabase() 0 20 1
A testFetchColumn() 0 35 1
A testSwitchingAutoCommitModeCommitsAllCurrentTransactions() 0 22 1
A testIsConnected() 0 3 1
A testThrowsExceptionWhenInValidPlatformSpecified() 0 11 1
A testPlatformDetectionIsTriggerOnlyOnceOnRetrievingPlatform() 0 27 1
A testConnectDispatchEvent() 0 16 1
A getQueryMethods() 0 29 1
A testDriverExceptionIsWrapped() 0 11 1
A testSetAutoCommit() 0 4 1
A testRollbackWithNoActiveTransactionThrowsException() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Tests;
6
7
use Doctrine\Common\Cache\Cache;
8
use Doctrine\Common\EventManager;
9
use Doctrine\DBAL\Cache\ArrayStatement;
10
use Doctrine\DBAL\Cache\QueryCacheProfile;
11
use Doctrine\DBAL\Configuration;
12
use Doctrine\DBAL\Connection;
13
use Doctrine\DBAL\ConnectionException;
14
use Doctrine\DBAL\DBALException;
15
use Doctrine\DBAL\Driver;
16
use Doctrine\DBAL\Driver\Connection as DriverConnection;
17
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
18
use Doctrine\DBAL\Driver\Statement;
19
use Doctrine\DBAL\DriverManager;
20
use Doctrine\DBAL\Events;
21
use Doctrine\DBAL\Exception\InvalidArgumentException;
22
use Doctrine\DBAL\FetchMode;
23
use Doctrine\DBAL\Logging\DebugStack;
24
use Doctrine\DBAL\ParameterType;
25
use Doctrine\DBAL\Platforms\AbstractPlatform;
26
use Doctrine\DBAL\VersionAwarePlatformDriver;
27
use Exception;
28
use PHPUnit\Framework\MockObject\MockObject;
29
use PHPUnit\Framework\TestCase;
30
use stdClass;
31
32
/**
33
 * @requires extension pdo_mysql
34
 */
35
class ConnectionTest extends TestCase
36
{
37
    /** @var Connection */
38
    private $connection;
39
40
    /** @var array<string, mixed> */
41
    protected $params = [
42
        'driver' => 'pdo_mysql',
43
        'host' => 'localhost',
44
        'user' => 'root',
45
        'password' => 'password',
46
        'port' => 1234,
47
    ];
48
49
    protected function setUp() : void
50
    {
51
        $this->connection = DriverManager::getConnection($this->params);
52
    }
53
54
    /**
55
     * @return Connection|MockObject
56
     */
57
    private function getExecuteUpdateMockConnection()
58
    {
59
        $driverMock = $this->createMock(Driver::class);
60
61
        $driverMock->expects(self::any())
62
            ->method('connect')
63
            ->will(self::returnValue(
64
                $this->createMock(DriverConnection::class)
65
            ));
66
67
        $platform = $this->getMockForAbstractClass(AbstractPlatform::class);
68
69
        return $this->getMockBuilder(Connection::class)
70
            ->onlyMethods(['executeUpdate'])
71
            ->setConstructorArgs([['platform' => $platform], $driverMock])
72
            ->getMock();
73
    }
74
75
    public function testIsConnected() : void
76
    {
77
        self::assertFalse($this->connection->isConnected());
78
    }
79
80
    public function testNoTransactionActiveByDefault() : void
81
    {
82
        self::assertFalse($this->connection->isTransactionActive());
83
    }
84
85
    public function testCommitWithNoActiveTransactionThrowsException() : void
86
    {
87
        $this->expectException(ConnectionException::class);
88
        $this->connection->commit();
89
    }
90
91
    public function testRollbackWithNoActiveTransactionThrowsException() : void
92
    {
93
        $this->expectException(ConnectionException::class);
94
        $this->connection->rollBack();
95
    }
96
97
    public function testSetRollbackOnlyNoActiveTransactionThrowsException() : void
98
    {
99
        $this->expectException(ConnectionException::class);
100
        $this->connection->setRollbackOnly();
101
    }
102
103
    public function testIsRollbackOnlyNoActiveTransactionThrowsException() : void
104
    {
105
        $this->expectException(ConnectionException::class);
106
        $this->connection->isRollbackOnly();
107
    }
108
109
    public function testGetDriver() : void
110
    {
111
        self::assertInstanceOf(\Doctrine\DBAL\Driver\PDOMySql\Driver::class, $this->connection->getDriver());
112
    }
113
114
    public function testConnectDispatchEvent() : void
115
    {
116
        $listenerMock = $this->getMockBuilder($this->getMockClass('ConnectDispatchEventListener'))
117
            ->addMethods(['postConnect'])
118
            ->getMock();
119
        $listenerMock->expects(self::once())->method('postConnect');
120
121
        $eventManager = new EventManager();
122
        $eventManager->addEventListener([Events::postConnect], $listenerMock);
123
124
        $driverMock = $this->createMock(Driver::class);
125
        $driverMock->expects(self::at(0))
126
                   ->method('connect');
127
128
        $conn = new Connection([], $driverMock, new Configuration(), $eventManager);
129
        $conn->connect();
130
    }
131
132
    public function testEventManagerPassedToPlatform() : void
133
    {
134
        $eventManager = new EventManager();
135
136
        /** @var AbstractPlatform|MockObject $platform */
137
        $platform = $this->createMock(AbstractPlatform::class);
138
        $platform->expects(self::once())
139
            ->method('setEventManager')
140
            ->with($eventManager);
141
142
        /** @var Driver|MockObject $driver */
143
        $driver = $this->createMock(Driver::class);
144
        $driver->expects(self::any())
145
            ->method('getDatabasePlatform')
146
            ->willReturn($platform);
147
148
        $connection = new Connection($this->params, $driver, null, $eventManager);
149
        $connection->getDatabasePlatform();
150
    }
151
152
    /**
153
     * @requires extension pdo_sqlite
154
     * @dataProvider getQueryMethods
155
     */
156
    public function testDriverExceptionIsWrapped(callable $callback) : void
157
    {
158
        $this->expectException(DBALException::class);
159
        $this->expectExceptionMessage("An exception occurred while executing \"MUUHAAAAHAAAA\":\n\nSQLSTATE[HY000]: General error: 1 near \"MUUHAAAAHAAAA\"");
160
161
        $connection = DriverManager::getConnection([
162
            'driver' => 'pdo_sqlite',
163
            'memory' => true,
164
        ]);
165
166
        $callback($connection, 'MUUHAAAAHAAAA');
167
    }
168
169
    /**
170
     * @return iterable<string, array<int, callable>>
171
     */
172
    public static function getQueryMethods() : iterable
173
    {
174
        yield 'exec' => [
175
            static function (Connection $connection, string $statement) : void {
176
                $connection->exec($statement);
177
            },
178
        ];
179
180
        yield 'query' => [
181
            static function (Connection $connection, string $statement) : void {
182
                $connection->query($statement);
183
            },
184
        ];
185
186
        yield 'executeQuery' => [
187
            static function (Connection $connection, string $statement) : void {
188
                $connection->executeQuery($statement);
189
            },
190
        ];
191
192
        yield 'executeUpdate' => [
193
            static function (Connection $connection, string $statement) : void {
194
                $connection->executeUpdate($statement);
195
            },
196
        ];
197
198
        yield 'prepare' => [
199
            static function (Connection $connection, string $statement) : void {
200
                $connection->prepare($statement);
201
            },
202
        ];
203
    }
204
205
    /**
206
     * Pretty dumb test, however we want to check that the DebugStack correctly implements the interface.
207
     *
208
     * @group DBAL-11
209
     */
210
    public function testDebugSQLStack() : void
211
    {
212
        $logger = new DebugStack();
213
        $this->connection->getConfiguration()->setSQLLogger($logger);
214
        self::assertSame($logger, $this->connection->getConfiguration()->getSQLLogger());
215
    }
216
217
    /**
218
     * @group DBAL-81
219
     */
220
    public function testIsAutoCommit() : void
221
    {
222
        self::assertTrue($this->connection->isAutoCommit());
223
    }
224
225
    /**
226
     * @group DBAL-81
227
     */
228
    public function testSetAutoCommit() : void
229
    {
230
        $this->connection->setAutoCommit(false);
231
        self::assertFalse($this->connection->isAutoCommit());
232
    }
233
234
    /**
235
     * @group DBAL-81
236
     */
237
    public function testConnectStartsTransactionInNoAutoCommitMode() : void
238
    {
239
        $driverMock = $this->createMock(Driver::class);
240
        $driverMock->expects(self::any())
241
            ->method('connect')
242
            ->will(self::returnValue(
243
                $this->createMock(DriverConnection::class)
244
            ));
245
        $conn = new Connection([], $driverMock);
246
247
        $conn->setAutoCommit(false);
248
249
        self::assertFalse($conn->isTransactionActive());
250
251
        $conn->connect();
252
253
        self::assertTrue($conn->isTransactionActive());
254
    }
255
256
    /**
257
     * @group DBAL-81
258
     */
259
    public function testCommitStartsTransactionInNoAutoCommitMode() : void
260
    {
261
        $driverMock = $this->createMock(Driver::class);
262
        $driverMock->expects(self::any())
263
            ->method('connect')
264
            ->will(self::returnValue(
265
                $this->createMock(DriverConnection::class)
266
            ));
267
        $conn = new Connection([], $driverMock);
268
269
        $conn->setAutoCommit(false);
270
        $conn->connect();
271
        $conn->commit();
272
273
        self::assertTrue($conn->isTransactionActive());
274
    }
275
276
    /**
277
     * @return bool[][]
278
     */
279
    public function resultProvider() : array
280
    {
281
        return [[true], [false]];
282
    }
283
284
    /**
285
     * @group DBAL-81
286
     */
287
    public function testRollBackStartsTransactionInNoAutoCommitMode() : void
288
    {
289
        $driverMock = $this->createMock(Driver::class);
290
        $driverMock->expects(self::any())
291
            ->method('connect')
292
            ->will(self::returnValue(
293
                $this->createMock(DriverConnection::class)
294
            ));
295
        $conn = new Connection([], $driverMock);
296
297
        $conn->setAutoCommit(false);
298
        $conn->connect();
299
        $conn->rollBack();
300
301
        self::assertTrue($conn->isTransactionActive());
302
    }
303
304
    /**
305
     * @group DBAL-81
306
     */
307
    public function testSwitchingAutoCommitModeCommitsAllCurrentTransactions() : void
308
    {
309
        $driverMock = $this->createMock(Driver::class);
310
        $driverMock->expects(self::any())
311
            ->method('connect')
312
            ->will(self::returnValue(
313
                $this->createMock(DriverConnection::class)
314
            ));
315
        $conn = new Connection([], $driverMock);
316
317
        $conn->connect();
318
        $conn->beginTransaction();
319
        $conn->beginTransaction();
320
        $conn->setAutoCommit(false);
321
322
        self::assertSame(1, $conn->getTransactionNestingLevel());
323
324
        $conn->beginTransaction();
325
        $conn->beginTransaction();
326
        $conn->setAutoCommit(true);
327
328
        self::assertFalse($conn->isTransactionActive());
329
    }
330
331
    public function testEmptyInsert() : void
332
    {
333
        $conn = $this->getExecuteUpdateMockConnection();
334
335
        $conn->expects(self::once())
336
            ->method('executeUpdate')
337
            ->with('INSERT INTO footable () VALUES ()');
338
339
        $conn->insert('footable', []);
340
    }
341
342
    /**
343
     * @group DBAL-2511
344
     */
345
    public function testUpdateWithDifferentColumnsInDataAndIdentifiers() : void
346
    {
347
        $conn = $this->getExecuteUpdateMockConnection();
348
349
        $conn->expects(self::once())
350
            ->method('executeUpdate')
351
            ->with(
352
                'UPDATE TestTable SET text = ?, is_edited = ? WHERE id = ? AND name = ?',
353
                [
354
                    'some text',
355
                    true,
356
                    1,
357
                    'foo',
358
                ],
359
                [
360
                    'string',
361
                    'boolean',
362
                    'integer',
363
                    'string',
364
                ]
365
            );
366
367
        $conn->update(
368
            'TestTable',
369
            [
370
                'text' => 'some text',
371
                'is_edited' => true,
372
            ],
373
            [
374
                'id' => 1,
375
                'name' => 'foo',
376
            ],
377
            [
378
                'text' => 'string',
379
                'is_edited' => 'boolean',
380
                'id' => 'integer',
381
                'name' => 'string',
382
            ]
383
        );
384
    }
385
386
    /**
387
     * @group DBAL-2511
388
     */
389
    public function testUpdateWithSameColumnInDataAndIdentifiers() : void
390
    {
391
        $conn = $this->getExecuteUpdateMockConnection();
392
393
        $conn->expects(self::once())
394
            ->method('executeUpdate')
395
            ->with(
396
                'UPDATE TestTable SET text = ?, is_edited = ? WHERE id = ? AND is_edited = ?',
397
                [
398
                    'some text',
399
                    true,
400
                    1,
401
                    false,
402
                ],
403
                [
404
                    'string',
405
                    'boolean',
406
                    'integer',
407
                    'boolean',
408
                ]
409
            );
410
411
        $conn->update(
412
            'TestTable',
413
            [
414
                'text' => 'some text',
415
                'is_edited' => true,
416
            ],
417
            [
418
                'id' => 1,
419
                'is_edited' => false,
420
            ],
421
            [
422
                'text' => 'string',
423
                'is_edited' => 'boolean',
424
                'id' => 'integer',
425
            ]
426
        );
427
    }
428
429
    /**
430
     * @group DBAL-2688
431
     */
432
    public function testUpdateWithIsNull() : void
433
    {
434
        $conn = $this->getExecuteUpdateMockConnection();
435
436
        $conn->expects(self::once())
437
            ->method('executeUpdate')
438
            ->with(
439
                'UPDATE TestTable SET text = ?, is_edited = ? WHERE id IS NULL AND name = ?',
440
                [
441
                    'some text',
442
                    null,
443
                    'foo',
444
                ],
445
                [
446
                    'string',
447
                    'boolean',
448
                    'string',
449
                ]
450
            );
451
452
        $conn->update(
453
            'TestTable',
454
            [
455
                'text' => 'some text',
456
                'is_edited' => null,
457
            ],
458
            [
459
                'id' => null,
460
                'name' => 'foo',
461
            ],
462
            [
463
                'text' => 'string',
464
                'is_edited' => 'boolean',
465
                'id' => 'integer',
466
                'name' => 'string',
467
            ]
468
        );
469
    }
470
471
    /**
472
     * @group DBAL-2688
473
     */
474
    public function testDeleteWithIsNull() : void
475
    {
476
        $conn = $this->getExecuteUpdateMockConnection();
477
478
        $conn->expects(self::once())
479
            ->method('executeUpdate')
480
            ->with(
481
                'DELETE FROM TestTable WHERE id IS NULL AND name = ?',
482
                ['foo'],
483
                ['string']
484
            );
485
486
        $conn->delete(
487
            'TestTable',
488
            [
489
                'id' => null,
490
                'name' => 'foo',
491
            ],
492
            [
493
                'id' => 'integer',
494
                'name' => 'string',
495
            ]
496
        );
497
    }
498
499
    public function testFetchAssoc() : void
500
    {
501
        $statement = 'SELECT * FROM foo WHERE bar = ?';
502
        $params    = [666];
503
        $types     = [ParameterType::INTEGER];
504
        $result    = [];
505
506
        $driverMock = $this->createMock(Driver::class);
507
508
        $driverMock->expects(self::any())
509
            ->method('connect')
510
            ->will(self::returnValue(
511
                $this->createMock(DriverConnection::class)
512
            ));
513
514
        $driverStatementMock = $this->createMock(Statement::class);
515
516
        $driverStatementMock->expects(self::once())
517
            ->method('fetch')
518
            ->with(FetchMode::ASSOCIATIVE)
519
            ->will(self::returnValue($result));
520
521
        /** @var Connection|MockObject $conn */
522
        $conn = $this->getMockBuilder(Connection::class)
523
            ->onlyMethods(['executeQuery'])
524
            ->setConstructorArgs([[], $driverMock])
525
            ->getMock();
526
527
        $conn->expects(self::once())
528
            ->method('executeQuery')
529
            ->with($statement, $params, $types)
530
            ->will(self::returnValue($driverStatementMock));
531
532
        self::assertSame($result, $conn->fetchAssoc($statement, $params, $types));
533
    }
534
535
    public function testFetchArray() : void
536
    {
537
        $statement = 'SELECT * FROM foo WHERE bar = ?';
538
        $params    = [666];
539
        $types     = [ParameterType::INTEGER];
540
        $result    = [];
541
542
        $driverMock = $this->createMock(Driver::class);
543
544
        $driverMock->expects(self::any())
545
            ->method('connect')
546
            ->will(self::returnValue(
547
                $this->createMock(DriverConnection::class)
548
            ));
549
550
        $driverStatementMock = $this->createMock(Statement::class);
551
552
        $driverStatementMock->expects(self::once())
553
            ->method('fetch')
554
            ->with(FetchMode::NUMERIC)
555
            ->will(self::returnValue($result));
556
557
        /** @var Connection|MockObject $conn */
558
        $conn = $this->getMockBuilder(Connection::class)
559
            ->onlyMethods(['executeQuery'])
560
            ->setConstructorArgs([[], $driverMock])
561
            ->getMock();
562
563
        $conn->expects(self::once())
564
            ->method('executeQuery')
565
            ->with($statement, $params, $types)
566
            ->will(self::returnValue($driverStatementMock));
567
568
        self::assertSame($result, $conn->fetchArray($statement, $params, $types));
569
    }
570
571
    public function testFetchColumn() : void
572
    {
573
        $statement = 'SELECT * FROM foo WHERE bar = ?';
574
        $params    = [666];
575
        $types     = [ParameterType::INTEGER];
576
        $column    = 0;
577
        $result    = [];
578
579
        $driverMock = $this->createMock(Driver::class);
580
581
        $driverMock->expects(self::any())
582
            ->method('connect')
583
            ->will(self::returnValue(
584
                $this->createMock(DriverConnection::class)
585
            ));
586
587
        $driverStatementMock = $this->createMock(Statement::class);
588
589
        $driverStatementMock->expects(self::once())
590
            ->method('fetchColumn')
591
            ->with($column)
592
            ->will(self::returnValue($result));
593
594
        /** @var Connection|MockObject $conn */
595
        $conn = $this->getMockBuilder(Connection::class)
596
            ->onlyMethods(['executeQuery'])
597
            ->setConstructorArgs([[], $driverMock])
598
            ->getMock();
599
600
        $conn->expects(self::once())
601
            ->method('executeQuery')
602
            ->with($statement, $params, $types)
603
            ->will(self::returnValue($driverStatementMock));
604
605
        self::assertSame($result, $conn->fetchColumn($statement, $params, $column, $types));
606
    }
607
608
    public function testFetchAll() : void
609
    {
610
        $statement = 'SELECT * FROM foo WHERE bar = ?';
611
        $params    = [666];
612
        $types     = [ParameterType::INTEGER];
613
        $result    = [];
614
615
        $driverMock = $this->createMock(Driver::class);
616
617
        $driverMock->expects(self::any())
618
            ->method('connect')
619
            ->will(self::returnValue(
620
                $this->createMock(DriverConnection::class)
621
            ));
622
623
        $driverStatementMock = $this->createMock(Statement::class);
624
625
        $driverStatementMock->expects(self::once())
626
            ->method('fetchAll')
627
            ->will(self::returnValue($result));
628
629
        /** @var Connection|MockObject $conn */
630
        $conn = $this->getMockBuilder(Connection::class)
631
            ->onlyMethods(['executeQuery'])
632
            ->setConstructorArgs([[], $driverMock])
633
            ->getMock();
634
635
        $conn->expects(self::once())
636
            ->method('executeQuery')
637
            ->with($statement, $params, $types)
638
            ->will(self::returnValue($driverStatementMock));
639
640
        self::assertSame($result, $conn->fetchAll($statement, $params, $types));
641
    }
642
643
    public function testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() : void
644
    {
645
        /** @var Driver $driver */
646
        $driver = $this->createMock(Driver::class);
647
        $conn   = new Connection([], $driver);
648
649
        $this->expectException(InvalidArgumentException::class);
650
        $conn->delete('kittens', []);
651
    }
652
653
    public function testCallConnectOnce() : void
654
    {
655
        /** @var Driver|MockObject $driver */
656
        $driver = $this->createMock(Driver::class);
657
        $driver->expects(self::once())
658
            ->method('connect');
659
660
        $platform = $this->createMock(AbstractPlatform::class);
661
662
        $conn = new Connection(['platform' => $platform], $driver);
663
        $conn->connect();
664
        $conn->connect();
665
    }
666
667
    /**
668
     * @group DBAL-1127
669
     */
670
    public function testPlatformDetectionIsTriggerOnlyOnceOnRetrievingPlatform() : void
671
    {
672
        /** @var VersionAwarePlatformDriver|MockObject $driverMock */
673
        $driverMock = $this->createMock(VersionAwarePlatformDriver::class);
674
675
        /** @var DriverConnection|ServerInfoAwareConnection|MockObject $driverConnectionMock */
676
        $driverConnectionMock = $this->createMock(ServerInfoAwareConnection::class);
677
678
        /** @var AbstractPlatform|MockObject $platformMock */
679
        $platformMock = $this->getMockForAbstractClass(AbstractPlatform::class);
680
681
        $connection = new Connection([], $driverMock);
682
683
        $driverMock->expects(self::once())
684
            ->method('connect')
685
            ->will(self::returnValue($driverConnectionMock));
686
687
        $driverConnectionMock->expects(self::once())
688
            ->method('getServerVersion')
689
            ->will(self::returnValue('6.6.6'));
690
691
        $driverMock->expects(self::once())
692
            ->method('createDatabasePlatformForVersion')
693
            ->with('6.6.6')
694
            ->will(self::returnValue($platformMock));
695
696
        self::assertSame($platformMock, $connection->getDatabasePlatform());
697
    }
698
699
    public function testConnectionParamsArePassedToTheQueryCacheProfileInExecuteCacheQuery() : void
700
    {
701
        $resultCacheDriverMock = $this->createMock(Cache::class);
702
703
        $resultCacheDriverMock
704
            ->expects(self::atLeastOnce())
705
            ->method('fetch')
706
            ->with('cacheKey')
707
            ->will(self::returnValue(['realKey' => []]));
708
709
        $query  = 'SELECT * FROM foo WHERE bar = ?';
710
        $params = [666];
711
        $types  = [ParameterType::INTEGER];
712
713
        /** @var QueryCacheProfile|MockObject $queryCacheProfileMock */
714
        $queryCacheProfileMock = $this->createMock(QueryCacheProfile::class);
715
716
        $queryCacheProfileMock
717
            ->expects(self::any())
718
            ->method('getResultCacheDriver')
719
            ->will(self::returnValue($resultCacheDriverMock));
720
721
        // This is our main expectation
722
        $queryCacheProfileMock
723
            ->expects(self::once())
724
            ->method('generateCacheKeys')
725
            ->with($query, $params, $types, $this->params)
726
            ->will(self::returnValue(['cacheKey', 'realKey']));
727
728
        /** @var Driver $driver */
729
        $driver = $this->createMock(Driver::class);
730
731
        self::assertInstanceOf(
732
            ArrayStatement::class,
733
            (new Connection($this->params, $driver))->executeCacheQuery($query, $params, $types, $queryCacheProfileMock)
734
        );
735
    }
736
737
    /**
738
     * @group #2821
739
     */
740
    public function testShouldNotPassPlatformInParamsToTheQueryCacheProfileInExecuteCacheQuery() : void
741
    {
742
        $resultCacheDriverMock = $this->createMock(Cache::class);
743
744
        $resultCacheDriverMock
745
            ->expects(self::atLeastOnce())
746
            ->method('fetch')
747
            ->with('cacheKey')
748
            ->will(self::returnValue(['realKey' => []]));
749
750
        /** @var QueryCacheProfile|MockObject $queryCacheProfileMock */
751
        $queryCacheProfileMock = $this->createMock(QueryCacheProfile::class);
752
753
        $queryCacheProfileMock
754
            ->expects(self::any())
755
            ->method('getResultCacheDriver')
756
            ->will(self::returnValue($resultCacheDriverMock));
757
758
        $query = 'SELECT 1';
759
760
        $connectionParams = $this->params;
761
762
        $queryCacheProfileMock
763
            ->expects(self::once())
764
            ->method('generateCacheKeys')
765
            ->with($query, [], [], $connectionParams)
766
            ->will(self::returnValue(['cacheKey', 'realKey']));
767
768
        $connectionParams['platform'] = $this->createMock(AbstractPlatform::class);
769
770
        /** @var Driver $driver */
771
        $driver = $this->createMock(Driver::class);
772
773
        (new Connection($connectionParams, $driver))->executeCacheQuery($query, [], [], $queryCacheProfileMock);
774
    }
775
776
    /**
777
     * @group #2821
778
     */
779
    public function testThrowsExceptionWhenInValidPlatformSpecified() : void
780
    {
781
        $connectionParams             = $this->params;
782
        $connectionParams['platform'] = new stdClass();
783
784
        /** @var Driver $driver */
785
        $driver = $this->createMock(Driver::class);
786
787
        $this->expectException(DBALException::class);
788
789
        new Connection($connectionParams, $driver);
790
    }
791
792
    /**
793
     * @group DBAL-990
794
     */
795
    public function testRethrowsOriginalExceptionOnDeterminingPlatformWhenConnectingToNonExistentDatabase() : void
796
    {
797
        /** @var VersionAwarePlatformDriver|MockObject $driverMock */
798
        $driverMock = $this->createMock(VersionAwarePlatformDriver::class);
799
800
        $connection        = new Connection(['dbname' => 'foo'], $driverMock);
801
        $originalException = new Exception('Original exception');
802
        $fallbackException = new Exception('Fallback exception');
803
804
        $driverMock->expects(self::at(0))
805
            ->method('connect')
806
            ->willThrowException($originalException);
807
808
        $driverMock->expects(self::at(1))
809
            ->method('connect')
810
            ->willThrowException($fallbackException);
811
812
        $this->expectExceptionMessage($originalException->getMessage());
813
814
        $connection->getDatabasePlatform();
815
    }
816
817
    /**
818
     * @group #3194
819
     */
820
    public function testExecuteCacheQueryStripsPlatformFromConnectionParamsBeforeGeneratingCacheKeys() : void
821
    {
822
        /** @var Driver|MockObject $driver */
823
        $driver = $this->createMock(Driver::class);
824
825
        /** @var AbstractPlatform|MockObject $platform */
826
        $platform = $this->createMock(AbstractPlatform::class);
827
828
        /** @var QueryCacheProfile|MockObject $queryCacheProfile */
829
        $queryCacheProfile = $this->createMock(QueryCacheProfile::class);
830
831
        /** @var Cache|MockObject $resultCacheDriver */
832
        $resultCacheDriver = $this->createMock(Cache::class);
833
834
        $queryCacheProfile
835
            ->expects(self::any())
836
            ->method('getResultCacheDriver')
837
            ->will(self::returnValue($resultCacheDriver));
838
839
        $resultCacheDriver
840
            ->expects(self::atLeastOnce())
841
            ->method('fetch')
842
            ->with('cacheKey')
843
            ->will(self::returnValue(['realKey' => []]));
844
845
        $query = 'SELECT 1';
846
847
        $params = [
848
            'dbname' => 'foo',
849
            'platform' => $platform,
850
        ];
851
852
        $paramsWithoutPlatform = $params;
853
        unset($paramsWithoutPlatform['platform']);
854
855
        $queryCacheProfile
856
            ->expects(self::once())
857
            ->method('generateCacheKeys')
858
            ->with($query, [], [], $paramsWithoutPlatform)
859
            ->will(self::returnValue(['cacheKey', 'realKey']));
860
861
        $connection = new Connection($params, $driver);
862
863
        self::assertSame($params, $connection->getParams());
864
865
        $connection->executeCacheQuery($query, [], [], $queryCacheProfile);
866
    }
867
}
868