Files
Gnuboard7/tests/Unit/Config/DatabaseConfigDeprecationTest.php
T
2026-05-11 11:29:41 +09:00

95 lines
3.5 KiB
PHP

<?php
namespace Tests\Unit\Config;
use Tests\TestCase;
/**
* config/database.php 의 PHP 8.5+ deprecation 회피 회귀 테스트
*
* PHP 8.5 에서 PDO::MYSQL_ATTR_SSL_CA 상수가 deprecated 되었으므로
* config 로드 시 E_DEPRECATED 가 트리거되지 않아야 한다.
*
* 검증 방식:
* 1. 동적: config 파일을 재include 하여 발생한 PDO 관련 deprecation 캡처 (PHP 8.5+ 에서만 트리거)
* 2. 정적: 파일 텍스트에서 가드 없는 PDO::MYSQL_ATTR_SSL_CA 직접 참조 패턴 검출 (모든 PHP 버전)
*
* 정적 검사는 PHP 8.4 이하 CI 에서도 회귀를 차단하기 위함이다.
*
* @see https://github.com/gnuboard/g7/issues/23
*/
class DatabaseConfigDeprecationTest extends TestCase
{
public function test_mysql_options_does_not_trigger_pdo_deprecation(): void
{
$deprecations = $this->captureDeprecations(function () {
// Laravel 부팅 후 config 파일을 재include — database_path() 등 헬퍼 사용 가능
$config = require config_path('database.php');
$mysqlOptions = $config['connections']['mysql']['options'];
$mariadbOptions = $config['connections']['mariadb']['options'];
// array_filter 결과를 실제로 순회하여 키 상수 평가 강제
foreach ($mysqlOptions as $k => $v) {
$unused = $k;
}
foreach ($mariadbOptions as $k => $v) {
$unused = $k;
}
});
$this->assertEmpty(
$deprecations,
'config/database.php emitted PHP deprecation: '
. json_encode($deprecations, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
);
}
public function test_config_file_does_not_reference_unguarded_deprecated_pdo_constant(): void
{
$file = file_get_contents(config_path('database.php'));
// 가드 패턴: PHP_VERSION_ID >= 80500 ternary 안에서만 PDO::MYSQL_ATTR_SSL_CA 사용 허용
$guardedPattern = '/PHP_VERSION_ID\s*>=\s*80500.*?Pdo\\\\Mysql::ATTR_SSL_CA.*?PDO::MYSQL_ATTR_SSL_CA/s';
$hasGuard = (bool) preg_match($guardedPattern, $file);
// 직접 참조 횟수
$directReferences = preg_match_all('/PDO::MYSQL_ATTR_SSL_CA/', $file);
if ($directReferences > 0 && ! $hasGuard) {
$this->fail(
"config/database.php references PDO::MYSQL_ATTR_SSL_CA without a "
. "PHP_VERSION_ID >= 80500 ternary guard. This causes E_DEPRECATED "
. "on PHP 8.5+. Use \\Pdo\\Mysql::ATTR_SSL_CA when PHP_VERSION_ID >= 80500."
);
}
$this->assertTrue(true);
}
/**
* @param callable $fn 실행 중 발생한 deprecation 을 수집할 콜백
* @return array<int, array{message: string, file: string, line: int}>
*/
private function captureDeprecations(callable $fn): array
{
$deprecations = [];
set_error_handler(function ($severity, $message, $file, $line) use (&$deprecations) {
if ($severity === E_DEPRECATED || $severity === E_USER_DEPRECATED) {
if (str_contains($message, 'PDO::') || str_contains($message, 'MYSQL_ATTR_')) {
$deprecations[] = compact('message', 'file', 'line');
}
}
return true;
}, E_DEPRECATED | E_USER_DEPRECATED);
try {
$fn();
} finally {
restore_error_handler();
}
return $deprecations;
}
}