Failed Conditions
Push — master ( 30b923...92920e )
by Marco
19s queued 13s
created

IsClosedButNotUnset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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