2012-07-18 15:20:01 +00:00
< ? php
/*
* This file is part of Composer .
*
* ( c ) Nils Adermann < naderman @ naderman . de >
* Jordi Boggiano < j . boggiano @ seld . be >
*
* 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\ValidatingArrayLoader ;
2012-11-02 14:14:09 +00:00
use Composer\Package\Loader\InvalidPackageException ;
2020-02-07 03:18:45 +00:00
use Composer\Test\TestCase ;
2012-07-18 15:20:01 +00:00
2017-11-04 14:52:13 +00:00
class ValidatingArrayLoaderTest extends TestCase
2012-07-18 15:20:01 +00:00
{
/**
* @ dataProvider successProvider
2021-11-01 20:44:12 +00:00
*
* @ param array < string , mixed > $config
2012-07-18 15:20:01 +00:00
*/
2022-02-18 09:38:54 +00:00
public function testLoadSuccess ( $config ) : void
2012-07-18 15:20:01 +00:00
{
2018-04-12 08:24:56 +00:00
$internalLoader = $this -> getMockBuilder ( 'Composer\Package\Loader\LoaderInterface' ) -> getMock ();
2012-07-18 15:20:01 +00:00
$internalLoader
-> expects ( $this -> once ())
-> method ( 'load' )
-> with ( $config );
2014-04-09 13:23:43 +00:00
$loader = new ValidatingArrayLoader ( $internalLoader , true , null , ValidatingArrayLoader :: CHECK_ALL );
2012-07-18 15:20:01 +00:00
$loader -> load ( $config );
}
2022-02-21 12:42:28 +00:00
public function successProvider () : array
2012-07-18 15:20:01 +00:00
{
return array (
array ( // minimal
array (
'name' => 'foo/bar' ,
),
),
array ( // complete
array (
'name' => 'foo/bar' ,
'description' => 'Foo bar' ,
'version' => '1.0.0' ,
'type' => 'library' ,
2015-06-02 13:04:58 +00:00
'keywords' => array ( 'a' , 'b_c' , 'D E' , 'éîüø' , '微信' ),
2012-07-18 15:20:01 +00:00
'homepage' => 'https://foo.com' ,
'time' => '2010-10-10T10:10:10+00:00' ,
'license' => 'MIT' ,
'authors' => array (
array (
'name' => 'Alice' ,
'email' => 'alice@example.org' ,
'role' => 'Lead' ,
'homepage' => 'http://example.org' ,
),
array (
'name' => 'Bob' ,
2012-11-05 14:39:43 +00:00
'homepage' => '' ,
2012-07-18 15:20:01 +00:00
),
),
'support' => array (
'email' => 'mail@example.org' ,
'issues' => 'http://example.org/' ,
'forum' => 'http://example.org/' ,
'wiki' => 'http://example.org/' ,
'source' => 'http://example.org/' ,
'irc' => 'irc://example.org/example' ,
2016-05-16 21:23:10 +00:00
'rss' => 'http://example.org/rss' ,
2018-10-14 11:15:25 +00:00
'chat' => 'http://example.org/chat' ,
2012-07-18 15:20:01 +00:00
),
2019-11-28 21:34:29 +00:00
'funding' => array (
array (
'type' => 'example' ,
2020-11-22 13:48:56 +00:00
'url' => 'https://example.org/fund' ,
2019-11-28 21:34:29 +00:00
),
array (
2020-11-22 13:48:56 +00:00
'url' => 'https://example.org/fund' ,
2019-11-28 21:34:29 +00:00
),
),
2012-07-18 15:20:01 +00:00
'require' => array (
'a/b' => '1.*' ,
2013-10-12 00:29:16 +00:00
'b/c' => '~2' ,
2021-11-25 11:33:59 +00:00
'example/pkg' => '>2.0-dev,<2.4-dev' ,
2020-04-28 14:04:00 +00:00
'composer-runtime-api' => '*' ,
2012-07-18 15:20:01 +00:00
),
'require-dev' => array (
'a/b' => '1.*' ,
2013-10-12 00:29:16 +00:00
'b/c' => '*' ,
2021-11-25 11:33:59 +00:00
'example/pkg' => '>2.0-dev,<2.4-dev' ,
2012-07-18 15:20:01 +00:00
),
'conflict' => array (
2021-11-25 11:33:59 +00:00
'a/bx' => '1.*' ,
'b/cx' => '>2.7' ,
'example/pkgx' => '>2.0-dev,<2.4-dev' ,
2012-07-18 15:20:01 +00:00
),
'replace' => array (
'a/b' => '1.*' ,
2021-11-25 11:33:59 +00:00
'example/pkg' => '>2.0-dev,<2.4-dev' ,
2012-07-18 15:20:01 +00:00
),
'provide' => array (
'a/b' => '1.*' ,
2021-11-25 11:33:59 +00:00
'example/pkg' => '>2.0-dev,<2.4-dev' ,
2012-07-18 15:20:01 +00:00
),
'suggest' => array (
'foo/bar' => 'Foo bar is very useful' ,
),
'autoload' => array (
'psr-0' => array (
'Foo\\Bar' => 'src/' ,
'' => 'fallback/libs/' ,
),
'classmap' => array (
'dir/' ,
'dir2/file.php' ,
),
'files' => array (
'functions.php' ,
),
),
'include-path' => array (
'lib/' ,
),
'target-dir' => 'Foo/Bar' ,
'minimum-stability' => 'dev' ,
'repositories' => array (
array (
'type' => 'composer' ,
2018-07-24 07:30:06 +00:00
'url' => 'https://repo.packagist.org/' ,
2015-09-28 09:51:14 +00:00
),
2012-07-18 15:20:01 +00:00
),
'config' => array (
'bin-dir' => 'bin' ,
'vendor-dir' => 'vendor' ,
'process-timeout' => 10000 ,
),
2013-02-07 14:45:58 +00:00
'archive' => array (
'exclude' => array ( '/foo/bar' , 'baz' , '!/foo/bar/baz' ),
),
2012-07-18 15:20:01 +00:00
'scripts' => array (
'post-update-cmd' => 'Foo\\Bar\\Baz::doSomething' ,
'post-install-cmd' => array (
'Foo\\Bar\\Baz::doSomething' ,
),
),
'extra' => array (
'random' => array ( 'stuff' => array ( 'deeply' => 'nested' )),
2012-11-05 13:14:55 +00:00
'branch-alias' => array (
'dev-master' => '2.0-dev' ,
'dev-old' => '1.0.x-dev' ,
2015-09-28 09:51:14 +00:00
'3.x-dev' => '3.1.x-dev' ,
2012-11-05 13:14:55 +00:00
),
2012-07-18 15:20:01 +00:00
),
'bin' => array (
'bin/foo' ,
'bin/bar' ,
),
2015-09-28 09:51:14 +00:00
'transport-options' => array ( 'ssl' => array ( 'local_cert' => '/opt/certs/test.pem' )),
2012-07-18 15:20:01 +00:00
),
),
2018-01-02 08:55:41 +00:00
array ( // test licenses as array
2012-07-18 15:20:01 +00:00
array (
'name' => 'foo/bar' ,
'license' => array ( 'MIT' , 'WTFPL' ),
),
),
2018-01-02 08:55:41 +00:00
array ( // test bin as string
array (
'name' => 'foo/bar' ,
'bin' => 'bin1' ,
),
),
2020-04-10 14:27:37 +00:00
array ( // package name with dashes
array (
'name' => 'foo/bar-baz' ,
),
),
array ( // package name with dashes
array (
'name' => 'foo/bar--baz' ,
),
),
array ( // package name with dashes
array (
'name' => 'foo/b-ar--ba-z' ,
),
),
array ( // package name with dashes
array (
'name' => 'npm-asset/angular--core' ,
),
),
2021-04-30 07:40:58 +00:00
array ( // refs as int or string
array (
'name' => 'foo/bar' ,
'source' => array ( 'url' => 'https://example.org' , 'reference' => 1234 , 'type' => 'baz' ),
'dist' => array ( 'url' => 'https://example.org' , 'reference' => 'foobar' , 'type' => 'baz' ),
),
),
2012-07-18 15:20:01 +00:00
);
}
/**
2012-11-05 11:08:02 +00:00
* @ dataProvider errorProvider
2021-11-01 20:44:12 +00:00
*
* @ param array < string , mixed > $config
* @ param string [] $expectedErrors
2012-07-18 15:20:01 +00:00
*/
2022-02-18 09:38:54 +00:00
public function testLoadFailureThrowsException ( $config , $expectedErrors ) : void
2012-07-18 15:20:01 +00:00
{
2018-04-12 08:24:56 +00:00
$internalLoader = $this -> getMockBuilder ( 'Composer\Package\Loader\LoaderInterface' ) -> getMock ();
2014-04-09 13:23:43 +00:00
$loader = new ValidatingArrayLoader ( $internalLoader , true , null , ValidatingArrayLoader :: CHECK_ALL );
2012-07-18 15:20:01 +00:00
try {
$loader -> load ( $config );
$this -> fail ( 'Expected exception to be thrown' );
2012-11-02 14:14:09 +00:00
} catch ( InvalidPackageException $e ) {
$errors = $e -> getErrors ();
2012-07-18 15:20:01 +00:00
sort ( $expectedErrors );
sort ( $errors );
$this -> assertEquals ( $expectedErrors , $errors );
}
}
/**
2012-11-05 11:08:02 +00:00
* @ dataProvider warningProvider
2021-11-01 20:44:12 +00:00
*
* @ param array < string , mixed > $config
* @ param string [] $expectedWarnings
2012-07-18 15:20:01 +00:00
*/
2022-02-18 09:38:54 +00:00
public function testLoadWarnings ( $config , $expectedWarnings ) : void
2012-11-05 11:08:02 +00:00
{
2018-04-12 08:24:56 +00:00
$internalLoader = $this -> getMockBuilder ( 'Composer\Package\Loader\LoaderInterface' ) -> getMock ();
2014-04-09 13:23:43 +00:00
$loader = new ValidatingArrayLoader ( $internalLoader , true , null , ValidatingArrayLoader :: CHECK_ALL );
2012-11-05 11:08:02 +00:00
$loader -> load ( $config );
$warnings = $loader -> getWarnings ();
sort ( $expectedWarnings );
sort ( $warnings );
$this -> assertEquals ( $expectedWarnings , $warnings );
}
/**
* @ dataProvider warningProvider
2021-11-01 20:44:12 +00:00
*
* @ param array < string , mixed > $config
* @ param string [] $expectedWarnings
* @ param bool $mustCheck
2012-11-05 11:08:02 +00:00
*/
2022-02-18 09:38:54 +00:00
public function testLoadSkipsWarningDataWhenIgnoringErrors ( $config , $expectedWarnings , $mustCheck = true ) : void
2012-07-18 15:20:01 +00:00
{
2014-04-09 13:23:43 +00:00
if ( ! $mustCheck ) {
$this -> assertTrue ( true );
2014-06-10 14:02:44 +00:00
2014-04-09 13:23:43 +00:00
return ;
}
2018-04-12 08:24:56 +00:00
$internalLoader = $this -> getMockBuilder ( 'Composer\Package\Loader\LoaderInterface' ) -> getMock ();
2012-07-18 15:20:01 +00:00
$internalLoader
-> expects ( $this -> once ())
-> method ( 'load' )
-> with ( array ( 'name' => 'a/b' ));
2014-04-09 13:23:43 +00:00
$loader = new ValidatingArrayLoader ( $internalLoader , true , null , ValidatingArrayLoader :: CHECK_ALL );
2012-07-18 15:20:01 +00:00
$config [ 'name' ] = 'a/b' ;
$loader -> load ( $config );
}
2022-02-21 12:42:28 +00:00
public function errorProvider () : array
2012-07-18 15:20:01 +00:00
{
2020-04-10 14:27:37 +00:00
$invalidNames = array (
'foo' ,
'foo/-bar-' ,
'foo/-bar' ,
);
$invalidNaming = array ();
2020-11-22 13:48:56 +00:00
foreach ( $invalidNames as $invalidName ) {
2020-04-10 14:27:37 +00:00
$invalidNaming [] = array (
2012-07-18 15:20:01 +00:00
array (
2020-04-10 14:27:37 +00:00
'name' => $invalidName ,
2012-07-18 15:20:01 +00:00
),
array (
2021-11-25 11:33:59 +00:00
" name : $invalidName is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match \" ^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|- { 0,2})[a-z0-9]+)* $\ " . " ,
),
);
}
$invalidNames = array (
'fo--oo/bar' ,
'fo-oo/bar__baz' ,
'fo-oo/bar_.baz' ,
'foo/bar---baz' ,
);
foreach ( $invalidNames as $invalidName ) {
$invalidNaming [] = array (
array (
'name' => $invalidName ,
),
array (
" name : $invalidName is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match \" ^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|- { 0,2})[a-z0-9]+)* $\ " . " ,
2015-09-28 09:51:14 +00:00
),
2021-11-25 11:33:59 +00:00
false ,
2020-04-10 14:27:37 +00:00
);
}
return array_merge ( $invalidNaming , array (
2012-07-18 15:20:01 +00:00
array (
array (
2012-11-05 11:08:02 +00:00
'name' => 'foo/bar' ,
'homepage' => 43 ,
),
array (
'homepage : should be a string, integer given' ,
2015-09-28 09:51:14 +00:00
),
2012-11-05 11:08:02 +00:00
),
array (
array (
'name' => 'foo/bar' ,
'support' => array (
'source' => array (),
),
),
array (
'support.source : invalid value, must be a string' ,
2015-09-28 09:51:14 +00:00
),
2012-11-05 11:08:02 +00:00
),
2021-11-25 11:33:59 +00:00
array (
array (
'name' => 'foo/bar.json' ,
),
array (
'name : foo/bar.json is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.' ,
),
),
array (
array (
'name' => 'com1/foo' ,
),
array (
'name : com1/foo is reserved, package and vendor names can not match any of: nul, con, prn, aux, com1, com2, com3, com4, com5, com6, com7, com8, com9, lpt1, lpt2, lpt3, lpt4, lpt5, lpt6, lpt7, lpt8, lpt9.' ,
),
),
array (
array (
'name' => 'Foo/Bar' ,
),
array (
'name : Foo/Bar is invalid, it should not contain uppercase characters. We suggest using foo/bar instead.' ,
),
),
array (
array (
'name' => 'foo/bar' ,
'require' => array (
'Foo/Baz' => '^1.0' ,
),
),
array (
'require.Foo/Baz is invalid, it should not contain uppercase characters. Please use foo/baz instead.' ,
),
false ,
),
2013-04-25 19:02:15 +00:00
array (
array (
'name' => 'foo/bar' ,
'autoload' => 'strings' ,
),
array (
2015-09-28 09:51:14 +00:00
'autoload : should be an array, string given' ,
),
2013-04-25 19:02:15 +00:00
),
array (
array (
'name' => 'foo/bar' ,
'autoload' => array (
'psr0' => array (
'foo' => 'src' ,
),
),
),
array (
2015-10-30 20:40:09 +00:00
'autoload : invalid value (psr0), must be one of psr-0, psr-4, classmap, files, exclude-from-classmap' ,
2015-09-28 09:51:14 +00:00
),
2013-04-25 19:02:15 +00:00
),
2013-08-19 07:40:08 +00:00
array (
array (
'name' => 'foo/bar' ,
2014-05-07 16:25:28 +00:00
'transport-options' => 'test' ,
2013-08-19 07:40:08 +00:00
),
array (
2015-09-28 09:51:14 +00:00
'transport-options : should be an array, string given' ,
),
2013-08-19 07:40:08 +00:00
),
2021-04-28 19:53:09 +00:00
array (
array (
'name' => 'foo/bar' ,
'source' => array ( 'url' => '--foo' , 'reference' => ' --bar' , 'type' => 'baz' ),
'dist' => array ( 'url' => ' --foox' , 'reference' => '--barx' , 'type' => 'baz' ),
),
array (
'dist.reference : must not start with a "-", "--barx" given' ,
'dist.url : must not start with a "-", " --foox" given' ,
'source.reference : must not start with a "-", " --bar" given' ,
'source.url : must not start with a "-", "--foo" given' ,
),
),
2021-11-10 10:07:44 +00:00
array (
array (
'name' => 'foo/bar' ,
'require' => array ( 'foo/Bar' => '1.*' ),
),
array (
'require.foo/Bar : a package cannot set a require on itself' ,
),
),
2020-04-10 14:27:37 +00:00
));
2012-11-05 11:08:02 +00:00
}
2022-02-21 12:42:28 +00:00
public function warningProvider () : array
2012-11-05 11:08:02 +00:00
{
2021-11-25 11:33:59 +00:00
return array (
2012-11-05 11:08:02 +00:00
array (
array (
2012-07-18 15:20:01 +00:00
'name' => 'foo/bar' ,
'homepage' => 'foo:bar' ,
),
array (
2015-09-28 09:51:14 +00:00
'homepage : invalid value (foo:bar), must be an http/https URL' ,
),
2012-07-18 15:20:01 +00:00
),
array (
array (
'name' => 'foo/bar' ,
'support' => array (
'source' => 'foo:bar' ,
'forum' => 'foo:bar' ,
'issues' => 'foo:bar' ,
'wiki' => 'foo:bar' ,
2018-10-14 11:15:25 +00:00
'chat' => 'foo:bar' ,
2012-07-18 15:20:01 +00:00
),
),
array (
2012-11-05 19:04:29 +00:00
'support.source : invalid value (foo:bar), must be an http/https URL' ,
'support.forum : invalid value (foo:bar), must be an http/https URL' ,
'support.issues : invalid value (foo:bar), must be an http/https URL' ,
'support.wiki : invalid value (foo:bar), must be an http/https URL' ,
2018-10-14 11:15:25 +00:00
'support.chat : invalid value (foo:bar), must be an http/https URL' ,
2015-09-28 09:51:14 +00:00
),
2012-07-18 15:20:01 +00:00
),
2013-10-12 00:29:16 +00:00
array (
array (
'name' => 'foo/bar' ,
'require' => array (
'foo/baz' => '*' ,
'bar/baz' => '>=1.0' ,
'bar/hacked' => '@stable' ,
2016-04-15 15:37:47 +00:00
'bar/woo' => '1.0.0' ,
2014-04-09 13:23:43 +00:00
),
2013-10-12 00:29:16 +00:00
),
array (
2014-04-09 13:23:43 +00:00
'require.foo/baz : unbound version constraints (*) should be avoided' ,
'require.bar/baz : unbound version constraints (>=1.0) should be avoided' ,
'require.bar/hacked : unbound version constraints (@stable) should be avoided' ,
2016-04-15 15:37:47 +00:00
'require.bar/woo : exact version constraints (1.0.0) should be avoided if the package follows semantic versioning' ,
2014-04-09 13:23:43 +00:00
),
2015-09-28 09:51:14 +00:00
false ,
2013-10-12 00:29:16 +00:00
),
2016-05-15 20:15:48 +00:00
array (
array (
'name' => 'foo/bar' ,
'require' => array (
'bar/unstable' => '0.3.0' ,
),
),
array (
// using an exact version constraint for an unstable version should not trigger a warning
),
false ,
),
2014-12-01 05:09:35 +00:00
array (
array (
'name' => 'foo/bar' ,
'extra' => array (
'branch-alias' => array (
2015-09-28 09:51:14 +00:00
'5.x-dev' => '3.1.x-dev' ,
2014-12-01 05:09:35 +00:00
),
2015-09-28 09:51:14 +00:00
),
2014-12-01 05:09:35 +00:00
),
array (
2015-09-28 09:51:14 +00:00
'extra.branch-alias.5.x-dev : the target branch (3.1.x-dev) is not a valid numeric alias for this version' ,
2014-12-01 05:09:35 +00:00
),
2015-09-28 09:51:14 +00:00
false ,
2014-12-01 05:09:35 +00:00
),
2015-01-20 10:26:10 +00:00
array (
array (
'name' => 'foo/bar' ,
'extra' => array (
'branch-alias' => array (
2015-09-28 09:51:14 +00:00
'5.x-dev' => '3.1-dev' ,
2015-01-20 10:26:10 +00:00
),
2015-09-28 09:51:14 +00:00
),
2015-01-20 10:26:10 +00:00
),
array (
2015-09-28 09:51:14 +00:00
'extra.branch-alias.5.x-dev : the target branch (3.1-dev) is not a valid numeric alias for this version' ,
2015-01-20 10:26:10 +00:00
),
2015-09-28 09:51:14 +00:00
false ,
2015-01-20 10:26:10 +00:00
),
2021-11-25 11:33:59 +00:00
);
2012-07-18 15:20:01 +00:00
}
}