diff --git a/src/Composer/Json/JsonValidationException.php b/src/Composer/Json/JsonValidationException.php index 2fa5eb489..2d113a802 100644 --- a/src/Composer/Json/JsonValidationException.php +++ b/src/Composer/Json/JsonValidationException.php @@ -24,7 +24,7 @@ class JsonValidationException extends Exception public function __construct($message, $errors = array(), Exception $previous = null) { $this->errors = $errors; - parent::__construct($message, 0, $previous); + parent::__construct((string) $message, 0, $previous); } public function getErrors() diff --git a/src/Composer/Util/Bitbucket.php b/src/Composer/Util/Bitbucket.php index 5970aa631..445dbed7e 100644 --- a/src/Composer/Util/Bitbucket.php +++ b/src/Composer/Util/Bitbucket.php @@ -151,7 +151,7 @@ class Bitbucket $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName())); $this->io->writeError('Ensure you enter a "Callback URL" (http://example.com is fine) or it will not be possible to create an Access Token (this callback url will not be used by composer)'); - $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): ')); + $consumerKey = trim((string) $this->io->askAndHideAnswer('Consumer Key (hidden): ')); if (!$consumerKey) { $this->io->writeError('No consumer key given, aborting.'); @@ -160,7 +160,7 @@ class Bitbucket return false; } - $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): ')); + $consumerSecret = trim((string) $this->io->askAndHideAnswer('Consumer Secret (hidden): ')); if (!$consumerSecret) { $this->io->writeError('No consumer secret given, aborting.'); diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index 0bde7fb3e..ea2b1152c 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -160,7 +160,7 @@ class Perforce public function isStream() { - return (strcmp($this->p4DepotType, 'stream') === 0); + return is_string($this->p4DepotType) && (strcmp($this->p4DepotType, 'stream') === 0); } public function getStream() @@ -204,11 +204,11 @@ class Perforce public function queryP4User() { $this->getUser(); - if (strlen($this->p4User) > 0) { + if (strlen((string) $this->p4User) > 0) { return; } $this->p4User = $this->getP4variable('P4USER'); - if (strlen($this->p4User) > 0) { + if (strlen((string) $this->p4User) > 0) { return; } $this->p4User = $this->io->ask('Enter P4 User:'); @@ -262,7 +262,7 @@ class Perforce return $this->p4Password; } $password = $this->getP4variable('P4PASSWD'); - if (strlen($password) <= 0) { + if (strlen((string) $password) <= 0) { $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': '); } $this->p4Password = $password; diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index 6b6e84bee..c00e8fd20 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -356,9 +356,9 @@ class ProcessExecutor */ public function splitLines($output) { - $output = trim($output); + $output = trim((string) $output); - return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output); + return $output === '' ? array() : preg_split('{\r?\n}', $output); } /** diff --git a/tests/Composer/Test/Downloader/FileDownloaderTest.php b/tests/Composer/Test/Downloader/FileDownloaderTest.php index ead8bc1c1..036410407 100644 --- a/tests/Composer/Test/Downloader/FileDownloaderTest.php +++ b/tests/Composer/Test/Downloader/FileDownloaderTest.php @@ -18,6 +18,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Plugin\PluginEvents; use Composer\Plugin\PreFileDownloadEvent; use Composer\Test\TestCase; +use Composer\Test\Mock\ProcessExecutorMock; use Composer\Util\Filesystem; use Composer\Util\Http\Response; use Composer\Util\Loop; @@ -194,7 +195,7 @@ class FileDownloaderTest extends TestCase $dispatcher = new EventDispatcher( $composerMock, $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), - $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock() + new ProcessExecutorMock ); $dispatcher->addListener(PluginEvents::PRE_FILE_DOWNLOAD, function (PreFileDownloadEvent $event) use ($expectedUrl) { $event->setProcessedUrl($expectedUrl); @@ -288,7 +289,7 @@ class FileDownloaderTest extends TestCase $dispatcher = new EventDispatcher( $composerMock, $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), - $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock() + new ProcessExecutorMock ); $dispatcher->addListener(PluginEvents::PRE_FILE_DOWNLOAD, function (PreFileDownloadEvent $event) use ($customCacheKey) { $event->setCustomCacheKey($customCacheKey); diff --git a/tests/Composer/Test/Downloader/FossilDownloaderTest.php b/tests/Composer/Test/Downloader/FossilDownloaderTest.php index 33920da27..69a810977 100644 --- a/tests/Composer/Test/Downloader/FossilDownloaderTest.php +++ b/tests/Composer/Test/Downloader/FossilDownloaderTest.php @@ -16,6 +16,7 @@ use Composer\Downloader\FossilDownloader; use Composer\Test\TestCase; use Composer\Util\Filesystem; use Composer\Util\Platform; +use Composer\Test\Mock\ProcessExecutorMock; class FossilDownloaderTest extends TestCase { @@ -39,7 +40,7 @@ class FossilDownloaderTest extends TestCase { $io = $io ?: $this->getMockBuilder('Composer\IO\IOInterface')->getMock(); $config = $config ?: $this->getMockBuilder('Composer\Config')->getMock(); - $executor = $executor ?: $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $executor = $executor ?: new ProcessExecutorMock; $filesystem = $filesystem ?: $this->getMockBuilder('Composer\Util\Filesystem')->getMock(); return new FossilDownloader($io, $config, $executor, $filesystem); @@ -67,28 +68,18 @@ class FossilDownloaderTest extends TestCase $packageMock->expects($this->once()) ->method('getSourceUrls') ->will($this->returnValue(array('http://fossil.kd2.org/kd2fw/'))); - $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $expectedFossilCommand = $this->getCmd('fossil clone -- \'http://fossil.kd2.org/kd2fw/\' \'repo.fossil\''); - $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedFossilCommand)) - ->will($this->returnValue(0)); + $process = new ProcessExecutorMock; + $process->expects(array( + $this->getCmd('fossil clone -- \'http://fossil.kd2.org/kd2fw/\' \'repo.fossil\''), + $this->getCmd('fossil open --nested -- \'repo.fossil\''), + $this->getCmd('fossil update -- \'trunk\''), + ), true); - $expectedFossilCommand = $this->getCmd('fossil open --nested -- \'repo.fossil\''); - $processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedFossilCommand)) - ->will($this->returnValue(0)); - - $expectedFossilCommand = $this->getCmd('fossil update -- \'trunk\''); - $processExecutor->expects($this->at(2)) - ->method('execute') - ->with($this->equalTo($expectedFossilCommand)) - ->will($this->returnValue(0)); - - $downloader = $this->getDownloaderMock(null, null, $processExecutor); + $downloader = $this->getDownloaderMock(null, null, $process); $downloader->install($packageMock, 'repo'); + + $process->assertComplete($this); } public function testUpdateforPackageWithoutSourceReference() @@ -126,46 +117,46 @@ class FossilDownloaderTest extends TestCase $packageMock->expects($this->any()) ->method('getVersion') ->will($this->returnValue('1.0.0.0')); - $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $expectedFossilCommand = $this->getCmd("fossil changes"); - $processExecutor->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo($expectedFossilCommand)) - ->will($this->returnCallback(function ($cmd, &$output, $path) { - $output = ''; + $process = new ProcessExecutorMock; + $process->expects(array( + $this->getCmd("fossil changes"), + $this->getCmd("fossil pull && fossil up 'trunk'"), + ), true); - return 0; - })); - $expectedFossilCommand = $this->getCmd("fossil pull && fossil up 'trunk'"); - $processExecutor->expects($this->at(1)) - ->method('execute') - ->with($this->equalTo($expectedFossilCommand)) - ->will($this->returnValue(0)); - - $downloader = $this->getDownloaderMock(null, null, $processExecutor); + $downloader = $this->getDownloaderMock(null, null, $process); $downloader->prepare('update', $packageMock, $this->workingDir, $packageMock); $downloader->update($packageMock, $packageMock, $this->workingDir); $downloader->cleanup('update', $packageMock, $this->workingDir, $packageMock); + + $process->assertComplete($this); } public function testRemove() { - $expectedResetCommand = $this->getCmd('cd \'composerPath\' && fossil status'); + // Ensure file exists + $file = $this->workingDir . '/.fslckout'; + touch($file); $packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock(); - $processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $processExecutor->expects($this->any()) - ->method('execute') - ->with($this->equalTo($expectedResetCommand)); + + $process = new ProcessExecutorMock; + $process->expects(array( + $this->getCmd('fossil changes'), + ), true); + $filesystem = $this->getMockBuilder('Composer\Util\Filesystem')->getMock(); $filesystem->expects($this->once()) ->method('removeDirectoryAsync') - ->with($this->equalTo('composerPath')) + ->with($this->equalTo($this->workingDir)) ->will($this->returnValue(\React\Promise\resolve(true))); - $downloader = $this->getDownloaderMock(null, null, $processExecutor, $filesystem); - $downloader->remove($packageMock, 'composerPath'); + $downloader = $this->getDownloaderMock(null, null, $process, $filesystem); + $downloader->prepare('uninstall', $packageMock, $this->workingDir); + $downloader->remove($packageMock, $this->workingDir); + $downloader->cleanup('uninstall', $packageMock, $this->workingDir); + + $process->assertComplete($this); } public function testGetInstallationSource() diff --git a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php index 370fc9d31..cd47d8ecf 100644 --- a/tests/Composer/Test/Downloader/PerforceDownloaderTest.php +++ b/tests/Composer/Test/Downloader/PerforceDownloaderTest.php @@ -19,6 +19,7 @@ use Composer\IO\IOInterface; use Composer\Test\TestCase; use Composer\Factory; use Composer\Util\Filesystem; +use Composer\Test\Mock\ProcessExecutorMock; /** * @author Matt Whittom @@ -41,7 +42,7 @@ class PerforceDownloaderTest extends TestCase $this->repoConfig = $this->getRepoConfig(); $this->config = $this->getConfig(); $this->io = $this->getMockIoInterface(); - $this->processExecutor = $this->getMockProcessExecutor(); + $this->processExecutor = new ProcessExecutorMock; $this->repository = $this->getMockRepository($this->repoConfig, $this->io, $this->config); $this->package = $this->getMockPackageInterface($this->repository); $this->downloader = new PerforceDownloader($this->io, $this->config, $this->processExecutor); @@ -61,11 +62,6 @@ class PerforceDownloaderTest extends TestCase } } - protected function getMockProcessExecutor() - { - return $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - } - protected function getConfig() { $config = new Config(); diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index bbf3e6b98..400f4dec9 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -22,6 +22,7 @@ use Composer\IO\BufferIO; use Composer\Script\ScriptEvents; use Composer\Script\Event as ScriptEvent; use Composer\Util\ProcessExecutor; +use Composer\Test\Mock\ProcessExecutorMock; use Symfony\Component\Console\Output\OutputInterface; class EventDispatcherTest extends TestCase @@ -56,7 +57,11 @@ class EventDispatcherTest extends TestCase */ public function testDispatcherCanExecuteSingleCommandLineScript($command) { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $process = new ProcessExecutorMock; + $process->expects(array( + $command, + ), true); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->createComposerInstance(), @@ -71,12 +76,9 @@ class EventDispatcherTest extends TestCase ->method('getListeners') ->will($this->returnValue($listener)); - $process->expects($this->once()) - ->method('execute') - ->with($command) - ->will($this->returnValue(0)); - $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); + + $process->assertComplete($this); } /** @@ -104,7 +106,7 @@ class EventDispatcherTest extends TestCase $dispatcher = new EventDispatcher( $composer, $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), - $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock() + new ProcessExecutorMock ); $event = $this->getMockBuilder('Composer\Script\Event') @@ -179,7 +181,7 @@ class EventDispatcherTest extends TestCase $dispatcher = new EventDispatcher( $composer, $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE), - $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock() + new ProcessExecutorMock ); $listener = array($this, 'someMethod'); @@ -214,7 +216,12 @@ class EventDispatcherTest extends TestCase public function testDispatcherCanExecuteCliAndPhpInSameEventScriptStack() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $process = new ProcessExecutorMock; + $process->expects(array( + 'echo -n foo', + 'echo -n bar', + ), true); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->createComposerInstance(), @@ -226,10 +233,6 @@ class EventDispatcherTest extends TestCase )) ->getMock(); - $process->expects($this->exactly(2)) - ->method('execute') - ->will($this->returnValue(0)); - $listeners = array( 'echo -n foo', 'Composer\\Test\\EventDispatcher\\EventDispatcherTest::someMethod', @@ -246,16 +249,17 @@ class EventDispatcherTest extends TestCase '> post-install-cmd: Composer\Test\EventDispatcher\EventDispatcherTest::someMethod'.PHP_EOL. '> post-install-cmd: echo -n bar'.PHP_EOL; $this->assertEquals($expected, $io->getOutput()); + + $process->assertComplete($this); } public function testDispatcherCanPutEnv() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->createComposerInstance(), $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE), - $process, + new ProcessExecutorMock, )) ->setMethods(array( 'getListeners', @@ -285,11 +289,10 @@ class EventDispatcherTest extends TestCase chdir(__DIR__); putenv('COMPOSER_BIN_DIR=' . __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->setConstructorArgs(array( $this->createComposerInstance(), $io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE), - $process, + new ProcessExecutorMock, ))->setMethods(array( 'getListeners', ))->getMock(); @@ -342,7 +345,13 @@ class EventDispatcherTest extends TestCase public function testDispatcherCanExecuteComposerScriptGroups() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $process = new ProcessExecutorMock; + $process->expects(array( + 'echo -n foo', + 'echo -n baz', + 'echo -n bar', + ), true); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $composer = $this->createComposerInstance(), @@ -354,10 +363,6 @@ class EventDispatcherTest extends TestCase )) ->getMock(); - $process->expects($this->exactly(3)) - ->method('execute') - ->will($this->returnValue(0)); - $dispatcher->expects($this->atLeastOnce()) ->method('getListeners') ->will($this->returnCallback(function (Event $event) { @@ -383,11 +388,17 @@ class EventDispatcherTest extends TestCase '> subgroup: echo -n baz'.PHP_EOL. '> group: echo -n bar'.PHP_EOL; $this->assertEquals($expected, $io->getOutput()); + + $process->assertComplete($this); } public function testRecursionInScriptsNames() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $process = new ProcessExecutorMock; + $process->expects(array( + 'echo Hello '.ProcessExecutor::escape('World'), + ), true); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $composer = $this->createComposerInstance(), @@ -399,10 +410,6 @@ class EventDispatcherTest extends TestCase )) ->getMock(); - $process->expects($this->exactly(1)) - ->method('execute') - ->will($this->returnValue(0)); - $dispatcher->expects($this->atLeastOnce()) ->method('getListeners') ->will($this->returnCallback(function (Event $event) { @@ -422,18 +429,19 @@ class EventDispatcherTest extends TestCase "> hello: echo Hello " .escapeshellarg('World').PHP_EOL; $this->assertEquals($expected, $io->getOutput()); + + $process->assertComplete($this); } public function testDispatcherDetectInfiniteRecursion() { $this->setExpectedException('RuntimeException'); - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $composer = $this->createComposerInstance(), $io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), - $process, + new ProcessExecutorMock, )) ->setMethods(array( 'getListeners', @@ -549,12 +557,11 @@ class EventDispatcherTest extends TestCase public function testDispatcherInstallerEvents() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') ->setConstructorArgs(array( $this->createComposerInstance(), $this->getMockBuilder('Composer\IO\IOInterface')->getMock(), - $process, + new ProcessExecutorMock, )) ->setMethods(array('getListeners')) ->getMock(); diff --git a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php index 880b6f766..d83208632 100644 --- a/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php +++ b/tests/Composer/Test/Package/Loader/RootPackageLoaderTest.php @@ -19,13 +19,14 @@ use Composer\Package\RootPackage; use Composer\Package\Version\VersionGuesser; use Composer\Semver\VersionParser; use Composer\Test\TestCase; +use Composer\Test\Mock\ProcessExecutorMock; use Prophecy\Argument; class RootPackageLoaderTest extends TestCase { protected function loadPackage($data) { - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + $manager = $this->getMockBuilder('Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() ->getMock(); @@ -67,38 +68,28 @@ class RootPackageLoaderTest extends TestCase public function testNoVersionIsVisibleInPrettyVersion() { - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + $manager = $this->getMockBuilder('Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() ->getMock() ; - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $executor - ->expects($this->any()) - ->method('execute') - ->willReturn(null) - ; - $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser())); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $process = new ProcessExecutorMock, new VersionParser())); + $process->expects(array(), false, array('return' => 1)); + $package = $loader->load(array()); $this->assertEquals("1.0.0.0", $package->getVersion()); $this->assertEquals(RootPackage::DEFAULT_PRETTY_VERSION, $package->getPrettyVersion()); + } public function testPrettyVersionForRootPackageInVersionBranch() { // see #6845 - $manager = $this->prophesize('\\Composer\\Repository\\RepositoryManager'); - $versionGuesser = $this->prophesize('\\Composer\\Package\\Version\\VersionGuesser'); + $manager = $this->prophesize('Composer\\Repository\\RepositoryManager'); + $versionGuesser = $this->prophesize('Composer\\Package\\Version\\VersionGuesser'); $versionGuesser->guessVersion(Argument::cetera()) ->willReturn(array( 'name' => 'A', @@ -120,48 +111,28 @@ class RootPackageLoaderTest extends TestCase $this->markTestSkipped('proc_open() is not available'); } - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + $manager = $this->getMockBuilder('Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() ->getMock() ; - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $self = $this; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git branch -a --no-color --no-abbrev -v', $command); - $output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n"; - - return 0; - }) - ; - - $executor - ->expects($this->at(1)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git rev-list master..latest-production', $command); - $output = ""; - - return 0; - }) - ; + $process = new ProcessExecutorMock; + $process->expects(array( + array( + 'cmd' => 'git branch -a --no-color --no-abbrev -v', + 'stdout' => "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n", + ), + 'git rev-list master..latest-production', + ), true); $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser())); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $process, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'))); $this->assertEquals("dev-master", $package->getPrettyVersion()); + + $process->assertComplete($this); } public function testNonFeatureBranchPrettyVersion() @@ -170,36 +141,26 @@ class RootPackageLoaderTest extends TestCase $this->markTestSkipped('proc_open() is not available'); } - $manager = $this->getMockBuilder('\\Composer\\Repository\\RepositoryManager') + $manager = $this->getMockBuilder('Composer\\Repository\\RepositoryManager') ->disableOriginalConstructor() ->getMock() ; - $executor = $this->getMockBuilder('\\Composer\\Util\\ProcessExecutor') - ->setMethods(array('execute')) - ->disableArgumentCloning() - ->disableOriginalConstructor() - ->getMock() - ; - - $self = $this; - - $executor - ->expects($this->at(0)) - ->method('execute') - ->willReturnCallback(function ($command, &$output) use ($self) { - $self->assertEquals('git branch -a --no-color --no-abbrev -v', $command); - $output = "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n"; - - return 0; - }) - ; + $process = new ProcessExecutorMock; + $process->expects(array( + array( + 'cmd' => 'git branch -a --no-color --no-abbrev -v', + 'stdout' => "* latest-production 38137d2f6c70e775e137b2d8a7a7d3eaebf7c7e5 Commit message\n master 4f6ed96b0bc363d2aa4404c3412de1c011f67c66 Commit message\n" + ), + ), true); $config = new Config; $config->merge(array('repositories' => array('packagist' => false))); - $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $executor, new VersionParser())); + $loader = new RootPackageLoader($manager, $config, null, new VersionGuesser($config, $process, new VersionParser())); $package = $loader->load(array('require' => array('foo/bar' => 'self.version'), "non-feature-branches" => array("latest-.*"))); $this->assertEquals("dev-latest-production", $package->getPrettyVersion()); + + $process->assertComplete($this); } } diff --git a/tests/Composer/Test/Repository/Vcs/GitHubDriverTest.php b/tests/Composer/Test/Repository/Vcs/GitHubDriverTest.php index 7c2727c20..38dd7bc34 100644 --- a/tests/Composer/Test/Repository/Vcs/GitHubDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/GitHubDriverTest.php @@ -17,7 +17,10 @@ use Composer\Repository\Vcs\GitHubDriver; use Composer\Test\TestCase; use Composer\Util\Filesystem; use Composer\Util\Http\Response; +use Composer\Test\Mock\ProcessExecutorMock; use Composer\Config; +use Composer\Util\ProcessExecutor; +use Symfony\Component\Process\Process; class GitHubDriverTest extends TestCase { @@ -58,10 +61,8 @@ class GitHubDriverTest extends TestCase ->setConstructorArgs(array($io, $this->config)) ->getMock(); - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $process->expects($this->any()) - ->method('execute') - ->will($this->returnValue(1)); + $process = new ProcessExecutorMock; + $process->expects(array(), false, array('return' => 1)); $httpDownloader->expects($this->at(0)) ->method('get') @@ -139,11 +140,7 @@ class GitHubDriverTest extends TestCase ); $repoUrl = 'https://github.com/composer/packagist.git'; - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor') - ->disableOriginalConstructor() - ->getMock(); - - $gitHubDriver = new GitHubDriver($repoConfig, $io, $this->config, $httpDownloader, $process); + $gitHubDriver = new GitHubDriver($repoConfig, $io, $this->config, $httpDownloader, new ProcessExecutorMock); $gitHubDriver->initialize(); $this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha)); @@ -201,11 +198,7 @@ class GitHubDriverTest extends TestCase ); $repoUrl = 'https://github.com/composer/packagist.git'; - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor') - ->disableOriginalConstructor() - ->getMock(); - - $gitHubDriver = new GitHubDriver($repoConfig, $io, $this->config, $httpDownloader, $process); + $gitHubDriver = new GitHubDriver($repoConfig, $io, $this->config, $httpDownloader, new ProcessExecutorMock); $gitHubDriver->initialize(); $this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha)); @@ -239,10 +232,6 @@ class GitHubDriverTest extends TestCase ->method('isInteractive') ->will($this->returnValue(true)); - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor') - ->disableOriginalConstructor() - ->getMock(); - $httpDownloader = $this->getMockBuilder('Composer\Util\HttpDownloader') ->setConstructorArgs(array($io, $this->config)) ->getMock(); @@ -271,7 +260,7 @@ class GitHubDriverTest extends TestCase 'url' => $repoUrl, ); - $gitHubDriver = new GitHubDriver($repoConfig, $io, $this->config, $httpDownloader, $process); + $gitHubDriver = new GitHubDriver($repoConfig, $io, $this->config, $httpDownloader, new ProcessExecutorMock); $gitHubDriver->initialize(); $this->setAttribute($gitHubDriver, 'tags', array($identifier => $sha)); @@ -288,10 +277,6 @@ class GitHubDriverTest extends TestCase $identifier = 'v0.0.0'; $sha = 'SOMESHA'; - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor') - ->disableOriginalConstructor() - ->getMock(); - $io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock(); $io->expects($this->any()) ->method('isInteractive') @@ -310,39 +295,23 @@ class GitHubDriverTest extends TestCase $fs = new Filesystem(); $fs->removeDirectory(sys_get_temp_dir() . '/composer-test'); - $process->expects($this->at(0)) - ->method('execute') - ->with($this->equalTo('git config github.accesstoken')) - ->will($this->returnValue(1)); - - $process->expects($this->at(1)) - ->method('execute') - ->with($this->stringContains($repoSshUrl)) - ->will($this->returnValue(0)); - - $process->expects($this->at(2)) - ->method('execute') - ->with($this->stringContains('git show-ref --tags')); - - $process->expects($this->at(3)) - ->method('splitLines') - ->will($this->returnValue(array($sha.' refs/tags/'.$identifier))); - - $process->expects($this->at(4)) - ->method('execute') - ->with($this->stringContains('git branch --no-color --no-abbrev -v')); - - $process->expects($this->at(5)) - ->method('splitLines') - ->will($this->returnValue(array(' test_master edf93f1fccaebd8764383dc12016d0a1a9672d89 Fix test & behavior'))); - - $process->expects($this->at(6)) - ->method('execute') - ->with($this->stringContains('git branch --no-color')); - - $process->expects($this->at(7)) - ->method('splitLines') - ->will($this->returnValue(array('* test_master'))); + $process = new ProcessExecutorMock; + $process->expects(array( + array('cmd' => 'git config github.accesstoken', 'return' => 1), + 'git clone --mirror -- '.ProcessExecutor::escape($repoSshUrl).' '.ProcessExecutor::escape($this->config->get('cache-vcs-dir').'/git-github.com-composer-packagist.git/'), + array( + 'cmd' => 'git show-ref --tags --dereference', + 'stdout' => $sha.' refs/tags/'.$identifier, + ), + array( + 'cmd' => 'git branch --no-color --no-abbrev -v', + 'stdout' => ' test_master edf93f1fccaebd8764383dc12016d0a1a9672d89 Fix test & behavior', + ), + array( + 'cmd' => 'git branch --no-color', + 'stdout' => '* test_master', + ), + ), true); $repoConfig = array( 'url' => $repoUrl, @@ -367,6 +336,8 @@ class GitHubDriverTest extends TestCase $this->assertEquals('git', $source['type']); $this->assertEquals($repoSshUrl, $source['url']); $this->assertEquals($sha, $source['reference']); + + $process->assertComplete($this); } protected function setAttribute($object, $attribute, $value) diff --git a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php index 1c44e82dd..11f1524d3 100644 --- a/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/PerforceDriverTest.php @@ -17,6 +17,7 @@ use Composer\Test\TestCase; use Composer\Util\Filesystem; use Composer\Config; use Composer\Util\Perforce; +use Composer\Test\Mock\ProcessExecutorMock; /** * @author Matt Whittom @@ -42,7 +43,7 @@ class PerforceDriverTest extends TestCase $this->config = $this->getTestConfig($this->testPath); $this->repoConfig = $this->getTestRepoConfig(); $this->io = $this->getMockIOInterface(); - $this->process = $this->getMockProcessExecutor(); + $this->process = new ProcessExecutorMock; $this->httpDownloader = $this->getMockHttpDownloader(); $this->perforce = $this->getMockPerforce(); $this->driver = new PerforceDriver($this->repoConfig, $this->io, $this->config, $this->httpDownloader, $this->process); @@ -94,11 +95,6 @@ class PerforceDriverTest extends TestCase return $this->getMockBuilder('Composer\IO\IOInterface')->getMock(); } - protected function getMockProcessExecutor() - { - return $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - } - protected function getMockHttpDownloader() { return $this->getMockBuilder('Composer\Util\HttpDownloader')->disableOriginalConstructor()->getMock(); diff --git a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php index 9c61c3105..b2699e61b 100644 --- a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php @@ -16,6 +16,7 @@ use Composer\Repository\Vcs\SvnDriver; use Composer\Config; use Composer\Test\TestCase; use Composer\Util\Filesystem; +use Composer\Test\Mock\ProcessExecutorMock; class SvnDriverTest extends TestCase { @@ -50,16 +51,11 @@ class SvnDriverTest extends TestCase $output .= " authorization failed: Could not authenticate to server:"; $output .= " rejected Basic challenge (https://corp.svn.local/)"; - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $process->expects($this->at(1)) - ->method('execute') - ->will($this->returnValue(1)); - $process->expects($this->exactly(7)) - ->method('getErrorOutput') - ->will($this->returnValue($output)); - $process->expects($this->at(2)) - ->method('execute') - ->will($this->returnValue(0)); + $process = new ProcessExecutorMock; + $process->expects(array( + 'svn --version', + array('cmd' => '', 'return' => 1, 'stderr' => $output), + ), true); $repoConfig = array( 'url' => 'https://till:secret@corp.svn.local/repo', @@ -67,6 +63,8 @@ class SvnDriverTest extends TestCase $svn = new SvnDriver($repoConfig, $console, $this->config, $httpDownloader, $process); $svn->initialize(); + + $process->assertComplete($this); } public static function supportProvider() diff --git a/tests/Composer/Test/Util/BitbucketTest.php b/tests/Composer/Test/Util/BitbucketTest.php index 3262c2fe8..3182ac014 100644 --- a/tests/Composer/Test/Util/BitbucketTest.php +++ b/tests/Composer/Test/Util/BitbucketTest.php @@ -15,6 +15,7 @@ namespace Composer\Test\Util; use Composer\Util\Bitbucket; use Composer\Util\Http\Response; use Composer\Test\TestCase; +use Composer\Test\Mock\ProcessExecutorMock; /** * @author Paul Wenke @@ -456,10 +457,8 @@ class BitbucketTest extends TestCase public function testAuthorizeOAuthWithoutAvailableGitConfigToken() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $process->expects($this->once()) - ->method('execute') - ->willReturn(-1); + $process = new ProcessExecutorMock; + $process->expects(array(), false, array('return' => -1)); $bitbucket = new Bitbucket($this->io, $this->config, $process, $this->httpDownloader, $this->time); @@ -468,10 +467,7 @@ class BitbucketTest extends TestCase public function testAuthorizeOAuthWithAvailableGitConfigToken() { - $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); - $process->expects($this->once()) - ->method('execute') - ->willReturn(0); + $process = new ProcessExecutorMock; $bitbucket = new Bitbucket($this->io, $this->config, $process, $this->httpDownloader, $this->time); diff --git a/tests/Composer/Test/Util/GitLabTest.php b/tests/Composer/Test/Util/GitLabTest.php index 7c671afc0..e5ba33db6 100644 --- a/tests/Composer/Test/Util/GitLabTest.php +++ b/tests/Composer/Test/Util/GitLabTest.php @@ -93,8 +93,9 @@ class GitLabTest extends TestCase $httpDownloader ->expects($this->exactly(5)) ->method('get') - ->will($this->throwException(new TransportException('', 401))) + ->will($this->throwException($e = new TransportException('', 401))) ; + $e->setResponse('{}'); $config = $this->getConfigMock(); $config diff --git a/tests/Composer/Test/Util/GitTest.php b/tests/Composer/Test/Util/GitTest.php index 4fbc1826a..f1df7c2f7 100644 --- a/tests/Composer/Test/Util/GitTest.php +++ b/tests/Composer/Test/Util/GitTest.php @@ -16,7 +16,7 @@ use Composer\Config; use Composer\IO\IOInterface; use Composer\Util\Filesystem; use Composer\Util\Git; -use Composer\Util\ProcessExecutor; +use Composer\Test\Mock\ProcessExecutorMock; use Composer\Test\TestCase; class GitTest extends TestCase @@ -27,7 +27,7 @@ class GitTest extends TestCase private $io; /** @var Config&\PHPUnit\Framework\MockObject\MockObject */ private $config; - /** @var ProcessExecutor&\PHPUnit\Framework\MockObject\MockObject */ + /** @var ProcessExecutorMock */ private $process; /** @var Filesystem&\PHPUnit\Framework\MockObject\MockObject */ private $fs; @@ -36,7 +36,7 @@ class GitTest extends TestCase { $this->io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock(); $this->config = $this->getMockBuilder('Composer\Config')->disableOriginalConstructor()->getMock(); - $this->process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->disableOriginalConstructor()->getMock(); + $this->process = new ProcessExecutorMock; $this->fs = $this->getMockBuilder('Composer\Util\Filesystem')->disableOriginalConstructor()->getMock(); $this->git = new Git($this->io, $this->config, $this->process, $this->fs); } @@ -55,13 +55,11 @@ class GitTest extends TestCase $this->mockConfig($protocol); - $this->process - ->expects($this->once()) - ->method('execute') - ->with($this->equalTo('git command')) - ->willReturn(0); + $this->process->expects(array('git command'), true); $this->git->runCommand($commandCallable, 'https://github.com/acme/repo', null, true); + + $this->process->assertComplete($this); } public function publicGithubNoCredentialsProvider() @@ -85,20 +83,21 @@ class GitTest extends TestCase $this->mockConfig('https'); - $this->process - ->method('execute') - ->willReturnMap(array( - array('git command', null, null, 1), - array('git --version', null, null, 0), - )); + + $this->process->expects(array( + array('cmd' => 'git command', 'return' => 1), + array('cmd' => 'git --version', 'return' => 0), + ), true); $this->git->runCommand($commandCallable, 'https://github.com/acme/repo', null, true); + + $this->process->assertComplete($this); } /** * @dataProvider privateGithubWithCredentialsProvider */ - public function testRunCommandPrivateGitHubRepositoryNotInitialCloneNotInteractiveWithAuthentication($gitUrl, $protocol, $gitHubToken, $expectedUrl) + public function testRunCommandPrivateGitHubRepositoryNotInitialCloneNotInteractiveWithAuthentication($gitUrl, $protocol, $gitHubToken, $expectedUrl, $expectedFailuresBeforeSuccess) { $commandCallable = function ($url) use ($expectedUrl) { if ($url !== $expectedUrl) { @@ -110,13 +109,10 @@ class GitTest extends TestCase $this->mockConfig($protocol); - $this->process - ->expects($this->atLeast(2)) - ->method('execute') - ->willReturnMap(array( - array('git command failing', null, null, 1), - array('git command ok', null, null, 0), - )); + $expectedCalls = array_fill(0, $expectedFailuresBeforeSuccess, array('cmd' => 'git command failing', 'return' => 1)); + $expectedCalls[] = array('cmd' => 'git command ok', 'return' => 0); + + $this->process->expects($expectedCalls, true); $this->io ->method('isInteractive') @@ -135,13 +131,15 @@ class GitTest extends TestCase ->willReturn(array('username' => 'token', 'password' => $gitHubToken)); $this->git->runCommand($commandCallable, $gitUrl, null, true); + + $this->process->assertComplete($this); } public function privateGithubWithCredentialsProvider() { return array( - array('git@github.com:acme/repo.git', 'ssh', 'MY_GITHUB_TOKEN', 'https://token:MY_GITHUB_TOKEN@github.com/acme/repo.git'), - array('https://github.com/acme/repo', 'https', 'MY_GITHUB_TOKEN', 'https://token:MY_GITHUB_TOKEN@github.com/acme/repo.git'), + array('git@github.com:acme/repo.git', 'ssh', 'MY_GITHUB_TOKEN', 'https://token:MY_GITHUB_TOKEN@github.com/acme/repo.git', 1), + array('https://github.com/acme/repo', 'https', 'MY_GITHUB_TOKEN', 'https://token:MY_GITHUB_TOKEN@github.com/acme/repo.git', 2), ); }