Files
XC_VM/tests/Unit/GitHubReleasesTest.php
T
Divarion-D da291e20f8 chore(psr4): phase 3 (Core) — namespace remaining Core subdirs
Namespace the rest of Core, completing the Core layer:
- Backup, Boundary, Cache (CacheInterface/FileCache/RedisCache), Diagnostics,
  GeoIP (GeoIPService/MaxMindUpdater), Init (LegacyInitializer), Localization
  (Translator), Process (Thread/Multithread/ProcessManager), Updates
  (GitHubReleases), Util (NetworkUtils, AdminHelpers, Encryption, GeoIP,
  ImageUtils/ImageResizeService, Mobile_Detect, StreamUtils, SystemInfo,
  TimeUtils), Validation (InputValidator) → XcVm\Core\<Subdir>.
- Rename GithubReleases.php → GitHubReleases.php so the file matches its class
  name (PSR-4 is case-sensitive); fix the WebApiBootstrap require accordingly.
- Qualify built-ins (\Exception, \DateTime, \DateTimeZone, \Redis,
  \RuntimeException, \BadMethodCallException, ...) and still-global deps
  (\ServerRepository, \CacheReader, \DatabaseFactory, \BouquetService,
  \CategoryService, \FfmpegPaths, \StreamSorter, \XC_VM). LegacyInitializer's
  Domain calls stay \-qualified (the known Core→Domain exception).
- Add use to referrers; fix leading-backslash refs from earlier commits; fix
  string class refs class_exists('Translator'/'NetworkUtils'/...) → ::class.
  Remove the duplicate global 'use BoundaryInterface;' in MinistraModule.
- phpstan-baseline.neon regenerated.

Core is now fully namespaced (procedural constant/error/RequestGuard files stay
global by design; M3uParser/PhpM3u8 remain vendored). Verified: php -l clean;
PHPStan no errors; PHPUnit 295/295; leading-backslash re-sweep clean.
2026-06-24 22:35:33 +03:00

91 lines
3.3 KiB
PHP

<?php
use XcVm\Core\Updates\GitHubReleases;
use PHPUnit\Framework\TestCase;
final class GitHubReleasesTest extends TestCase {
public function testIsValidVersionAcceptsSemanticVersion() {
$this->assertTrue(GitHubReleases::isValidVersion('1.2.3'));
}
public function testIsValidVersionRejectsLeadingZeros() {
$this->assertFalse(GitHubReleases::isValidVersion('01.2.3'));
}
public function testIsValidVersionThrowsForTooLongInput() {
$this->expectException(InvalidArgumentException::class);
GitHubReleases::isValidVersion(str_repeat('1', 21));
}
public function testGetLatestVersionReturnsNullWhenAlreadyUpToDate() {
$mock = $this->getMockBuilder(GitHubReleases::class)
->setConstructorArgs(array('Vateron-Media', 'XC_VM', 'stable'))
->onlyMethods(array('getReleases'))
->getMock();
$mock->method('getReleases')->willReturn(array('1.2.3', '1.2.2', '1.2.1'));
$this->assertNull($mock->getLatestVersion('1.2.3'));
}
public function testGetLatestVersionReturnsNewestVersion() {
$mock = $this->getMockBuilder(GitHubReleases::class)
->setConstructorArgs(array('Vateron-Media', 'XC_VM', 'stable'))
->onlyMethods(array('getReleases'))
->getMock();
$mock->method('getReleases')->willReturn(array('1.4.0', '1.3.9', '1.3.0'));
$this->assertSame('1.4.0', $mock->getLatestVersion('1.3.9'));
}
public function testGetUpdateFileBuildsMainArchiveUrlAndHash() {
$mock = $this->getMockBuilder(GitHubReleases::class)
->setConstructorArgs(array('Vateron-Media', 'XC_VM', 'stable'))
->onlyMethods(array('getLatestVersion', 'getAssetHash'))
->getMock();
$mock->method('getLatestVersion')->with('1.0.0')->willReturn('1.1.0');
$mock->method('getAssetHash')->with('1.1.0', 'xc_vm.tar.gz')->willReturn('md5-hash-value');
$result = $mock->getUpdateFile('main', '1.0.0');
$this->assertSame('https://github.com/Vateron-Media/XC_VM/releases/download/1.1.0/xc_vm.tar.gz', $result['url']);
$this->assertSame('md5-hash-value', $result['md5']);
}
public function testSetTimeoutKeepsMinimumOneSecond() {
$instance = new GitHubReleases('Vateron-Media', 'XC_VM', 'stable');
$instance->setTimeout(0);
$reflection = new ReflectionClass($instance);
$timeout = $reflection->getProperty('timeout');
$timeout->setAccessible(true);
$this->assertSame(1, $timeout->getValue($instance));
}
public function testSetChannelUpdatesCacheFileAndClearsOldCache() {
$instance = new GitHubReleases('Vateron-Media', 'XC_VM', 'stable');
$reflection = new ReflectionClass($instance);
$cacheProperty = $reflection->getProperty('cache_file');
$cacheProperty->setAccessible(true);
$channelProperty = $reflection->getProperty('channel');
$channelProperty->setAccessible(true);
$basePath = sys_get_temp_dir() . '/gitapi_test_' . uniqid('', true);
$cacheProperty->setValue($instance, $basePath . '_stable');
file_put_contents($basePath . '_stable', 'cache-data');
$instance->setChannel('unstable');
$this->assertSame('unstable', $channelProperty->getValue($instance));
$this->assertSame($basePath . '_unstable', $cacheProperty->getValue($instance));
$this->assertFalse(file_exists($basePath . '_stable'));
}
public function testSetChannelRejectsInvalidValue() {
$instance = new GitHubReleases('Vateron-Media', 'XC_VM', 'stable');
$this->expectException(InvalidArgumentException::class);
$instance->setChannel('beta');
}
}