1
0
Fork 0

Merge pull request #684 from Seldaek/functional

Add functional tests for the installer, fixes #580
pull/682/merge
Nils Adermann 2012-05-13 13:07:01 -07:00
commit 83e8dba23c
9 changed files with 327 additions and 11 deletions

View File

@ -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)>

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
} }

View File

@ -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)
{
}
}

View File

@ -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()

View File

@ -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()
{
}
}

View File

@ -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());