mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-03 23:05:41 +08:00
352 lines
11 KiB
PHP
352 lines
11 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace Tests\StaticPHP\Artifact;
|
||
|
|
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
use StaticPHP\Artifact\Artifact;
|
||
|
|
use StaticPHP\Artifact\ArtifactDownloader;
|
||
|
|
use StaticPHP\Config\ArtifactConfig;
|
||
|
|
use StaticPHP\Exception\WrongUsageException;
|
||
|
|
use StaticPHP\Registry\ArtifactLoader;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @internal
|
||
|
|
*/
|
||
|
|
class ArtifactDownloaderTest extends TestCase
|
||
|
|
{
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
parent::setUp();
|
||
|
|
|
||
|
|
// Reset ArtifactConfig and ArtifactLoader static state
|
||
|
|
$reflection = new \ReflectionClass(ArtifactConfig::class);
|
||
|
|
$property = $reflection->getProperty('artifact_configs');
|
||
|
|
$property->setAccessible(true);
|
||
|
|
$property->setValue(null, []);
|
||
|
|
|
||
|
|
$loaderReflection = new \ReflectionClass(ArtifactLoader::class);
|
||
|
|
$loaderProperty = $loaderReflection->getProperty('artifacts');
|
||
|
|
$loaderProperty->setAccessible(true);
|
||
|
|
$loaderProperty->setValue(null, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function tearDown(): void
|
||
|
|
{
|
||
|
|
parent::tearDown();
|
||
|
|
|
||
|
|
$reflection = new \ReflectionClass(ArtifactConfig::class);
|
||
|
|
$property = $reflection->getProperty('artifact_configs');
|
||
|
|
$property->setAccessible(true);
|
||
|
|
$property->setValue(null, []);
|
||
|
|
|
||
|
|
$loaderReflection = new \ReflectionClass(ArtifactLoader::class);
|
||
|
|
$loaderProperty = $loaderReflection->getProperty('artifacts');
|
||
|
|
$loaderProperty->setAccessible(true);
|
||
|
|
$loaderProperty->setValue(null, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== DOWNLOADERS constant ====================
|
||
|
|
|
||
|
|
public function testDownloadersConstantHasExpectedKeys(): void
|
||
|
|
{
|
||
|
|
$expectedKeys = ['bitbuckettag', 'filelist', 'git', 'ghrel', 'ghtar', 'ghtagtar', 'local', 'pie', 'pecl', 'url', 'php-release', 'hosted'];
|
||
|
|
|
||
|
|
foreach ($expectedKeys as $key) {
|
||
|
|
$this->assertArrayHasKey($key, ArtifactDownloader::DOWNLOADERS, "Missing downloader key: {$key}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== Constructor options ====================
|
||
|
|
|
||
|
|
public function testConstructWithDefaultOptions(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$this->assertSame(0, $downloader->getRetry());
|
||
|
|
$this->assertFalse($downloader->interactive);
|
||
|
|
$this->assertEmpty($downloader->getArtifacts());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithParallelOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['parallel' => 4], false);
|
||
|
|
|
||
|
|
// parallel is internal but setParallel/getArtifacts reveals behavior; check via setParallel chainability
|
||
|
|
// Indirect verification: setParallel with same value returns $this
|
||
|
|
$this->assertSame($downloader, $downloader->setParallel(4));
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithRetryOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['retry' => 3], false);
|
||
|
|
|
||
|
|
$this->assertSame(3, $downloader->getRetry());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithNegativeRetryClampedToZero(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['retry' => -5], false);
|
||
|
|
|
||
|
|
$this->assertSame(0, $downloader->getRetry());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithPreferSourceBoolOption(): void
|
||
|
|
{
|
||
|
|
// prefer-source=true sets default to FETCH_PREFER_SOURCE (0)
|
||
|
|
$downloader = new ArtifactDownloader(['prefer-source' => true], false);
|
||
|
|
|
||
|
|
$this->assertSame(0, $downloader->getRetry()); // sanity check, object created fine
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithPreferBinaryBoolOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['prefer-binary' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithPreferPreBuiltBoolOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['prefer-pre-built' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithSourceOnlyBoolOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['source-only' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithBinaryOnlyBoolOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['binary-only' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithIgnoreCacheBoolOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['ignore-cache' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithIgnoreCacheStringOptionParsesNames(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['ignore-cache' => 'openssl,zlib'], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithIgnoreCacheSourcesBackwardCompat(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['ignore-cache-sources' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithCustomUrlOptionAddsToIgnoreCache(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(
|
||
|
|
['custom-url' => ['openssl:https://custom.example.com/openssl.tar.gz']],
|
||
|
|
false
|
||
|
|
);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithCustomGitOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(
|
||
|
|
['custom-git' => ['php-src:master:https://github.com/php/php-src.git']],
|
||
|
|
false
|
||
|
|
);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithCustomLocalOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(
|
||
|
|
['custom-local' => ['my-lib:/tmp/my-lib-source']],
|
||
|
|
false
|
||
|
|
);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testConstructWithNoAltOption(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['no-alt' => true], false);
|
||
|
|
|
||
|
|
$this->assertNotNull($downloader);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== getRetry ====================
|
||
|
|
|
||
|
|
public function testGetRetryDefaultsToZero(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$this->assertSame(0, $downloader->getRetry());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testGetRetryReturnsConfiguredValue(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['retry' => 5], false);
|
||
|
|
|
||
|
|
$this->assertSame(5, $downloader->getRetry());
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== getOption ====================
|
||
|
|
|
||
|
|
public function testGetOptionReturnsConfiguredValue(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader(['retry' => 2, 'parallel' => 3], false);
|
||
|
|
|
||
|
|
$this->assertSame(2, $downloader->getOption('retry'));
|
||
|
|
$this->assertSame(3, $downloader->getOption('parallel'));
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testGetOptionReturnsDefaultWhenNotSet(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$this->assertNull($downloader->getOption('non-existent'));
|
||
|
|
$this->assertSame('default-val', $downloader->getOption('non-existent', 'default-val'));
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== getArtifacts ====================
|
||
|
|
|
||
|
|
public function testGetArtifactsReturnsEmptyInitially(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$this->assertSame([], $downloader->getArtifacts());
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== add ====================
|
||
|
|
|
||
|
|
public function testAddWithArtifactObjectAddsToList(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
$artifact = new Artifact('my-pkg', ['source' => ['type' => 'url', 'url' => 'https://example.com/file.tar.gz']]);
|
||
|
|
|
||
|
|
$downloader->add($artifact);
|
||
|
|
|
||
|
|
$artifacts = $downloader->getArtifacts();
|
||
|
|
$this->assertArrayHasKey('my-pkg', $artifacts);
|
||
|
|
$this->assertSame($artifact, $artifacts['my-pkg']);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testAddReturnsSelf(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
$artifact = new Artifact('my-pkg', ['source' => ['type' => 'url', 'url' => 'https://example.com/file.tar.gz']]);
|
||
|
|
|
||
|
|
$result = $downloader->add($artifact);
|
||
|
|
|
||
|
|
$this->assertSame($downloader, $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testAddDoesNotAddDuplicateArtifact(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
$artifact = new Artifact('my-pkg', ['source' => ['type' => 'url', 'url' => 'https://example.com/file.tar.gz']]);
|
||
|
|
|
||
|
|
$downloader->add($artifact);
|
||
|
|
$downloader->add($artifact);
|
||
|
|
|
||
|
|
$this->assertCount(1, $downloader->getArtifacts());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testAddWithStringNameLooksUpFromArtifactLoader(): void
|
||
|
|
{
|
||
|
|
$this->injectArtifactConfig('my-lib', ['source' => ['type' => 'url', 'url' => 'https://example.com/file.tar.gz']]);
|
||
|
|
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
$downloader->add('my-lib');
|
||
|
|
|
||
|
|
$artifacts = $downloader->getArtifacts();
|
||
|
|
$this->assertArrayHasKey('my-lib', $artifacts);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testAddWithStringNameThrowsForNonExistentArtifact(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$this->expectException(WrongUsageException::class);
|
||
|
|
$this->expectExceptionMessage("Artifact 'non-existent' not found");
|
||
|
|
|
||
|
|
$downloader->add('non-existent');
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== addArtifacts ====================
|
||
|
|
|
||
|
|
public function testAddArtifactsAddsMultipleAtOnce(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
$a1 = new Artifact('pkg-a', ['source' => ['type' => 'url', 'url' => 'https://example.com/a.tar.gz']]);
|
||
|
|
$a2 = new Artifact('pkg-b', ['source' => ['type' => 'url', 'url' => 'https://example.com/b.tar.gz']]);
|
||
|
|
|
||
|
|
$downloader->addArtifacts([$a1, $a2]);
|
||
|
|
|
||
|
|
$this->assertCount(2, $downloader->getArtifacts());
|
||
|
|
$this->assertArrayHasKey('pkg-a', $downloader->getArtifacts());
|
||
|
|
$this->assertArrayHasKey('pkg-b', $downloader->getArtifacts());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testAddArtifactsReturnsSelf(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$result = $downloader->addArtifacts([]);
|
||
|
|
|
||
|
|
$this->assertSame($downloader, $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== setParallel ====================
|
||
|
|
|
||
|
|
public function testSetParallelReturnsSelf(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$result = $downloader->setParallel(3);
|
||
|
|
|
||
|
|
$this->assertSame($downloader, $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testSetParallelEnforcesMinimumOfOne(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$downloader->setParallel(0);
|
||
|
|
// No direct getter for parallel, but verifying it doesn't throw
|
||
|
|
$this->assertSame($downloader, $downloader->setParallel(0));
|
||
|
|
}
|
||
|
|
|
||
|
|
public function testSetParallelAcceptsNormalValue(): void
|
||
|
|
{
|
||
|
|
$downloader = new ArtifactDownloader([], false);
|
||
|
|
|
||
|
|
$result = $downloader->setParallel(5);
|
||
|
|
$this->assertSame($downloader, $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==================== Helpers ====================
|
||
|
|
|
||
|
|
private function injectArtifactConfig(string $name, array $config): void
|
||
|
|
{
|
||
|
|
$reflection = new \ReflectionClass(ArtifactConfig::class);
|
||
|
|
$property = $reflection->getProperty('artifact_configs');
|
||
|
|
$property->setAccessible(true);
|
||
|
|
$configs = $property->getValue(null) ?? [];
|
||
|
|
$configs[$name] = $config;
|
||
|
|
$property->setValue(null, $configs);
|
||
|
|
}
|
||
|
|
}
|