Failed Conditions
Push — master ( 9355a2...379085 )
by Sergei
26s queued 12s
created

testCommitWithNoActiveTransactionThrowsException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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