Files
XC_VM/tests/Unit/DatabaseHostTest.php
T
Divarion_D 284798ede7 fix(db): let Database accept a null host again (CLI boot crash)
The panel boots the DB with `new DatabaseHandler()` and no arguments, so $host
is null and the real credentials are resolved by the bundled XC_VM extension in
db_connect() — dbhost is never used on that path. A strict
`normalizeHost(string $rHost)` hint turned that normal null into a fatal
TypeError at bootstrap (initDatabase → __construct → normalizeHost), taking down
console.php / cron boot:

  Database::normalizeHost(): Argument #1 ($rHost) must be of type string,
  null given, called in .../Database.php on line 53

Make normalizeHost accept and pass through null (?string → ?string), restoring
the pre-typing behaviour; the explicit-credentials path (db_explicit_connect)
still passes a real string. Also make the constructor's implicitly-nullable
`string $x = null` params explicitly `?string` (same root cause, no behaviour
change, and avoids the PHP 8.4 implicit-nullable deprecation).

Add DatabaseHostTest as a regression (reflection on a constructor-less instance,
since the class needs the XC_VM extension to instantiate).
2026-09-13 16:05:56 +03:00

43 lines
1.5 KiB
PHP

<?php
use XcVm\Core\Database\Database;
use PHPUnit\Framework\TestCase;
/**
* Database::normalizeHost — regression for a production CLI-boot crash.
*
* The panel constructs `new DatabaseHandler()` with no arguments, so $host is
* null and the real credentials are resolved by the bundled XC_VM extension in
* db_connect(). A strict `normalizeHost(string $rHost)` hint made that null a
* fatal TypeError at boot; the parameter must accept null and pass it through.
*
* The class can't be instantiated here (db_connect() needs the XC_VM
* extension), so the private method is exercised on a constructor-less instance
* via reflection.
*/
final class DatabaseHostTest extends TestCase {
private function normalize(?string $host)
{
$instance = (new ReflectionClass(Database::class))->newInstanceWithoutConstructor();
$method = new ReflectionMethod(Database::class, 'normalizeHost');
$method->setAccessible(true);
return $method->invoke($instance, $host);
}
public function testNullHostPassesThroughInsteadOfThrowing(): void {
// Regression: a null host (the no-arg DatabaseHandler() boot path) must
// not raise a TypeError.
$this->assertNull($this->normalize(null));
}
public function testLocalhostIsForcedToTcpLoopback(): void {
$this->assertSame('127.0.0.1', $this->normalize('localhost'));
}
public function testOtherHostsAreUnchanged(): void {
$this->assertSame('db.internal', $this->normalize('db.internal'));
$this->assertSame('10.0.0.5', $this->normalize('10.0.0.5'));
}
}