* Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Test\Package\Loader; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; use Composer\Package\Link; use Composer\Test\TestCase; class ArrayLoaderTest extends TestCase { /** * @var ArrayLoader */ private $loader; public function setUp(): void { $this->loader = new ArrayLoader(null); } public function testSelfVersion(): void { $config = array( 'name' => 'A', 'version' => '1.2.3.4', 'replace' => array( 'foo' => 'self.version', ), ); $package = $this->loader->load($config); $replaces = $package->getReplaces(); $this->assertEquals('== 1.2.3.4', (string) $replaces['foo']->getConstraint()); } public function testTypeDefault(): void { $config = array( 'name' => 'A', 'version' => '1.0', ); $package = $this->loader->load($config); $this->assertEquals('library', $package->getType()); $config = array( 'name' => 'A', 'version' => '1.0', 'type' => 'foo', ); $package = $this->loader->load($config); $this->assertEquals('foo', $package->getType()); } public function testNormalizedVersionOptimization(): void { $config = array( 'name' => 'A', 'version' => '1.2.3', ); $package = $this->loader->load($config); $this->assertEquals('1.2.3.0', $package->getVersion()); $config = array( 'name' => 'A', 'version' => '1.2.3', 'version_normalized' => '1.2.3.4', ); $package = $this->loader->load($config); $this->assertEquals('1.2.3.4', $package->getVersion()); } public function parseDumpProvider(): array { $validConfig = array( 'name' => 'A/B', 'version' => '1.2.3', 'version_normalized' => '1.2.3.0', 'description' => 'Foo bar', 'type' => 'library', 'keywords' => array('a', 'b', 'c'), 'homepage' => 'http://example.com', 'license' => array('MIT', 'GPLv3'), 'authors' => array( array('name' => 'Bob', 'email' => 'bob@example.org', 'homepage' => 'example.org', 'role' => 'Developer'), ), 'funding' => array( array('type' => 'example', 'url' => 'https://example.org/fund'), ), 'require' => array( 'foo/bar' => '1.0', ), 'require-dev' => array( 'foo/baz' => '1.0', ), 'replace' => array( 'foo/qux' => '1.0', ), 'conflict' => array( 'foo/quux' => '1.0', ), 'provide' => array( 'foo/quuux' => '1.0', ), 'autoload' => array( 'psr-0' => array('Ns\Prefix' => 'path'), 'classmap' => array('path', 'path2'), ), 'include-path' => array('path3', 'path4'), 'target-dir' => 'some/prefix', 'extra' => array('random' => array('things' => 'of', 'any' => 'shape')), 'bin' => array('bin1', 'bin/foo'), 'archive' => array( 'exclude' => array('/foo/bar', 'baz', '!/foo/bar/baz'), ), 'transport-options' => array('ssl' => array('local_cert' => '/opt/certs/test.pem')), 'abandoned' => 'foo/bar', ); return array(array($validConfig)); } /** * @param array $config * * @return array */ protected function fixConfigWhenLoadConfigIsFalse(array $config): array { $expectedConfig = $config; unset($expectedConfig['transport-options']); return $expectedConfig; } /** * The default parser should default to loading the config as this * allows require-dev libraries to have transport options included. * * @dataProvider parseDumpProvider * * @param array $config */ public function testParseDumpDefaultLoadConfig(array $config): void { $package = $this->loader->load($config); $dumper = new ArrayDumper; $expectedConfig = $this->fixConfigWhenLoadConfigIsFalse($config); $this->assertEquals($expectedConfig, $dumper->dump($package)); } /** * @dataProvider parseDumpProvider * * @param array $config */ public function testParseDumpTrueLoadConfig(array $config): void { $loader = new ArrayLoader(null, true); $package = $loader->load($config); $dumper = new ArrayDumper; $expectedConfig = $config; $this->assertEquals($expectedConfig, $dumper->dump($package)); } /** * @dataProvider parseDumpProvider * * @param array $config */ public function testParseDumpFalseLoadConfig(array $config): void { $loader = new ArrayLoader(null, false); $package = $loader->load($config); $dumper = new ArrayDumper; $expectedConfig = $this->fixConfigWhenLoadConfigIsFalse($config); $this->assertEquals($expectedConfig, $dumper->dump($package)); } public function testPackageWithBranchAlias(): void { $config = array( 'name' => 'A', 'version' => 'dev-master', 'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')), ); $package = $this->loader->load($config); $this->assertInstanceOf('Composer\Package\AliasPackage', $package); $this->assertEquals('1.0.x-dev', $package->getPrettyVersion()); $config = array( 'name' => 'A', 'version' => 'dev-master', 'extra' => array('branch-alias' => array('dev-master' => '1.0-dev')), ); $package = $this->loader->load($config); $this->assertInstanceOf('Composer\Package\AliasPackage', $package); $this->assertEquals('1.0.x-dev', $package->getPrettyVersion()); $config = array( 'name' => 'B', 'version' => '4.x-dev', 'extra' => array('branch-alias' => array('4.x-dev' => '4.0.x-dev')), ); $package = $this->loader->load($config); $this->assertInstanceOf('Composer\Package\AliasPackage', $package); $this->assertEquals('4.0.x-dev', $package->getPrettyVersion()); $config = array( 'name' => 'B', 'version' => '4.x-dev', 'extra' => array('branch-alias' => array('4.x-dev' => '4.0-dev')), ); $package = $this->loader->load($config); $this->assertInstanceOf('Composer\Package\AliasPackage', $package); $this->assertEquals('4.0.x-dev', $package->getPrettyVersion()); $config = array( 'name' => 'C', 'version' => '4.x-dev', 'extra' => array('branch-alias' => array('4.x-dev' => '3.4.x-dev')), ); $package = $this->loader->load($config); $this->assertInstanceOf('Composer\Package\CompletePackage', $package); $this->assertEquals('4.x-dev', $package->getPrettyVersion()); } public function testAbandoned(): void { $config = array( 'name' => 'A', 'version' => '1.2.3.4', 'abandoned' => 'foo/bar', ); $package = $this->loader->load($config); $this->assertTrue($package->isAbandoned()); $this->assertEquals('foo/bar', $package->getReplacementPackage()); } public function testNotAbandoned(): void { $config = array( 'name' => 'A', 'version' => '1.2.3.4', ); $package = $this->loader->load($config); $this->assertFalse($package->isAbandoned()); } public function providePluginApiVersions(): array { return array( array('1.0'), array('1.0.0'), array('1.0.0.0'), array('1'), array('=1.0.0'), array('==1.0'), array('~1.0.0'), array('*'), array('3.0.*'), array('@stable'), array('1.0.0@stable'), array('^5.1'), array('>=1.0.0 <2.5'), array('x'), array('1.0.0-dev'), ); } /** * @dataProvider providePluginApiVersions * * @param string $apiVersion */ public function testPluginApiVersionAreKeptAsDeclared(string $apiVersion): void { $links = $this->loader->parseLinks('Plugin', '9.9.9', Link::TYPE_REQUIRE, array('composer-plugin-api' => $apiVersion)); $this->assertArrayHasKey('composer-plugin-api', $links); $this->assertSame($apiVersion, $links['composer-plugin-api']->getConstraint()->getPrettyString()); } public function testPluginApiVersionDoesSupportSelfVersion(): void { $links = $this->loader->parseLinks('Plugin', '6.6.6', Link::TYPE_REQUIRE, array('composer-plugin-api' => 'self.version')); $this->assertArrayHasKey('composer-plugin-api', $links); $this->assertSame('6.6.6', $links['composer-plugin-api']->getConstraint()->getPrettyString()); } public function testNoneStringVersion(): void { $config = array( 'name' => 'acme/package', 'version' => 1, ); $package = $this->loader->load($config); $this->assertSame('1', $package->getPrettyVersion()); } }