Failed Conditions
Pull Request — master (#3443)
by Sergei
62:41
created

testConnectStartsTransactionInNoAutoCommitMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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