1 | <?php |
||
2 | |||
3 | namespace Doctrine\Tests\DBAL\Functional; |
||
4 | |||
5 | use Doctrine\DBAL\ConnectionException; |
||
6 | use Doctrine\DBAL\DriverManager; |
||
7 | use Doctrine\DBAL\Platforms\AbstractPlatform; |
||
8 | use Doctrine\DBAL\Types\Type; |
||
9 | |||
10 | class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase |
||
11 | { |
||
12 | protected function setUp() |
||
13 | { |
||
14 | $this->resetSharedConn(); |
||
15 | parent::setUp(); |
||
16 | } |
||
17 | |||
18 | protected function tearDown() |
||
19 | { |
||
20 | parent::tearDown(); |
||
21 | $this->resetSharedConn(); |
||
22 | } |
||
23 | |||
24 | public function testGetWrappedConnection() |
||
25 | { |
||
26 | self::assertInstanceOf('Doctrine\DBAL\Driver\Connection', $this->_conn->getWrappedConnection()); |
||
27 | } |
||
28 | |||
29 | public function testCommitWithRollbackOnlyThrowsException() |
||
30 | { |
||
31 | $this->_conn->beginTransaction(); |
||
32 | $this->_conn->setRollbackOnly(); |
||
33 | |||
34 | $this->expectException(ConnectionException::class); |
||
35 | $this->_conn->commit(); |
||
36 | } |
||
37 | |||
38 | public function testTransactionNestingBehavior() |
||
39 | { |
||
40 | try { |
||
41 | $this->_conn->beginTransaction(); |
||
42 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
43 | |||
44 | try { |
||
45 | $this->_conn->beginTransaction(); |
||
46 | self::assertEquals(2, $this->_conn->getTransactionNestingLevel()); |
||
47 | throw new \Exception; |
||
48 | $this->_conn->commit(); // never reached |
||
0 ignored issues
–
show
|
|||
49 | } catch (\Exception $e) { |
||
50 | $this->_conn->rollBack(); |
||
51 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
52 | //no rethrow |
||
53 | } |
||
54 | self::assertTrue($this->_conn->isRollbackOnly()); |
||
55 | |||
56 | $this->_conn->commit(); // should throw exception |
||
57 | $this->fail('Transaction commit after failed nested transaction should fail.'); |
||
58 | } catch (ConnectionException $e) { |
||
59 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
60 | $this->_conn->rollBack(); |
||
61 | self::assertEquals(0, $this->_conn->getTransactionNestingLevel()); |
||
62 | } |
||
63 | } |
||
64 | |||
65 | public function testTransactionNestingBehaviorWithSavepoints() |
||
66 | { |
||
67 | if (!$this->_conn->getDatabasePlatform()->supportsSavepoints()) { |
||
68 | $this->markTestSkipped('This test requires the platform to support savepoints.'); |
||
69 | } |
||
70 | |||
71 | $this->_conn->setNestTransactionsWithSavepoints(true); |
||
72 | try { |
||
73 | $this->_conn->beginTransaction(); |
||
74 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
75 | |||
76 | try { |
||
77 | $this->_conn->beginTransaction(); |
||
78 | self::assertEquals(2, $this->_conn->getTransactionNestingLevel()); |
||
79 | $this->_conn->beginTransaction(); |
||
80 | self::assertEquals(3, $this->_conn->getTransactionNestingLevel()); |
||
81 | $this->_conn->commit(); |
||
82 | self::assertEquals(2, $this->_conn->getTransactionNestingLevel()); |
||
83 | throw new \Exception; |
||
84 | $this->_conn->commit(); // never reached |
||
85 | } catch (\Exception $e) { |
||
86 | $this->_conn->rollBack(); |
||
87 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
88 | //no rethrow |
||
89 | } |
||
90 | self::assertFalse($this->_conn->isRollbackOnly()); |
||
91 | try { |
||
92 | $this->_conn->setNestTransactionsWithSavepoints(false); |
||
93 | $this->fail('Should not be able to disable savepoints in usage for nested transactions inside an open transaction.'); |
||
94 | } catch (ConnectionException $e) { |
||
95 | self::assertTrue($this->_conn->getNestTransactionsWithSavepoints()); |
||
96 | } |
||
97 | $this->_conn->commit(); // should not throw exception |
||
98 | } catch (ConnectionException $e) { |
||
99 | $this->fail('Transaction commit after failed nested transaction should not fail when using savepoints.'); |
||
100 | $this->_conn->rollBack(); |
||
101 | } |
||
102 | } |
||
103 | |||
104 | public function testTransactionNestingBehaviorCantBeChangedInActiveTransaction() |
||
105 | { |
||
106 | if (!$this->_conn->getDatabasePlatform()->supportsSavepoints()) { |
||
107 | $this->markTestSkipped('This test requires the platform to support savepoints.'); |
||
108 | } |
||
109 | |||
110 | $this->_conn->beginTransaction(); |
||
111 | $this->expectException(ConnectionException::class); |
||
112 | $this->_conn->setNestTransactionsWithSavepoints(true); |
||
113 | } |
||
114 | |||
115 | View Code Duplication | public function testSetNestedTransactionsThroughSavepointsNotSupportedThrowsException() |
|
116 | { |
||
117 | if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) { |
||
118 | $this->markTestSkipped('This test requires the platform not to support savepoints.'); |
||
119 | } |
||
120 | |||
121 | $this->expectException(ConnectionException::class); |
||
122 | $this->expectExceptionMessage("Savepoints are not supported by this driver."); |
||
123 | |||
124 | $this->_conn->setNestTransactionsWithSavepoints(true); |
||
125 | } |
||
126 | |||
127 | View Code Duplication | public function testCreateSavepointsNotSupportedThrowsException() |
|
128 | { |
||
129 | if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) { |
||
130 | $this->markTestSkipped('This test requires the platform not to support savepoints.'); |
||
131 | } |
||
132 | |||
133 | $this->expectException(ConnectionException::class); |
||
134 | $this->expectExceptionMessage("Savepoints are not supported by this driver."); |
||
135 | |||
136 | $this->_conn->createSavepoint('foo'); |
||
137 | } |
||
138 | |||
139 | View Code Duplication | public function testReleaseSavepointsNotSupportedThrowsException() |
|
140 | { |
||
141 | if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) { |
||
142 | $this->markTestSkipped('This test requires the platform not to support savepoints.'); |
||
143 | } |
||
144 | |||
145 | $this->expectException(ConnectionException::class); |
||
146 | $this->expectExceptionMessage("Savepoints are not supported by this driver."); |
||
147 | |||
148 | $this->_conn->releaseSavepoint('foo'); |
||
149 | } |
||
150 | |||
151 | View Code Duplication | public function testRollbackSavepointsNotSupportedThrowsException() |
|
152 | { |
||
153 | if ($this->_conn->getDatabasePlatform()->supportsSavepoints()) { |
||
154 | $this->markTestSkipped('This test requires the platform not to support savepoints.'); |
||
155 | } |
||
156 | |||
157 | $this->expectException(ConnectionException::class); |
||
158 | $this->expectExceptionMessage("Savepoints are not supported by this driver."); |
||
159 | |||
160 | $this->_conn->rollbackSavepoint('foo'); |
||
161 | } |
||
162 | |||
163 | View Code Duplication | public function testTransactionBehaviorWithRollback() |
|
164 | { |
||
165 | try { |
||
166 | $this->_conn->beginTransaction(); |
||
167 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
168 | |||
169 | throw new \Exception; |
||
170 | |||
171 | $this->_conn->commit(); // never reached |
||
172 | } catch (\Exception $e) { |
||
173 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
174 | $this->_conn->rollBack(); |
||
175 | self::assertEquals(0, $this->_conn->getTransactionNestingLevel()); |
||
176 | } |
||
177 | } |
||
178 | |||
179 | View Code Duplication | public function testTransactionBehaviour() |
|
180 | { |
||
181 | try { |
||
182 | $this->_conn->beginTransaction(); |
||
183 | self::assertEquals(1, $this->_conn->getTransactionNestingLevel()); |
||
184 | $this->_conn->commit(); |
||
185 | } catch (\Exception $e) { |
||
186 | $this->_conn->rollBack(); |
||
187 | self::assertEquals(0, $this->_conn->getTransactionNestingLevel()); |
||
188 | } |
||
189 | |||
190 | self::assertEquals(0, $this->_conn->getTransactionNestingLevel()); |
||
191 | } |
||
192 | |||
193 | public function testTransactionalWithException() |
||
194 | { |
||
195 | try { |
||
196 | $this->_conn->transactional(function($conn) { |
||
197 | /* @var $conn \Doctrine\DBAL\Connection */ |
||
198 | $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL()); |
||
199 | throw new \RuntimeException("Ooops!"); |
||
200 | }); |
||
201 | $this->fail('Expected exception'); |
||
202 | } catch (\RuntimeException $expected) { |
||
203 | self::assertEquals(0, $this->_conn->getTransactionNestingLevel()); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | public function testTransactionalWithThrowable() |
||
208 | { |
||
209 | if (version_compare(PHP_VERSION, '7.0', '<')) { |
||
210 | $this->markTestSkipped('Only for PHP 7.0 and above.'); |
||
211 | } |
||
212 | |||
213 | try { |
||
214 | $this->_conn->transactional(function($conn) { |
||
215 | /* @var $conn \Doctrine\DBAL\Connection */ |
||
216 | $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL()); |
||
217 | throw new \Error("Ooops!"); |
||
218 | }); |
||
219 | $this->fail('Expected exception'); |
||
220 | } catch (\Error $expected) { |
||
221 | self::assertEquals(0, $this->_conn->getTransactionNestingLevel()); |
||
222 | } |
||
223 | } |
||
224 | |||
225 | public function testTransactional() |
||
226 | { |
||
227 | $res = $this->_conn->transactional(function($conn) { |
||
228 | /* @var $conn \Doctrine\DBAL\Connection */ |
||
229 | $conn->executeQuery($conn->getDatabasePlatform()->getDummySelectSQL()); |
||
230 | }); |
||
231 | |||
232 | self::assertNull($res); |
||
233 | } |
||
234 | |||
235 | public function testTransactionalReturnValue() |
||
236 | { |
||
237 | $res = $this->_conn->transactional(function() { |
||
238 | return 42; |
||
239 | }); |
||
240 | |||
241 | self::assertEquals(42, $res); |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * Tests that the quote function accepts DBAL and PDO types. |
||
246 | */ |
||
247 | public function testQuote() |
||
248 | { |
||
249 | self::assertEquals($this->_conn->quote("foo", Type::STRING), $this->_conn->quote("foo", \PDO::PARAM_STR)); |
||
250 | } |
||
251 | |||
252 | public function testPingDoesTriggersConnect() |
||
253 | { |
||
254 | self::assertTrue($this->_conn->ping()); |
||
255 | self::assertTrue($this->_conn->isConnected()); |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * @group DBAL-1025 |
||
260 | */ |
||
261 | public function testConnectWithoutExplicitDatabaseName() |
||
262 | { |
||
263 | View Code Duplication | if (in_array($this->_conn->getDatabasePlatform()->getName(), array('oracle', 'db2'), true)) { |
|
264 | $this->markTestSkipped('Platform does not support connecting without database name.'); |
||
265 | } |
||
266 | |||
267 | $params = $this->_conn->getParams(); |
||
268 | unset($params['dbname']); |
||
269 | |||
270 | $connection = DriverManager::getConnection( |
||
271 | $params, |
||
272 | $this->_conn->getConfiguration(), |
||
273 | $this->_conn->getEventManager() |
||
274 | ); |
||
275 | |||
276 | self::assertTrue($connection->connect()); |
||
277 | |||
278 | $connection->close(); |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * @group DBAL-990 |
||
283 | */ |
||
284 | public function testDeterminesDatabasePlatformWhenConnectingToNonExistentDatabase() |
||
285 | { |
||
286 | View Code Duplication | if (in_array($this->_conn->getDatabasePlatform()->getName(), ['oracle', 'db2'], true)) { |
|
287 | $this->markTestSkipped('Platform does not support connecting without database name.'); |
||
288 | } |
||
289 | |||
290 | $params = $this->_conn->getParams(); |
||
291 | $params['dbname'] = 'foo_bar'; |
||
292 | |||
293 | $connection = DriverManager::getConnection( |
||
294 | $params, |
||
295 | $this->_conn->getConfiguration(), |
||
296 | $this->_conn->getEventManager() |
||
297 | ); |
||
298 | |||
299 | self::assertInstanceOf(AbstractPlatform::class, $connection->getDatabasePlatform()); |
||
300 | self::assertFalse($connection->isConnected()); |
||
301 | self::assertSame($params, $connection->getParams()); |
||
302 | |||
303 | $connection->close(); |
||
304 | } |
||
305 | } |
||
306 |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.