fix(tests): isolate databases in memory and reject persistent connections
This commit is contained in:
80
tests/verify-database-safety.php
Normal file
80
tests/verify-database-safety.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
// Standalone safety check: no test lifecycle, migrations, queries, or PDO connections.
|
||||
putenv('DB_CONNECTION=mysql');
|
||||
$_ENV['DB_DATABASE'] = 'shopit';
|
||||
$_SERVER['DB_URL'] = 'mysql://localhost/shopit';
|
||||
require __DIR__.'/bootstrap.php';
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Tests\Support\InMemoryConnectionFactory;
|
||||
|
||||
$safe = ['driver' => 'sqlite', 'database' => ':memory:'];
|
||||
$unsafe = [
|
||||
[],
|
||||
['driver' => 'mysql', 'database' => 'shopit'],
|
||||
['driver' => 'mysql', 'database' => 'shopit_test'],
|
||||
['driver' => 'sqlite', 'database' => 'database/database.sqlite'],
|
||||
['driver' => 'sqlite', 'database' => 'shopit_test'],
|
||||
array_merge($safe, ['url' => 'mysql://localhost/shopit']),
|
||||
array_merge($safe, ['read' => ['database' => 'shopit']]),
|
||||
array_merge($safe, ['write' => ['database' => 'shopit']]),
|
||||
array_merge($safe, ['direct' => ['database' => 'shopit']]),
|
||||
];
|
||||
$factory = new InMemoryConnectionFactory(new Container);
|
||||
foreach ($unsafe as $config) {
|
||||
try {
|
||||
$factory->make($config);
|
||||
} catch (RuntimeException) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new RuntimeException('Unsafe connection was accepted.');
|
||||
}
|
||||
|
||||
$connection = $factory->make($safe);
|
||||
if (! $connection->getRawPdo() instanceof Closure) {
|
||||
throw new RuntimeException('Verification must not open a PDO connection.');
|
||||
}
|
||||
|
||||
$case = new class('safetyCheck') extends Tests\TestCase {};
|
||||
$app = $case->createApplication();
|
||||
if (! $app['db.factory'] instanceof InMemoryConnectionFactory
|
||||
|| $app['config']->get('database.default') !== 'sqlite'
|
||||
|| ! $app['db']->connection()->getRawPdo() instanceof Closure) {
|
||||
throw new RuntimeException('Application database isolation is not active.');
|
||||
}
|
||||
|
||||
foreach (['mysql', 'pgsql', 'mariadb', 'sqlsrv'] as $name) {
|
||||
try {
|
||||
$app['db']->connection($name);
|
||||
} catch (RuntimeException) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new RuntimeException('A persistent application connection was accepted.');
|
||||
}
|
||||
|
||||
// Include URL overrides resolved by Laravel and dynamically built connections.
|
||||
foreach ([
|
||||
['driver' => 'mysql', 'database' => 'shopit'],
|
||||
array_merge($safe, ['url' => 'mysql://localhost/shopit']),
|
||||
array_merge($safe, ['url' => 'sqlite:///database/database.sqlite']),
|
||||
] as $config) {
|
||||
$app['config']->set('database.connections.unsafe', $config);
|
||||
|
||||
foreach ([
|
||||
fn () => $app['db']->connection('unsafe'),
|
||||
fn () => $app['db']->build($config),
|
||||
] as $connect) {
|
||||
try {
|
||||
$connect();
|
||||
} catch (RuntimeException) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new LogicException('A dynamically configured persistent connection was accepted.');
|
||||
}
|
||||
}
|
||||
|
||||
echo "Database safety verified: unsafe connections rejected; no PDO connections or migrations executed.\n";
|
||||
Reference in New Issue
Block a user