Completed
Push — 3.0.x ( 8be6d1...8d2aa4 )
by Sergei
25s queued 16s
created

ConnectionTest::testEchoSQLLogger()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Doctrine\DBAL\Tests;
4
5
use Doctrine\Common\Cache\Cache;
6
use Doctrine\Common\EventManager;
7
use Doctrine\DBAL\Cache\ArrayStatement;
8
use Doctrine\DBAL\Cache\QueryCacheProfile;
9
use Doctrine\DBAL\Configuration;
10
use Doctrine\DBAL\Connection;
11
use Doctrine\DBAL\ConnectionException;
12
use Doctrine\DBAL\DBALException;
13
use Doctrine\DBAL\Driver;
14
use Doctrine\DBAL\Driver\Connection as DriverConnection;
15
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
16
use Doctrine\DBAL\Driver\Statement;
17
use Doctrine\DBAL\DriverManager;
18
use Doctrine\DBAL\Events;
19
use Doctrine\DBAL\Exception\InvalidArgumentException;
20
use Doctrine\DBAL\FetchMode;
21
use Doctrine\DBAL\Logging\DebugStack;
22
use Doctrine\DBAL\ParameterType;
23
use Doctrine\DBAL\Platforms\AbstractPlatform;
24
use Doctrine\DBAL\VersionAwarePlatformDriver;
25
use Exception;
26
use PHPUnit\Framework\MockObject\MockObject;
27
use PHPUnit\Framework\TestCase;
28
use stdClass;
29
30
/**
31
 * @requires extension pdo_mysql
32
 */
33
class ConnectionTest extends TestCase
34
{
35
    /** @var Connection */
36
    private $connection;
37
38
    /** @var string[] */
39
    protected $params = [
40
        'driver' => 'pdo_mysql',
41
        'host' => 'localhost',
42
        'user' => 'root',
43
        'password' => 'password',
44
        'port' => '1234',
45
    ];
46
47
    protected function setUp() : void
48
    {
49
        $this->connection = DriverManager::getConnection($this->params);
50
    }
51
52
    /**
53
     * @return Connection|MockObject
54
     */
55
    private function getExecuteUpdateMockConnection()
56
    {
57
        $driverMock = $this->createMock(Driver::class);
58
59
        $driverMock->expects($this->any())
60
            ->method('connect')
61
            ->will($this->returnValue(
62
                $this->createMock(DriverConnection::class)
63
            ));
64
65
        $platform = $this->getMockForAbstractClass(AbstractPlatform::class);
66
67
        return $this->getMockBuilder(Connection::class)
68
            ->onlyMethods(['executeUpdate'])
69
            ->setConstructorArgs([['platform' => $platform], $driverMock])
70
            ->getMock();
71
    }
72
73
    public function testIsConnected() : void
74
    {
75
        self::assertFalse($this->connection->isConnected());
76
    }
77
78
    public function testNoTransactionActiveByDefault() : void
79
    {
80
        self::assertFalse($this->connection->isTransactionActive());
81
    }
82
83
    public function testCommitWithNoActiveTransactionThrowsException() : void
84
    {
85
        $this->expectException(ConnectionException::class);
86
        $this->connection->commit();
87
    }
88
89
    public function testRollbackWithNoActiveTransactionThrowsException() : void
90
    {
91
        $this->expectException(ConnectionException::class);
92
        $this->connection->rollBack();
93
    }
94
95
    public function testSetRollbackOnlyNoActiveTransactionThrowsException() : void
96
    {
97
        $this->expectException(ConnectionException::class);
98
        $this->connection->setRollbackOnly();
99
    }
100
101
    public function testIsRollbackOnlyNoActiveTransactionThrowsException() : void
102
    {
103
        $this->expectException(ConnectionException::class);
104
        $this->connection->isRollbackOnly();
105
    }
106
107
    public function testGetConfiguration() : void
108
    {
109
        $config = $this->connection->getConfiguration();
110
111
        self::assertInstanceOf(Configuration::class, $config);
112
    }
113
114
    public function testGetHost() : void
115
    {
116
        self::assertEquals('localhost', $this->connection->getHost());
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::getHost() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

116
        self::assertEquals('localhost', /** @scrutinizer ignore-deprecated */ $this->connection->getHost());
Loading history...
117
    }
118
119
    public function testGetPort() : void
120
    {
121
        self::assertEquals('1234', $this->connection->getPort());
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::getPort() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

121
        self::assertEquals('1234', /** @scrutinizer ignore-deprecated */ $this->connection->getPort());
Loading history...
122
    }
123
124
    public function testGetUsername() : void
125
    {
126
        self::assertEquals('root', $this->connection->getUsername());
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::getUsername() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

126
        self::assertEquals('root', /** @scrutinizer ignore-deprecated */ $this->connection->getUsername());
Loading history...
127
    }
128
129
    public function testGetPassword() : void
130
    {
131
        self::assertEquals('password', $this->connection->getPassword());
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\Connection::getPassword() has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

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