mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-03 12:02:29 +02:00
Make the GitHub-release GeoIP updates cohesive and testable, and keep the GitHubReleases class a generic release client. - GitHubReleases: drop the domain-specific getGeolite()/getIspDatabase()/ getAsnCatalog() and the private releaseAsset() — they hard-coded the maxmind paths and GeoIP filenames, which don't belong in a generic GitHub-releases client. Add the generic assetUrl($version, $asset) primitive; domain code now composes its own specs around it. Also drop a stale usage example that referenced the removed getGeolite(). - New XcVm\Core\GeoIP\GeoLiteReleaseUpdater owns the release-asset sync: builds the GeoLite2-City/Country and GeoIP2-ISP specs (url via assetUrl, md5 via getAssetHash, local maxmind path), downloads them through ONE path, and records the version into maxmind/version.json. This unifies GeoIP2-ISP with GeoLite2 — the ISP now gets the same dir self-heal, checksum-tolerant "always save" behaviour, status lines and chmod 0750 (was 0640) instead of the leaner fetchReleaseFile() it used before. - MaxMindCronJob is now a thin orchestrator (updateGeoLite/updateIsp); AsnCatalogSync builds its own blocked_asns spec via assetUrl/getAssetHash. - Tests: GeoLiteReleaseUpdaterTest (specs/paths/version, error paths) via a mocked repo + protected download/record seams; GitHubReleasesTest covers assetUrl().
99 lines
3.7 KiB
PHP
99 lines
3.7 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'); // legacy alias, normalized to 'beta'
|
|
|
|
$this->assertSame('beta', $channelProperty->getValue($instance));
|
|
$this->assertSame($basePath . '_beta', $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('nightly');
|
|
}
|
|
|
|
public function testAssetUrlBuildsReleaseDownloadUrl() {
|
|
$instance = new GitHubReleases('Vateron-Media', 'XC_VM_Update', 'stable');
|
|
$this->assertSame(
|
|
'https://github.com/Vateron-Media/XC_VM_Update/releases/download/29062026/GeoLite2-City.mmdb',
|
|
$instance->assetUrl('29062026', 'GeoLite2-City.mmdb')
|
|
);
|
|
}
|
|
}
|