Failed Conditions
Pull Request — 2.10 (#3803)
by Sergei
62:38
created

ConnectionTest::testCallConnectOnce()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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

117
        self::assertEquals('localhost', /** @scrutinizer ignore-deprecated */ $this->connection->getHost());
Loading history...
118
    }
119
120
    public function testGetPort() : void
121
    {
122
        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

122
        self::assertEquals('1234', /** @scrutinizer ignore-deprecated */ $this->connection->getPort());
Loading history...
123
    }
124
125
    public function testGetUsername() : void
126
    {
127
        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

127
        self::assertEquals('root', /** @scrutinizer ignore-deprecated */ $this->connection->getUsername());
Loading history...
128
    }
129
130
    public function testGetPassword() : void
131
    {
132
        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

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