Files
XC_VM/tests/Unit/AutoloadOrderTest.php
T
Divarion-D fd35f00c4d fix(views): import migrated classes at top of 5 admin view templates
enigma, episode, episodes, process_monitor and stream_view referenced migrated
classes (UserRepository, BouquetService, StreamRepository, RequestManager,
SettingsManager, ...) by short name with either no `use` or a `use` placed
*below* the first usage. PHP imports outside the top scope are positional, so the
short name resolved to a now-nonexistent global class — a runtime fatal on those
admin pages (php -l passes; not covered by PHPStan/PHPUnit). The migration's
automated `use` insertion missed them due to the interleaved HTML / short-tag
(<? , <?=) structure, and the later php-cs-fixer pass stripped some as 'unused'
because it could not see usage inside short-tag blocks.

- Consolidate every needed `use XcVm\...;` into a single top-of-file PHP block.
- Exclude Public/Views and Modules/*/views from php-cs-fixer (no_unused_imports
  is unreliable on short-tag templates); their import correctness is enforced by
  the new check_procedural_use gate instead.

Verified: php -l (short_open_tag=1) clean; PHPStan no errors; PHPUnit green.
2026-06-25 20:57:37 +03:00

76 lines
2.5 KiB
PHP

<?php
use PHPUnit\Framework\TestCase;
/**
* Autoloader invariants after the PSR-4 migration (plan: Фаза 0 + Финал).
*
* - The Composer PSR-4 autoloader is registered and resolves every XcVm\* class.
* - The legacy XC_Autoloader directory scanner is RETIRED: its init() is a no-op
* that registers nothing, so it must not appear in the SPL stack.
* - No igbinary class-map cache (tmp/cache/autoload_map) is ever written.
*/
final class AutoloadOrderTest extends TestCase {
public function testComposerAutoloaderIsRegistered(): void {
$hasComposer = false;
foreach (spl_autoload_functions() as $fn) {
if (is_array($fn) && is_object($fn[0])
&& $fn[0] instanceof \Composer\Autoload\ClassLoader) {
$hasComposer = true;
break;
}
}
$this->assertTrue($hasComposer, 'Composer ClassLoader must be registered.');
}
public function testComposerResolvesNamespacedClassFromEveryLayer(): void {
$samples = [
'XcVm\\Core\\Config\\SettingsManager',
'XcVm\\Domain\\User\\UserRepository',
'XcVm\\Infrastructure\\Redis\\RedisManager',
'XcVm\\Streaming\\Codec\\FfmpegPaths',
'XcVm\\Cli\\CommandRegistry',
'XcVm\\Public\\Controllers\\Admin\\UserController',
];
foreach ($samples as $fqcn) {
$this->assertTrue(
class_exists($fqcn) || interface_exists($fqcn),
"Composer must autoload {$fqcn}."
);
}
}
public function testLegacyScannerIsNotRegistered(): void {
foreach (spl_autoload_functions() as $fn) {
if (is_array($fn)) {
$target = is_object($fn[0]) ? get_class($fn[0]) : (string) $fn[0];
$this->assertNotSame(
'XC_Autoloader',
$target,
'The retired XC_Autoloader scanner must not be registered.'
);
}
}
$this->addToAssertionCount(1);
}
public function testInitIsANoOpAndAddsNoLoader(): void {
$this->assertTrue(class_exists('XC_Autoloader'), 'Stub class kept for one release.');
$before = count(spl_autoload_functions());
\XC_Autoloader::init(MAIN_HOME);
$after = count(spl_autoload_functions());
$this->assertSame($before, $after, 'XC_Autoloader::init() must register nothing.');
}
public function testNoClassMapCacheIsWritten(): void {
$cache = MAIN_HOME . 'tmp/cache/autoload_map';
if (is_file($cache)) {
@unlink($cache);
}
// Trigger an autoload + the retired stub; neither may recreate the cache.
$this->assertTrue(class_exists('XcVm\\Core\\Logging\\Logger'));
\XC_Autoloader::init(MAIN_HOME);
$this->assertFileDoesNotExist($cache, 'The igbinary class-map cache must be gone.');
}
}