Failed Conditions
Pull Request — master (#3847)
by Sergei
64:47
created

ConnectionTest::testSetAutoCommit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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