Add functional tests for the installer, fixes #580
parent
0a0a6b1813
commit
4505df29df
|
@ -0,0 +1,14 @@
|
||||||
|
--TEST--
|
||||||
|
<test description>
|
||||||
|
--CONDITION--
|
||||||
|
<php code that checks if test can run, must return a Boolean>
|
||||||
|
--COMPOSER--
|
||||||
|
<composer.json file definition>
|
||||||
|
--LOCK--
|
||||||
|
<composer.lock file definition>
|
||||||
|
--INSTALLED--
|
||||||
|
<installed.json file definition>
|
||||||
|
--INSTALLED:DEV--
|
||||||
|
<installed_dev.json file definition>
|
||||||
|
--EXPECT-- or --EXPECT:UPDATE-- or --EXPECT:DEV-- or --EXPECT:UPDATE:DEV--
|
||||||
|
<output (stringified operations)>
|
|
@ -0,0 +1,23 @@
|
||||||
|
--TEST--
|
||||||
|
Installs a package in dev env
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{ "name": "a/a", "version": "1.0.0" },
|
||||||
|
{ "name": "a/b", "version": "1.0.0" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"a/a": "1.0.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"a/b": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--EXPECT:DEV--
|
||||||
|
Installing a/a (1.0.0)
|
||||||
|
Installing a/b (1.0.0)
|
|
@ -0,0 +1,18 @@
|
||||||
|
--TEST--
|
||||||
|
Installs a simple package with exact match requirement
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{ "name": "a/a", "version": "1.0.0" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"a/a": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--EXPECT--
|
||||||
|
Installing a/a (1.0.0)
|
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
Updates updateable packages
|
||||||
|
--COMPOSER--
|
||||||
|
{
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "package",
|
||||||
|
"package": [
|
||||||
|
{ "name": "a/a", "version": "1.0.0" },
|
||||||
|
{ "name": "a/a", "version": "1.0.1" },
|
||||||
|
{ "name": "a/a", "version": "1.1.0" },
|
||||||
|
|
||||||
|
{ "name": "a/b", "version": "1.0.0" },
|
||||||
|
{ "name": "a/b", "version": "1.0.1" },
|
||||||
|
{ "name": "a/b", "version": "2.0.0" },
|
||||||
|
|
||||||
|
{ "name": "a/c", "version": "1.0.0" },
|
||||||
|
{ "name": "a/c", "version": "2.0.0" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"a/a": "1.0.*",
|
||||||
|
"a/c": "1.*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"a/b": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--INSTALLED--
|
||||||
|
[
|
||||||
|
{ "name": "a/a", "version": "1.0.0" },
|
||||||
|
{ "name": "a/c", "version": "1.0.0" }
|
||||||
|
]
|
||||||
|
--INSTALLED:DEV--
|
||||||
|
[
|
||||||
|
{ "name": "a/b", "version": "1.0.0" }
|
||||||
|
]
|
||||||
|
--EXPECT:UPDATE:DEV--
|
||||||
|
Updating a/a (1.0.0) to a/a (1.0.1)
|
||||||
|
Updating a/b (1.0.0) to a/b (2.0.0)
|
|
@ -12,13 +12,18 @@
|
||||||
namespace Composer\Test;
|
namespace Composer\Test;
|
||||||
|
|
||||||
use Composer\Installer;
|
use Composer\Installer;
|
||||||
|
use Composer\Config;
|
||||||
|
use Composer\Json\JsonFile;
|
||||||
use Composer\Repository\ArrayRepository;
|
use Composer\Repository\ArrayRepository;
|
||||||
use Composer\Repository\RepositoryManager;
|
use Composer\Repository\RepositoryManager;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Package\Link;
|
use Composer\Package\Link;
|
||||||
use Composer\Test\Mock\WritableRepositoryMock;
|
use Composer\Package\Locker;
|
||||||
|
use Composer\Test\Mock\FactoryMock;
|
||||||
|
use Composer\Test\Mock\InstalledFilesystemRepositoryMock;
|
||||||
use Composer\Test\Mock\InstallationManagerMock;
|
use Composer\Test\Mock\InstallationManagerMock;
|
||||||
|
use Composer\Test\Mock\WritableRepositoryMock;
|
||||||
|
|
||||||
class InstallerTest extends TestCase
|
class InstallerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
@ -112,4 +117,126 @@ class InstallerTest extends TestCase
|
||||||
|
|
||||||
return $cases;
|
return $cases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getIntegrationTests
|
||||||
|
*/
|
||||||
|
public function testIntegration($file, $message, $condition, $composer, $lock, $installed, $installedDev, $update, $dev, $expect)
|
||||||
|
{
|
||||||
|
if ($condition) {
|
||||||
|
eval('$res = '.$condition.';');
|
||||||
|
if (!$res) {
|
||||||
|
$this->markTestSkipped($condition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$io = $this->getMock('Composer\IO\IOInterface');
|
||||||
|
|
||||||
|
$composer = FactoryMock::create($io, $composer);
|
||||||
|
|
||||||
|
$jsonMock = $this->getMockBuilder('Composer\Json\JsonFile')->disableOriginalConstructor()->getMock();
|
||||||
|
$jsonMock->expects($this->any())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue($installed));
|
||||||
|
$jsonMock->expects($this->any())
|
||||||
|
->method('exists')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
|
||||||
|
$devJsonMock = $this->getMockBuilder('Composer\Json\JsonFile')->disableOriginalConstructor()->getMock();
|
||||||
|
$devJsonMock->expects($this->any())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue($installedDev));
|
||||||
|
$devJsonMock->expects($this->any())
|
||||||
|
->method('exists')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
|
||||||
|
$repositoryManager = $composer->getRepositoryManager();
|
||||||
|
$repositoryManager->setLocalRepository(new InstalledFilesystemRepositoryMock($jsonMock));
|
||||||
|
$repositoryManager->setLocalDevRepository(new InstalledFilesystemRepositoryMock($devJsonMock));
|
||||||
|
|
||||||
|
$lockJsonMock = $this->getMockBuilder('Composer\Json\JsonFile')->disableOriginalConstructor()->getMock();
|
||||||
|
$lockJsonMock->expects($this->any())
|
||||||
|
->method('read')
|
||||||
|
->will($this->returnValue($lock));
|
||||||
|
|
||||||
|
$locker = new Locker($lockJsonMock, $repositoryManager, isset($lock['hash']) ? $lock['hash'] : '');
|
||||||
|
$composer->setLocker($locker);
|
||||||
|
|
||||||
|
$autoloadGenerator = $this->getMock('Composer\Autoload\AutoloadGenerator');
|
||||||
|
|
||||||
|
$installer = Installer::create(
|
||||||
|
$io,
|
||||||
|
$composer,
|
||||||
|
null,
|
||||||
|
$autoloadGenerator
|
||||||
|
);
|
||||||
|
|
||||||
|
$installer->setDevMode($dev)->setUpdate($update);
|
||||||
|
|
||||||
|
$result = $installer->run();
|
||||||
|
$this->assertTrue($result);
|
||||||
|
|
||||||
|
$expectedInstalled = isset($options['install']) ? $options['install'] : array();
|
||||||
|
$expectedUpdated = isset($options['update']) ? $options['update'] : array();
|
||||||
|
$expectedUninstalled = isset($options['uninstall']) ? $options['uninstall'] : array();
|
||||||
|
|
||||||
|
$installationManager = $composer->getInstallationManager();
|
||||||
|
$this->assertSame($expect, implode("\n", $installationManager->getTrace()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIntegrationTests()
|
||||||
|
{
|
||||||
|
$fixturesDir = realpath(__DIR__.'/Fixtures/installer/');
|
||||||
|
$tests = array();
|
||||||
|
|
||||||
|
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
||||||
|
if (!preg_match('/\.test$/', $file)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = file_get_contents($file->getRealpath());
|
||||||
|
|
||||||
|
$pattern = '{^
|
||||||
|
--TEST--\s*(?P<test>.*?)\s*
|
||||||
|
(?:--CONDITION--\s*(?P<condition>.*?))?\s*
|
||||||
|
--COMPOSER--\s*(?P<composer>.*?)\s*
|
||||||
|
(?:--LOCK--\s*(?P<lock>.*?))?\s*
|
||||||
|
(?:--INSTALLED--\s*(?P<installed>.*?))?\s*
|
||||||
|
(?:--INSTALLED:DEV--\s*(?P<installedDev>.*?))?\s*
|
||||||
|
--EXPECT(?P<update>:UPDATE)?(?P<dev>:DEV)?--\s*(?P<expect>.*?)\s*
|
||||||
|
$}xs';
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
$installedDev = array();
|
||||||
|
$lock = array();
|
||||||
|
|
||||||
|
if (preg_match($pattern, $test, $match)) {
|
||||||
|
try {
|
||||||
|
$message = $match['test'];
|
||||||
|
$condition = !empty($match['condition']) ? $match['condition'] : null;
|
||||||
|
$composer = JsonFile::parseJson($match['composer']);
|
||||||
|
if (!empty($match['lock'])) {
|
||||||
|
$lock = JsonFile::parseJson($match['lock']);
|
||||||
|
}
|
||||||
|
if (!empty($match['installed'])) {
|
||||||
|
$installed = JsonFile::parseJson($match['installed']);
|
||||||
|
}
|
||||||
|
if (!empty($match['installedDev'])) {
|
||||||
|
$installedDev = JsonFile::parseJson($match['installedDev']);
|
||||||
|
}
|
||||||
|
$update = !empty($match['update']);
|
||||||
|
$dev = !empty($match['dev']);
|
||||||
|
$expect = $match['expect'];
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
die(sprintf('Test "%s" is not valid: '.$e->getMessage(), str_replace($fixturesDir.'/', '', $file)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die(sprintf('Test "%s" is not valid, did not match the expected format.', str_replace($fixturesDir.'/', '', $file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $composer, $lock, $installed, $installedDev, $update, $dev, $expect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tests;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?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\Mock;
|
||||||
|
|
||||||
|
use Composer\Config;
|
||||||
|
use Composer\Factory;
|
||||||
|
use Composer\Repository;
|
||||||
|
use Composer\Repository\RepositoryManager;
|
||||||
|
use Composer\Installer;
|
||||||
|
use Composer\Downloader;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
|
class FactoryMock extends Factory
|
||||||
|
{
|
||||||
|
public static function createConfig()
|
||||||
|
{
|
||||||
|
$config = new Config();
|
||||||
|
|
||||||
|
$config->merge(array('config' => array('home' => sys_get_temp_dir().'/composer-test')));
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addLocalRepository(RepositoryManager $rm, $vendorDir)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addPackagistRepository(array $localConfig)
|
||||||
|
{
|
||||||
|
return $localConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm, $vendorDir, $binDir, IOInterface $io)
|
||||||
|
{
|
||||||
|
return new InstallationManagerMock;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function purgePackages(Repository\RepositoryManager $rm, Installer\InstallationManager $im)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,20 +23,33 @@ class InstallationManagerMock extends InstallationManager
|
||||||
private $installed = array();
|
private $installed = array();
|
||||||
private $updated = array();
|
private $updated = array();
|
||||||
private $uninstalled = array();
|
private $uninstalled = array();
|
||||||
|
private $trace = array();
|
||||||
|
|
||||||
public function install(RepositoryInterface $repo, InstallOperation $operation)
|
public function install(RepositoryInterface $repo, InstallOperation $operation)
|
||||||
{
|
{
|
||||||
$this->installed[] = $operation->getPackage();
|
$this->installed[] = $operation->getPackage();
|
||||||
|
$this->trace[] = (string) $operation;
|
||||||
|
$repo->addPackage(clone $operation->getPackage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(RepositoryInterface $repo, UpdateOperation $operation)
|
public function update(RepositoryInterface $repo, UpdateOperation $operation)
|
||||||
{
|
{
|
||||||
$this->updated[] = array($operation->getInitialPackage(), $operation->getTargetPackage());
|
$this->updated[] = array($operation->getInitialPackage(), $operation->getTargetPackage());
|
||||||
|
$this->trace[] = (string) $operation;
|
||||||
|
$repo->removePackage($operation->getInitialPackage());
|
||||||
|
$repo->addPackage(clone $operation->getTargetPackage());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
|
public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
|
||||||
{
|
{
|
||||||
$this->uninstalled[] = $operation->getPackage();
|
$this->uninstalled[] = $operation->getPackage();
|
||||||
|
$this->trace[] = (string) $operation;
|
||||||
|
$repo->removePackage($operation->getPackage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTrace()
|
||||||
|
{
|
||||||
|
return $this->trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInstalledPackages()
|
public function getInstalledPackages()
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?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\Mock;
|
||||||
|
|
||||||
|
use Composer\Repository\InstalledFilesystemRepository;
|
||||||
|
|
||||||
|
class InstalledFilesystemRepositoryMock extends InstalledFilesystemRepository
|
||||||
|
{
|
||||||
|
public function reload()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,18 @@ use Composer\Config;
|
||||||
|
|
||||||
class GitHubDriverTest extends \PHPUnit_Framework_TestCase
|
class GitHubDriverTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->config = new Config();
|
||||||
|
$this->config->merge(array(
|
||||||
|
'config' => array(
|
||||||
|
'home' => sys_get_temp_dir() . '/composer-test',
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
public function testPrivateRepository()
|
public function testPrivateRepository()
|
||||||
{
|
{
|
||||||
$scheme = extension_loaded('openssl') ? 'https' : 'http';
|
$scheme = extension_loaded('openssl') ? 'https' : 'http';
|
||||||
|
@ -62,7 +74,7 @@ class GitHubDriverTest extends \PHPUnit_Framework_TestCase
|
||||||
->with($this->equalTo('github.com'), $this->equalTo($repoApiUrl), $this->equalTo(false))
|
->with($this->equalTo('github.com'), $this->equalTo($repoApiUrl), $this->equalTo(false))
|
||||||
->will($this->returnValue('{"master_branch": "test_master"}'));
|
->will($this->returnValue('{"master_branch": "test_master"}'));
|
||||||
|
|
||||||
$gitHubDriver = new GitHubDriver($repoUrl, $io, new Config(), null, $remoteFilesystem);
|
$gitHubDriver = new GitHubDriver($repoUrl, $io, $this->config, null, $remoteFilesystem);
|
||||||
$gitHubDriver->initialize();
|
$gitHubDriver->initialize();
|
||||||
$this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha));
|
$this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha));
|
||||||
|
|
||||||
|
@ -112,7 +124,7 @@ class GitHubDriverTest extends \PHPUnit_Framework_TestCase
|
||||||
->with($this->equalTo('github.com'), $this->equalTo($repoApiUrl), $this->equalTo(false))
|
->with($this->equalTo('github.com'), $this->equalTo($repoApiUrl), $this->equalTo(false))
|
||||||
->will($this->returnValue('{"master_branch": "test_master"}'));
|
->will($this->returnValue('{"master_branch": "test_master"}'));
|
||||||
|
|
||||||
$gitHubDriver = new GitHubDriver($repoUrl, $io, new Config(), null, $remoteFilesystem);
|
$gitHubDriver = new GitHubDriver($repoUrl, $io, $this->config, null, $remoteFilesystem);
|
||||||
$gitHubDriver->initialize();
|
$gitHubDriver->initialize();
|
||||||
$this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha));
|
$this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha));
|
||||||
|
|
||||||
|
@ -171,13 +183,6 @@ class GitHubDriverTest extends \PHPUnit_Framework_TestCase
|
||||||
$fs = new Filesystem();
|
$fs = new Filesystem();
|
||||||
$fs->removeDirectory(sys_get_temp_dir() . '/composer-test');
|
$fs->removeDirectory(sys_get_temp_dir() . '/composer-test');
|
||||||
|
|
||||||
$config = new Config();
|
|
||||||
$config->merge(array(
|
|
||||||
'config' => array(
|
|
||||||
'home' => sys_get_temp_dir() . '/composer-test',
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
$process->expects($this->at(0))
|
$process->expects($this->at(0))
|
||||||
->method('execute')
|
->method('execute')
|
||||||
->with($this->stringContains($repoSshUrl))
|
->with($this->stringContains($repoSshUrl))
|
||||||
|
@ -207,7 +212,7 @@ class GitHubDriverTest extends \PHPUnit_Framework_TestCase
|
||||||
->method('splitLines')
|
->method('splitLines')
|
||||||
->will($this->returnValue(array('* test_master')));
|
->will($this->returnValue(array('* test_master')));
|
||||||
|
|
||||||
$gitHubDriver = new GitHubDriver($repoUrl, $io, $config, $process, $remoteFilesystem);
|
$gitHubDriver = new GitHubDriver($repoUrl, $io, $this->config, $process, $remoteFilesystem);
|
||||||
$gitHubDriver->initialize();
|
$gitHubDriver->initialize();
|
||||||
|
|
||||||
$this->assertEquals('test_master', $gitHubDriver->getRootIdentifier());
|
$this->assertEquals('test_master', $gitHubDriver->getRootIdentifier());
|
||||||
|
|
Loading…
Reference in New Issue