mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-09 09:55:37 +08:00
Refactor test structure and update paths for improved organization
This commit is contained in:
303
tests/StaticPHP/Config/ArtifactConfigTest.php
Normal file
303
tests/StaticPHP/Config/ArtifactConfigTest.php
Normal file
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\StaticPHP\Config;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use StaticPHP\Config\ArtifactConfig;
|
||||
use StaticPHP\Exception\WrongUsageException;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ArtifactConfigTest extends TestCase
|
||||
{
|
||||
private string $tempDir;
|
||||
|
||||
/** @noinspection PhpExpressionResultUnusedInspection */
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tempDir = sys_get_temp_dir() . '/artifact_config_test_' . uniqid();
|
||||
mkdir($this->tempDir, 0755, true);
|
||||
|
||||
// Reset static state
|
||||
$reflection = new \ReflectionClass(ArtifactConfig::class);
|
||||
$property = $reflection->getProperty('artifact_configs');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue([]);
|
||||
}
|
||||
|
||||
/** @noinspection PhpExpressionResultUnusedInspection */
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
// Clean up temp directory
|
||||
if (is_dir($this->tempDir)) {
|
||||
$this->removeDirectory($this->tempDir);
|
||||
}
|
||||
|
||||
// Reset static state
|
||||
$reflection = new \ReflectionClass(ArtifactConfig::class);
|
||||
$property = $reflection->getProperty('artifact_configs');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue([]);
|
||||
}
|
||||
|
||||
public function testLoadFromDirThrowsExceptionWhenDirectoryDoesNotExist(): void
|
||||
{
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->expectExceptionMessage('Directory /nonexistent/path does not exist, cannot load artifact config.');
|
||||
|
||||
ArtifactConfig::loadFromDir('/nonexistent/path');
|
||||
}
|
||||
|
||||
public function testLoadFromDirWithValidArtifactJson(): void
|
||||
{
|
||||
$artifactContent = json_encode([
|
||||
'test-artifact' => [
|
||||
'source' => 'https://example.com/file.tar.gz',
|
||||
],
|
||||
]);
|
||||
|
||||
file_put_contents($this->tempDir . '/artifact.json', $artifactContent);
|
||||
|
||||
ArtifactConfig::loadFromDir($this->tempDir);
|
||||
|
||||
$config = ArtifactConfig::get('test-artifact');
|
||||
$this->assertIsArray($config);
|
||||
$this->assertArrayHasKey('source', $config);
|
||||
}
|
||||
|
||||
public function testLoadFromDirWithMultipleArtifactFiles(): void
|
||||
{
|
||||
$artifact1Content = json_encode([
|
||||
'artifact-1' => [
|
||||
'source' => 'https://example.com/file1.tar.gz',
|
||||
],
|
||||
]);
|
||||
|
||||
$artifact2Content = json_encode([
|
||||
'artifact-2' => [
|
||||
'source' => 'https://example.com/file2.tar.gz',
|
||||
],
|
||||
]);
|
||||
|
||||
file_put_contents($this->tempDir . '/artifact.ext.json', $artifact1Content);
|
||||
file_put_contents($this->tempDir . '/artifact.lib.json', $artifact2Content);
|
||||
file_put_contents($this->tempDir . '/artifact.json', json_encode(['artifact-3' => ['source' => 'custom']]));
|
||||
|
||||
ArtifactConfig::loadFromDir($this->tempDir);
|
||||
|
||||
$this->assertNotNull(ArtifactConfig::get('artifact-1'));
|
||||
$this->assertNotNull(ArtifactConfig::get('artifact-2'));
|
||||
$this->assertNotNull(ArtifactConfig::get('artifact-3'));
|
||||
}
|
||||
|
||||
public function testLoadFromFileThrowsExceptionWhenFileCannotBeRead(): void
|
||||
{
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->expectExceptionMessage('Failed to read artifact config file:');
|
||||
|
||||
ArtifactConfig::loadFromFile('/nonexistent/file.json');
|
||||
}
|
||||
|
||||
public function testLoadFromFileThrowsExceptionWhenJsonIsInvalid(): void
|
||||
{
|
||||
$file = $this->tempDir . '/invalid.json';
|
||||
file_put_contents($file, 'not valid json{');
|
||||
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->expectExceptionMessage('Invalid JSON format in artifact config file:');
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithValidJson(): void
|
||||
{
|
||||
$file = $this->tempDir . '/valid.json';
|
||||
$content = json_encode([
|
||||
'my-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'url',
|
||||
'url' => 'https://example.com/file.tar.gz',
|
||||
],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$config = ArtifactConfig::get('my-artifact');
|
||||
$this->assertIsArray($config);
|
||||
$this->assertArrayHasKey('source', $config);
|
||||
}
|
||||
|
||||
public function testGetAllReturnsAllLoadedArtifacts(): void
|
||||
{
|
||||
$file = $this->tempDir . '/artifacts.json';
|
||||
$content = json_encode([
|
||||
'artifact-a' => ['source' => 'custom'],
|
||||
'artifact-b' => ['source' => 'custom'],
|
||||
'artifact-c' => ['source' => 'custom'],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$all = ArtifactConfig::getAll();
|
||||
$this->assertIsArray($all);
|
||||
$this->assertCount(3, $all);
|
||||
$this->assertArrayHasKey('artifact-a', $all);
|
||||
$this->assertArrayHasKey('artifact-b', $all);
|
||||
$this->assertArrayHasKey('artifact-c', $all);
|
||||
}
|
||||
|
||||
public function testGetReturnsNullWhenArtifactNotFound(): void
|
||||
{
|
||||
$this->assertNull(ArtifactConfig::get('non-existent-artifact'));
|
||||
}
|
||||
|
||||
public function testGetReturnsConfigWhenArtifactExists(): void
|
||||
{
|
||||
$file = $this->tempDir . '/artifacts.json';
|
||||
$content = json_encode([
|
||||
'test-artifact' => [
|
||||
'source' => 'custom',
|
||||
'binary' => 'custom',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$config = ArtifactConfig::get('test-artifact');
|
||||
$this->assertIsArray($config);
|
||||
$this->assertEquals('custom', $config['source']);
|
||||
$this->assertIsArray($config['binary']);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithExpandedUrlInSource(): void
|
||||
{
|
||||
$file = $this->tempDir . '/artifacts.json';
|
||||
$content = json_encode([
|
||||
'test-artifact' => [
|
||||
'source' => 'https://example.com/archive.tar.gz',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$config = ArtifactConfig::get('test-artifact');
|
||||
$this->assertIsArray($config);
|
||||
$this->assertIsArray($config['source']);
|
||||
$this->assertEquals('url', $config['source']['type']);
|
||||
$this->assertEquals('https://example.com/archive.tar.gz', $config['source']['url']);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithBinaryCustom(): void
|
||||
{
|
||||
$file = $this->tempDir . '/artifacts.json';
|
||||
$content = json_encode([
|
||||
'test-artifact' => [
|
||||
'source' => 'custom',
|
||||
'binary' => 'custom',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$config = ArtifactConfig::get('test-artifact');
|
||||
$this->assertIsArray($config['binary']);
|
||||
$this->assertArrayHasKey('linux-x86_64', $config['binary']);
|
||||
$this->assertArrayHasKey('macos-aarch64', $config['binary']);
|
||||
$this->assertEquals('custom', $config['binary']['linux-x86_64']['type']);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithBinaryHosted(): void
|
||||
{
|
||||
$file = $this->tempDir . '/artifacts.json';
|
||||
$content = json_encode([
|
||||
'test-artifact' => [
|
||||
'source' => 'custom',
|
||||
'binary' => 'hosted',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$config = ArtifactConfig::get('test-artifact');
|
||||
$this->assertIsArray($config['binary']);
|
||||
$this->assertEquals('hosted', $config['binary']['linux-x86_64']['type']);
|
||||
$this->assertEquals('hosted', $config['binary']['macos-aarch64']['type']);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithBinaryPlatformSpecific(): void
|
||||
{
|
||||
$file = $this->tempDir . '/artifacts.json';
|
||||
$content = json_encode([
|
||||
'test-artifact' => [
|
||||
'source' => 'custom',
|
||||
'binary' => [
|
||||
'linux-x86_64' => 'https://example.com/linux.tar.gz',
|
||||
'macos-aarch64' => [
|
||||
'type' => 'url',
|
||||
'url' => 'https://example.com/macos.tar.gz',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
ArtifactConfig::loadFromFile($file);
|
||||
|
||||
$config = ArtifactConfig::get('test-artifact');
|
||||
$this->assertIsArray($config['binary']);
|
||||
$this->assertEquals('url', $config['binary']['linux-x86_64']['type']);
|
||||
$this->assertEquals('https://example.com/linux.tar.gz', $config['binary']['linux-x86_64']['url']);
|
||||
$this->assertEquals('url', $config['binary']['macos-aarch64']['type']);
|
||||
$this->assertEquals('https://example.com/macos.tar.gz', $config['binary']['macos-aarch64']['url']);
|
||||
}
|
||||
|
||||
public function testLoadFromDirWithEmptyDirectory(): void
|
||||
{
|
||||
// Empty directory should not throw exception
|
||||
ArtifactConfig::loadFromDir($this->tempDir);
|
||||
|
||||
$this->assertEquals([], ArtifactConfig::getAll());
|
||||
}
|
||||
|
||||
public function testMultipleLoadsAppendConfigs(): void
|
||||
{
|
||||
$file1 = $this->tempDir . '/artifact1.json';
|
||||
$file2 = $this->tempDir . '/artifact2.json';
|
||||
|
||||
file_put_contents($file1, json_encode(['art1' => ['source' => 'custom']]));
|
||||
file_put_contents($file2, json_encode(['art2' => ['source' => 'custom']]));
|
||||
|
||||
ArtifactConfig::loadFromFile($file1);
|
||||
ArtifactConfig::loadFromFile($file2);
|
||||
|
||||
$all = ArtifactConfig::getAll();
|
||||
$this->assertCount(2, $all);
|
||||
$this->assertArrayHasKey('art1', $all);
|
||||
$this->assertArrayHasKey('art2', $all);
|
||||
}
|
||||
|
||||
private function removeDirectory(string $dir): void
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
$files = array_diff(scandir($dir), ['.', '..']);
|
||||
foreach ($files as $file) {
|
||||
$path = $dir . '/' . $file;
|
||||
is_dir($path) ? $this->removeDirectory($path) : unlink($path);
|
||||
}
|
||||
rmdir($dir);
|
||||
}
|
||||
}
|
||||
196
tests/StaticPHP/Config/ConfigTypeTest.php
Normal file
196
tests/StaticPHP/Config/ConfigTypeTest.php
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\StaticPHP\Config;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use StaticPHP\Config\ConfigType;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ConfigTypeTest extends TestCase
|
||||
{
|
||||
public function testConstantValues(): void
|
||||
{
|
||||
$this->assertEquals('list_array', ConfigType::LIST_ARRAY);
|
||||
$this->assertEquals('assoc_array', ConfigType::ASSOC_ARRAY);
|
||||
$this->assertEquals('string', ConfigType::STRING);
|
||||
$this->assertEquals('bool', ConfigType::BOOL);
|
||||
}
|
||||
|
||||
public function testPackageTypesConstant(): void
|
||||
{
|
||||
$expectedTypes = [
|
||||
'library',
|
||||
'php-extension',
|
||||
'target',
|
||||
'virtual-target',
|
||||
];
|
||||
|
||||
$this->assertEquals($expectedTypes, ConfigType::PACKAGE_TYPES);
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithValidFileType(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'file',
|
||||
'path' => 'LICENSE',
|
||||
];
|
||||
|
||||
$this->assertTrue(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithValidFileTypeArrayPath(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'file',
|
||||
'path' => ['LICENSE', 'COPYING'],
|
||||
];
|
||||
|
||||
$this->assertTrue(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithValidTextType(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'text',
|
||||
'text' => 'MIT License',
|
||||
];
|
||||
|
||||
$this->assertTrue(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithListOfLicenses(): void
|
||||
{
|
||||
$licenses = [
|
||||
[
|
||||
'type' => 'file',
|
||||
'path' => 'LICENSE',
|
||||
],
|
||||
[
|
||||
'type' => 'text',
|
||||
'text' => 'MIT',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertTrue(ConfigType::validateLicenseField($licenses));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithEmptyList(): void
|
||||
{
|
||||
$licenses = [];
|
||||
|
||||
$this->assertTrue(ConfigType::validateLicenseField($licenses));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWhenNotAssocArray(): void
|
||||
{
|
||||
$this->assertFalse(ConfigType::validateLicenseField('string'));
|
||||
$this->assertFalse(ConfigType::validateLicenseField(123));
|
||||
$this->assertFalse(ConfigType::validateLicenseField(true));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWhenMissingType(): void
|
||||
{
|
||||
$license = [
|
||||
'path' => 'LICENSE',
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWithInvalidType(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'invalid',
|
||||
'data' => 'something',
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWhenFileTypeMissingPath(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'file',
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWhenFileTypePathIsInvalid(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'file',
|
||||
'path' => 123,
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWhenTextTypeMissingText(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'text',
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldReturnsFalseWhenTextTypeTextIsNotString(): void
|
||||
{
|
||||
$license = [
|
||||
'type' => 'text',
|
||||
'text' => ['array'],
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($license));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithListContainingInvalidItem(): void
|
||||
{
|
||||
$licenses = [
|
||||
[
|
||||
'type' => 'file',
|
||||
'path' => 'LICENSE',
|
||||
],
|
||||
[
|
||||
'type' => 'text',
|
||||
// missing 'text' field
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($licenses));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithNestedListsOfLicenses(): void
|
||||
{
|
||||
$licenses = [
|
||||
[
|
||||
[
|
||||
'type' => 'file',
|
||||
'path' => 'LICENSE',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertTrue(ConfigType::validateLicenseField($licenses));
|
||||
}
|
||||
|
||||
public function testValidateLicenseFieldWithNestedListContainingInvalidItem(): void
|
||||
{
|
||||
$licenses = [
|
||||
[
|
||||
[
|
||||
'type' => 'file',
|
||||
'path' => 'LICENSE',
|
||||
],
|
||||
'invalid-string-item',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertFalse(ConfigType::validateLicenseField($licenses));
|
||||
}
|
||||
}
|
||||
627
tests/StaticPHP/Config/ConfigValidatorTest.php
Normal file
627
tests/StaticPHP/Config/ConfigValidatorTest.php
Normal file
@@ -0,0 +1,627 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\StaticPHP\Config;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use StaticPHP\Config\ConfigValidator;
|
||||
use StaticPHP\Exception\ValidationException;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ConfigValidatorTest extends TestCase
|
||||
{
|
||||
public function testValidateAndLintArtifactsThrowsExceptionWhenDataIsNotArray(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('test.json is broken');
|
||||
|
||||
$data = 'not an array';
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithCustomSource(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => 'custom',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertEquals('custom', $data['test-artifact']['source']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsExpandsUrlString(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => 'https://example.com/file.tar.gz',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['source']);
|
||||
$this->assertEquals('url', $data['test-artifact']['source']['type']);
|
||||
$this->assertEquals('https://example.com/file.tar.gz', $data['test-artifact']['source']['url']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsExpandsHttpUrlString(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => 'http://example.com/file.tar.gz',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['source']);
|
||||
$this->assertEquals('url', $data['test-artifact']['source']['type']);
|
||||
$this->assertEquals('http://example.com/file.tar.gz', $data['test-artifact']['source']['url']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithSourceObject(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'git',
|
||||
'url' => 'https://github.com/example/repo.git',
|
||||
'rev' => 'main',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['source']);
|
||||
$this->assertEquals('git', $data['test-artifact']['source']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithBinaryCustom(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'binary' => 'custom',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['binary']);
|
||||
$this->assertArrayHasKey('linux-x86_64', $data['test-artifact']['binary']);
|
||||
$this->assertEquals('custom', $data['test-artifact']['binary']['linux-x86_64']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithBinaryHosted(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'binary' => 'hosted',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['binary']);
|
||||
$this->assertArrayHasKey('macos-aarch64', $data['test-artifact']['binary']);
|
||||
$this->assertEquals('hosted', $data['test-artifact']['binary']['macos-aarch64']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithBinaryPlatformObject(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'binary' => [
|
||||
'linux-x86_64' => [
|
||||
'type' => 'url',
|
||||
'url' => 'https://example.com/binary.tar.gz',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertEquals('url', $data['test-artifact']['binary']['linux-x86_64']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsExpandsBinaryPlatformUrlString(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'binary' => [
|
||||
'linux-x86_64' => 'https://example.com/binary.tar.gz',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['binary']['linux-x86_64']);
|
||||
$this->assertEquals('url', $data['test-artifact']['binary']['linux-x86_64']['type']);
|
||||
$this->assertEquals('https://example.com/binary.tar.gz', $data['test-artifact']['binary']['linux-x86_64']['url']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithSourceMirror(): void
|
||||
{
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source-mirror' => 'https://mirror.example.com/file.tar.gz',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-artifact']['source-mirror']);
|
||||
$this->assertEquals('url', $data['test-artifact']['source-mirror']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenDataIsNotArray(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('pkg.json is broken');
|
||||
|
||||
$data = 'not an array';
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenPackageIsNotAssocArray(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package [test-pkg] in pkg.json is not a valid associative array');
|
||||
|
||||
$data = [
|
||||
'test-pkg' => ['list', 'array'],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenTypeMissing(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Package [test-pkg] in pkg.json has invalid or missing 'type' field");
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'depends' => [],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenTypeInvalid(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Package [test-pkg] in pkg.json has invalid or missing 'type' field");
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'invalid-type',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithValidLibraryType(): void
|
||||
{
|
||||
$data = [
|
||||
'test-lib' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test-artifact',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertEquals('library', $data['test-lib']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithValidPhpExtensionType(): void
|
||||
{
|
||||
$data = [
|
||||
'test-ext' => [
|
||||
'type' => 'php-extension',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertEquals('php-extension', $data['test-ext']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithValidTargetType(): void
|
||||
{
|
||||
$data = [
|
||||
'test-target' => [
|
||||
'type' => 'target',
|
||||
'artifact' => 'test-artifact',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertEquals('target', $data['test-target']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithValidVirtualTargetType(): void
|
||||
{
|
||||
$data = [
|
||||
'test-virtual' => [
|
||||
'type' => 'virtual-target',
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertEquals('virtual-target', $data['test-virtual']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenLibraryMissingArtifact(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Package [test-lib] in pkg.json of type 'library' must have an 'artifact' field");
|
||||
|
||||
$data = [
|
||||
'test-lib' => [
|
||||
'type' => 'library',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenTargetMissingArtifact(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Package [test-target] in pkg.json of type 'target' must have an 'artifact' field");
|
||||
|
||||
$data = [
|
||||
'test-target' => [
|
||||
'type' => 'target',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithPhpExtensionFields(): void
|
||||
{
|
||||
$data = [
|
||||
'test-ext' => [
|
||||
'type' => 'php-extension',
|
||||
'php-extension' => [
|
||||
'zend-extension' => false,
|
||||
'build-shared' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-ext']['php-extension']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenPhpExtensionIsNotObject(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package test-ext [php-extension] must be an object');
|
||||
|
||||
$data = [
|
||||
'test-ext' => [
|
||||
'type' => 'php-extension',
|
||||
'php-extension' => 'string',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithDependsField(): void
|
||||
{
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends' => ['dep1', 'dep2'],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-pkg']['depends']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionWhenDependsIsNotList(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package test-pkg [depends] must be a list');
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends' => 'not-a-list',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithSuffixFields(): void
|
||||
{
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends@linux' => ['linux-dep'],
|
||||
'depends@windows' => ['windows-dep'],
|
||||
'headers@unix' => ['header.h'],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertIsArray($data['test-pkg']['depends@linux']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionForInvalidSuffixFieldType(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package test-pkg [headers@linux] must be a list');
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'headers@linux' => 'not-a-list',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionForUnknownField(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('package [test-pkg] has invalid field [unknown-field]');
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'unknown-field' => 'value',
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionForUnknownPhpExtensionField(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('php-extension [test-ext] has invalid field [unknown]');
|
||||
|
||||
$data = [
|
||||
'test-ext' => [
|
||||
'type' => 'php-extension',
|
||||
'php-extension' => [
|
||||
'unknown' => 'value',
|
||||
],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidatePlatformStringWithValidPlatforms(): void
|
||||
{
|
||||
ConfigValidator::validatePlatformString('linux-x86_64');
|
||||
ConfigValidator::validatePlatformString('linux-aarch64');
|
||||
ConfigValidator::validatePlatformString('windows-x86_64');
|
||||
ConfigValidator::validatePlatformString('windows-aarch64');
|
||||
ConfigValidator::validatePlatformString('macos-x86_64');
|
||||
ConfigValidator::validatePlatformString('macos-aarch64');
|
||||
|
||||
$this->assertTrue(true); // If no exception thrown, test passes
|
||||
}
|
||||
|
||||
public function testValidatePlatformStringThrowsExceptionForInvalidFormat(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Invalid platform format 'invalid', expected format 'os-arch'");
|
||||
|
||||
ConfigValidator::validatePlatformString('invalid');
|
||||
}
|
||||
|
||||
public function testValidatePlatformStringThrowsExceptionForTooManyParts(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Invalid platform format 'linux-x86_64-extra', expected format 'os-arch'");
|
||||
|
||||
ConfigValidator::validatePlatformString('linux-x86_64-extra');
|
||||
}
|
||||
|
||||
public function testValidatePlatformStringThrowsExceptionForInvalidOS(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Invalid platform OS 'bsd' in platform 'bsd-x86_64'");
|
||||
|
||||
ConfigValidator::validatePlatformString('bsd-x86_64');
|
||||
}
|
||||
|
||||
public function testValidatePlatformStringThrowsExceptionForInvalidArch(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Invalid platform architecture 'arm' in platform 'linux-arm'");
|
||||
|
||||
ConfigValidator::validatePlatformString('linux-arm');
|
||||
}
|
||||
|
||||
public function testArtifactTypeFieldsConstant(): void
|
||||
{
|
||||
$this->assertArrayHasKey('filelist', ConfigValidator::ARTIFACT_TYPE_FIELDS);
|
||||
$this->assertArrayHasKey('git', ConfigValidator::ARTIFACT_TYPE_FIELDS);
|
||||
$this->assertArrayHasKey('ghtagtar', ConfigValidator::ARTIFACT_TYPE_FIELDS);
|
||||
$this->assertArrayHasKey('url', ConfigValidator::ARTIFACT_TYPE_FIELDS);
|
||||
$this->assertArrayHasKey('custom', ConfigValidator::ARTIFACT_TYPE_FIELDS);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsThrowsExceptionForInvalidArtifactType(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Artifact source object has unknown type 'invalid-type'");
|
||||
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'invalid-type',
|
||||
],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsThrowsExceptionForMissingRequiredField(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Artifact source object of type 'git' must have required field 'url'");
|
||||
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'git',
|
||||
'rev' => 'main',
|
||||
// missing 'url'
|
||||
],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsThrowsExceptionForMissingTypeInSource(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage("Artifact source object must have a valid 'type' field");
|
||||
|
||||
$data = [
|
||||
'test-artifact' => [
|
||||
'source' => [
|
||||
'url' => 'https://example.com',
|
||||
],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintArtifactsWithAllArtifactTypes(): void
|
||||
{
|
||||
$data = [
|
||||
'filelist-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'filelist',
|
||||
'url' => 'https://example.com/list',
|
||||
'regex' => '/pattern/',
|
||||
],
|
||||
],
|
||||
'git-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'git',
|
||||
'url' => 'https://github.com/example/repo.git',
|
||||
'rev' => 'main',
|
||||
],
|
||||
],
|
||||
'ghtagtar-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'ghtagtar',
|
||||
'repo' => 'example/repo',
|
||||
],
|
||||
],
|
||||
'url-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'url',
|
||||
'url' => 'https://example.com/file.tar.gz',
|
||||
],
|
||||
],
|
||||
'custom-artifact' => [
|
||||
'source' => [
|
||||
'type' => 'custom',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintArtifacts('test.json', $data);
|
||||
|
||||
$this->assertIsArray($data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesWithAllFieldTypes(): void
|
||||
{
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test-artifact',
|
||||
'depends' => ['dep1'],
|
||||
'suggests' => ['sug1'],
|
||||
'license' => [
|
||||
'type' => 'file',
|
||||
'path' => 'LICENSE',
|
||||
],
|
||||
'lang' => 'c',
|
||||
'frameworks' => ['framework1'],
|
||||
'headers' => ['header.h'],
|
||||
'static-libs' => ['lib.a'],
|
||||
'pkg-configs' => ['pkg.pc'],
|
||||
'static-bins' => ['bin'],
|
||||
],
|
||||
];
|
||||
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
|
||||
$this->assertEquals('library', $data['test-pkg']['type']);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionForWrongTypeString(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package test-pkg [artifact] must be string');
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => ['not', 'a', 'string'],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionForWrongTypeBool(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package test-ext [zend-extension] must be boolean');
|
||||
|
||||
$data = [
|
||||
'test-ext' => [
|
||||
'type' => 'php-extension',
|
||||
'php-extension' => [
|
||||
'zend-extension' => 'not-a-bool',
|
||||
],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
|
||||
public function testValidateAndLintPackagesThrowsExceptionForWrongTypeAssocArray(): void
|
||||
{
|
||||
$this->expectException(ValidationException::class);
|
||||
$this->expectExceptionMessage('Package test-pkg [support] must be an object');
|
||||
|
||||
$data = [
|
||||
'test-pkg' => [
|
||||
'type' => 'php-extension',
|
||||
'php-extension' => [
|
||||
'support' => 'not-an-object',
|
||||
],
|
||||
],
|
||||
];
|
||||
ConfigValidator::validateAndLintPackages('pkg.json', $data);
|
||||
}
|
||||
}
|
||||
434
tests/StaticPHP/Config/PackageConfigTest.php
Normal file
434
tests/StaticPHP/Config/PackageConfigTest.php
Normal file
@@ -0,0 +1,434 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\StaticPHP\Config;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use StaticPHP\Config\PackageConfig;
|
||||
use StaticPHP\Exception\WrongUsageException;
|
||||
use StaticPHP\Runtime\SystemTarget;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class PackageConfigTest extends TestCase
|
||||
{
|
||||
private string $tempDir;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->tempDir = sys_get_temp_dir() . '/package_config_test_' . uniqid();
|
||||
mkdir($this->tempDir, 0755, true);
|
||||
|
||||
// Reset static state
|
||||
$reflection = new \ReflectionClass(PackageConfig::class);
|
||||
$property = $reflection->getProperty('package_configs');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue([]);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
// Clean up temp directory
|
||||
if (is_dir($this->tempDir)) {
|
||||
$this->removeDirectory($this->tempDir);
|
||||
}
|
||||
|
||||
// Reset static state
|
||||
$reflection = new \ReflectionClass(PackageConfig::class);
|
||||
$property = $reflection->getProperty('package_configs');
|
||||
$property->setAccessible(true);
|
||||
$property->setValue([]);
|
||||
}
|
||||
|
||||
public function testLoadFromDirThrowsExceptionWhenDirectoryDoesNotExist(): void
|
||||
{
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->expectExceptionMessage('Directory /nonexistent/path does not exist, cannot load pkg.json config.');
|
||||
|
||||
PackageConfig::loadFromDir('/nonexistent/path');
|
||||
}
|
||||
|
||||
public function testLoadFromDirWithValidPkgJson(): void
|
||||
{
|
||||
$packageContent = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test-artifact',
|
||||
],
|
||||
]);
|
||||
|
||||
file_put_contents($this->tempDir . '/pkg.json', $packageContent);
|
||||
|
||||
PackageConfig::loadFromDir($this->tempDir);
|
||||
|
||||
$this->assertTrue(PackageConfig::isPackageExists('test-pkg'));
|
||||
}
|
||||
|
||||
public function testLoadFromDirWithMultiplePackageFiles(): void
|
||||
{
|
||||
$pkg1Content = json_encode([
|
||||
'pkg-1' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'artifact-1',
|
||||
],
|
||||
]);
|
||||
|
||||
$pkg2Content = json_encode([
|
||||
'pkg-2' => [
|
||||
'type' => 'php-extension',
|
||||
],
|
||||
]);
|
||||
|
||||
file_put_contents($this->tempDir . '/pkg.ext.json', $pkg1Content);
|
||||
file_put_contents($this->tempDir . '/pkg.lib.json', $pkg2Content);
|
||||
file_put_contents($this->tempDir . '/pkg.json', json_encode(['pkg-3' => ['type' => 'virtual-target']]));
|
||||
|
||||
PackageConfig::loadFromDir($this->tempDir);
|
||||
|
||||
$this->assertTrue(PackageConfig::isPackageExists('pkg-1'));
|
||||
$this->assertTrue(PackageConfig::isPackageExists('pkg-2'));
|
||||
$this->assertTrue(PackageConfig::isPackageExists('pkg-3'));
|
||||
}
|
||||
|
||||
public function testLoadFromFileThrowsExceptionWhenFileCannotBeRead(): void
|
||||
{
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->expectExceptionMessage('Failed to read package config file:');
|
||||
|
||||
PackageConfig::loadFromFile('/nonexistent/file.json');
|
||||
}
|
||||
|
||||
public function testLoadFromFileThrowsExceptionWhenJsonIsInvalid(): void
|
||||
{
|
||||
$file = $this->tempDir . '/invalid.json';
|
||||
file_put_contents($file, 'not valid json{');
|
||||
|
||||
$this->expectException(WrongUsageException::class);
|
||||
$this->expectExceptionMessage('Invalid JSON format in package config file:');
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithValidJson(): void
|
||||
{
|
||||
$file = $this->tempDir . '/valid.json';
|
||||
$content = json_encode([
|
||||
'my-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'my-artifact',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$this->assertTrue(PackageConfig::isPackageExists('my-pkg'));
|
||||
}
|
||||
|
||||
public function testIsPackageExistsReturnsFalseWhenPackageNotLoaded(): void
|
||||
{
|
||||
$this->assertFalse(PackageConfig::isPackageExists('non-existent'));
|
||||
}
|
||||
|
||||
public function testIsPackageExistsReturnsTrueWhenPackageLoaded(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$this->assertTrue(PackageConfig::isPackageExists('test-pkg'));
|
||||
}
|
||||
|
||||
public function testGetAllReturnsAllLoadedPackages(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'pkg-a' => ['type' => 'virtual-target'],
|
||||
'pkg-b' => ['type' => 'virtual-target'],
|
||||
'pkg-c' => ['type' => 'virtual-target'],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$all = PackageConfig::getAll();
|
||||
$this->assertIsArray($all);
|
||||
$this->assertCount(3, $all);
|
||||
$this->assertArrayHasKey('pkg-a', $all);
|
||||
$this->assertArrayHasKey('pkg-b', $all);
|
||||
$this->assertArrayHasKey('pkg-c', $all);
|
||||
}
|
||||
|
||||
public function testGetReturnsDefaultWhenPackageNotExists(): void
|
||||
{
|
||||
$result = PackageConfig::get('non-existent', 'field', 'default-value');
|
||||
|
||||
$this->assertEquals('default-value', $result);
|
||||
}
|
||||
|
||||
public function testGetReturnsWholePackageWhenFieldNameIsNull(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends' => ['dep1'],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$result = PackageConfig::get('test-pkg');
|
||||
$this->assertIsArray($result);
|
||||
$this->assertEquals('library', $result['type']);
|
||||
$this->assertEquals('test', $result['artifact']);
|
||||
}
|
||||
|
||||
public function testGetReturnsFieldValueWhenFieldExists(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test-artifact',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$result = PackageConfig::get('test-pkg', 'artifact');
|
||||
$this->assertEquals('test-artifact', $result);
|
||||
}
|
||||
|
||||
public function testGetReturnsDefaultWhenFieldNotExists(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$result = PackageConfig::get('test-pkg', 'non-existent-field', 'default');
|
||||
$this->assertEquals('default', $result);
|
||||
}
|
||||
|
||||
public function testGetWithSuffixFieldsOnLinux(): void
|
||||
{
|
||||
// Mock SystemTarget to return Linux
|
||||
$mockTarget = $this->getMockBuilder(SystemTarget::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends' => ['base-dep'],
|
||||
'depends@linux' => ['linux-dep'],
|
||||
'depends@unix' => ['unix-dep'],
|
||||
'depends@windows' => ['windows-dep'],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
// The get method will check SystemTarget::getTargetOS()
|
||||
// On real Linux systems, it should return 'depends@linux' first
|
||||
$result = PackageConfig::get('test-pkg', 'depends', []);
|
||||
|
||||
// Result should be one of the suffixed versions or base version
|
||||
$this->assertIsArray($result);
|
||||
}
|
||||
|
||||
public function testGetWithSuffixFieldsReturnsBasicFieldWhenNoSuffixMatch(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends' => ['base-dep'],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$result = PackageConfig::get('test-pkg', 'depends');
|
||||
$this->assertEquals(['base-dep'], $result);
|
||||
}
|
||||
|
||||
public function testGetWithNonSuffixedFieldIgnoresSuffixes(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test-artifact',
|
||||
'artifact@linux' => 'linux-artifact', // This should be ignored
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
// 'artifact' is not in SUFFIX_ALLOWED_FIELDS, so it won't check suffixes
|
||||
$result = PackageConfig::get('test-pkg', 'artifact');
|
||||
$this->assertEquals('test-artifact', $result);
|
||||
}
|
||||
|
||||
public function testGetAllSuffixAllowedFields(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'test',
|
||||
'depends@linux' => ['dep1'],
|
||||
'suggests@macos' => ['sug1'],
|
||||
'headers@unix' => ['header.h'],
|
||||
'static-libs@windows' => ['lib.a'],
|
||||
'static-bins@linux' => ['bin'],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
// These are all suffix-allowed fields
|
||||
$pkg = PackageConfig::get('test-pkg');
|
||||
$this->assertArrayHasKey('depends@linux', $pkg);
|
||||
$this->assertArrayHasKey('suggests@macos', $pkg);
|
||||
$this->assertArrayHasKey('headers@unix', $pkg);
|
||||
$this->assertArrayHasKey('static-libs@windows', $pkg);
|
||||
$this->assertArrayHasKey('static-bins@linux', $pkg);
|
||||
}
|
||||
|
||||
public function testLoadFromDirWithEmptyDirectory(): void
|
||||
{
|
||||
// Empty directory should not throw exception
|
||||
PackageConfig::loadFromDir($this->tempDir);
|
||||
|
||||
$this->assertEquals([], PackageConfig::getAll());
|
||||
}
|
||||
|
||||
public function testMultipleLoadsAppendConfigs(): void
|
||||
{
|
||||
$file1 = $this->tempDir . '/pkg1.json';
|
||||
$file2 = $this->tempDir . '/pkg2.json';
|
||||
|
||||
file_put_contents($file1, json_encode(['pkg1' => ['type' => 'virtual-target']]));
|
||||
file_put_contents($file2, json_encode(['pkg2' => ['type' => 'virtual-target']]));
|
||||
|
||||
PackageConfig::loadFromFile($file1);
|
||||
PackageConfig::loadFromFile($file2);
|
||||
|
||||
$all = PackageConfig::getAll();
|
||||
$this->assertCount(2, $all);
|
||||
$this->assertArrayHasKey('pkg1', $all);
|
||||
$this->assertArrayHasKey('pkg2', $all);
|
||||
}
|
||||
|
||||
public function testGetWithComplexPhpExtensionPackage(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-ext' => [
|
||||
'type' => 'php-extension',
|
||||
'depends' => ['dep1'],
|
||||
'php-extension' => [
|
||||
'zend-extension' => false,
|
||||
'build-shared' => true,
|
||||
'build-static' => false,
|
||||
],
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$phpExt = PackageConfig::get('test-ext', 'php-extension');
|
||||
$this->assertIsArray($phpExt);
|
||||
$this->assertFalse($phpExt['zend-extension']);
|
||||
$this->assertTrue($phpExt['build-shared']);
|
||||
}
|
||||
|
||||
public function testGetReturnsNullAsDefaultWhenNotSpecified(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'test-pkg' => [
|
||||
'type' => 'virtual-target',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$result = PackageConfig::get('test-pkg', 'non-existent');
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
public function testLoadFromFileWithAllPackageTypes(): void
|
||||
{
|
||||
$file = $this->tempDir . '/pkg.json';
|
||||
$content = json_encode([
|
||||
'library-pkg' => [
|
||||
'type' => 'library',
|
||||
'artifact' => 'lib-artifact',
|
||||
],
|
||||
'extension-pkg' => [
|
||||
'type' => 'php-extension',
|
||||
],
|
||||
'target-pkg' => [
|
||||
'type' => 'target',
|
||||
'artifact' => 'target-artifact',
|
||||
],
|
||||
'virtual-pkg' => [
|
||||
'type' => 'virtual-target',
|
||||
],
|
||||
]);
|
||||
file_put_contents($file, $content);
|
||||
|
||||
PackageConfig::loadFromFile($file);
|
||||
|
||||
$this->assertTrue(PackageConfig::isPackageExists('library-pkg'));
|
||||
$this->assertTrue(PackageConfig::isPackageExists('extension-pkg'));
|
||||
$this->assertTrue(PackageConfig::isPackageExists('target-pkg'));
|
||||
$this->assertTrue(PackageConfig::isPackageExists('virtual-pkg'));
|
||||
}
|
||||
|
||||
private function removeDirectory(string $dir): void
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
$files = array_diff(scandir($dir), ['.', '..']);
|
||||
foreach ($files as $file) {
|
||||
$path = $dir . '/' . $file;
|
||||
is_dir($path) ? $this->removeDirectory($path) : unlink($path);
|
||||
}
|
||||
rmdir($dir);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user