Skip to content

Commit e4978c2

Browse files
authored
Merge pull request #3530 from doctrine/fix-readonly-sqlite-exception-test
Improve ExceptionTest::testConnectionExceptionSqLite
2 parents 945b271 + b244b9e commit e4978c2

File tree

1 file changed

+42
-19
lines changed

1 file changed

+42
-19
lines changed

tests/Doctrine/Tests/DBAL/Functional/ExceptionTest.php

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99
use Doctrine\DBAL\Schema\Table;
1010
use Doctrine\Tests\DbalFunctionalTestCase;
1111
use Throwable;
12+
use const PHP_OS;
1213
use function array_merge;
1314
use function chmod;
14-
use function defined;
15+
use function exec;
1516
use function file_exists;
17+
use function posix_geteuid;
18+
use function posix_getpwuid;
1619
use function sprintf;
1720
use function sys_get_temp_dir;
1821
use function touch;
@@ -284,25 +287,28 @@ public function testSyntaxErrorException()
284287
$this->connection->executeQuery($sql);
285288
}
286289

287-
/**
288-
* @dataProvider getSqLiteOpenConnection
289-
*/
290-
public function testConnectionExceptionSqLite($mode, $exceptionClass)
290+
public function testConnectionExceptionSqLite()
291291
{
292292
if ($this->connection->getDatabasePlatform()->getName() !== 'sqlite') {
293293
$this->markTestSkipped('Only fails this way on sqlite');
294294
}
295295

296+
// mode 0 is considered read-only on Windows
297+
$mode = PHP_OS === 'Linux' ? 0444 : 0000;
298+
296299
$filename = sprintf('%s/%s', sys_get_temp_dir(), 'doctrine_failed_connection_' . $mode . '.db');
297300

298301
if (file_exists($filename)) {
299-
chmod($filename, 0200); // make the file writable again, so it can be removed on Windows
300-
unlink($filename);
302+
$this->cleanupReadOnlyFile($filename);
301303
}
302304

303305
touch($filename);
304306
chmod($filename, $mode);
305307

308+
if ($this->isLinuxRoot()) {
309+
exec(sprintf('chattr +i %s', $filename));
310+
}
311+
306312
$params = [
307313
'driver' => 'pdo_sqlite',
308314
'path' => $filename,
@@ -313,19 +319,21 @@ public function testConnectionExceptionSqLite($mode, $exceptionClass)
313319
$table = $schema->createTable('no_connection');
314320
$table->addColumn('id', 'integer');
315321

316-
$this->expectException($exceptionClass);
317-
foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
318-
$conn->exec($sql);
319-
}
320-
}
322+
$this->expectException(Exception\ReadOnlyException::class);
323+
$this->expectExceptionMessage(<<<EOT
324+
An exception occurred while executing 'CREATE TABLE no_connection (id INTEGER NOT NULL)':
321325
322-
public function getSqLiteOpenConnection()
323-
{
324-
return [
325-
// mode 0 is considered read-only on Windows
326-
[0000, defined('PHP_WINDOWS_VERSION_BUILD') ? Exception\ReadOnlyException::class : Exception\ConnectionException::class],
327-
[0444, Exception\ReadOnlyException::class],
328-
];
326+
SQLSTATE[HY000]: General error: 8 attempt to write a readonly database
327+
EOT
328+
);
329+
330+
try {
331+
foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) {
332+
$conn->exec($sql);
333+
}
334+
} finally {
335+
$this->cleanupReadOnlyFile($filename);
336+
}
329337
}
330338

331339
/**
@@ -395,4 +403,19 @@ private function tearDownForeignKeyConstraintViolationExceptionTest()
395403
$schemaManager->dropTable('owning_table');
396404
$schemaManager->dropTable('constraint_error_table');
397405
}
406+
407+
private function isLinuxRoot() : bool
408+
{
409+
return PHP_OS === 'Linux' && posix_getpwuid(posix_geteuid())['name'] === 'root';
410+
}
411+
412+
private function cleanupReadOnlyFile(string $filename) : void
413+
{
414+
if ($this->isLinuxRoot()) {
415+
exec(sprintf('chattr -i %s', $filename));
416+
}
417+
418+
chmod($filename, 0200); // make the file writable again, so it can be removed on Windows
419+
unlink($filename);
420+
}
398421
}

0 commit comments

Comments
 (0)