Skip to content

Commit

Permalink
Introduce ProcessExecutorMock to fix deprecations and amount of mocki…
Browse files Browse the repository at this point in the history
…ng pain
  • Loading branch information
Seldaek committed Aug 18, 2021
1 parent 5062619 commit badf595
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 78 deletions.
3 changes: 3 additions & 0 deletions src/Composer/Util/ProcessExecutor.php
Expand Up @@ -371,6 +371,9 @@ public function getErrorOutput()
return $this->errorOutput;
}

/**
* @private
*/
public function outputHandler($type, $buffer)
{
if ($this->captureOutput) {
Expand Down
161 changes: 83 additions & 78 deletions tests/Composer/Test/Downloader/GitDownloaderTest.php
Expand Up @@ -17,6 +17,8 @@
use Composer\Test\TestCase;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Test\Mock\ProcessExecutorMock;
use DateTime;
use Prophecy\Argument;

class GitDownloaderTest extends TestCase
Expand Down Expand Up @@ -118,7 +120,11 @@ public function testDownload()
$processExecutor->expects($this->at(1))
->method('execute')
->with($this->equalTo($this->winCompat("git branch -r")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath')))
->will($this->returnValue(0));
->will($this->returnCallback(function ($cmd, &$output) {
$output = '';

return 0;
}));

$processExecutor->expects($this->at(2))
->method('execute')
Expand Down Expand Up @@ -189,7 +195,11 @@ public function testDownloadWithCache()
$processExecutor->expects($this->at(4))
->method('execute')
->with($this->equalTo($this->winCompat("git branch -r")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath')))
->will($this->returnValue(0));
->will($this->returnCallback(function ($cmd, &$output, $path) {
$output = '';

return 0;
}));

$processExecutor->expects($this->at(5))
->method('execute')
Expand Down Expand Up @@ -253,7 +263,11 @@ public function testDownloadUsesVariousProtocolsAndSetsPushUrlForGithub()
$processExecutor->expects($this->at(5))
->method('execute')
->with($this->equalTo('git branch -r'))
->will($this->returnValue(0));
->will($this->returnCallback(function ($cmd, &$output, $path) {
$output = '';

return 0;
}));

$processExecutor->expects($this->at(6))
->method('execute')
Expand Down Expand Up @@ -297,57 +311,61 @@ public function testDownloadAndSetPushUrlUseCustomVariousProtocolsForGithub($pro
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));
$processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->setMethods(array('execute'))->getMock();

$expectedGitCommand = $this->winCompat("git clone --no-checkout -- '{$url}' 'composerPath' && cd 'composerPath' && git remote add composer -- '{$url}' && git fetch composer && git remote set-url origin -- '{$url}' && git remote set-url composer -- '{$url}'");
$processExecutor->expects($this->at(0))
->method('execute')
->with($this->equalTo($expectedGitCommand))
->will($this->returnValue(0));

$expectedGitCommand = $this->winCompat("git remote set-url --push origin -- '{$pushUrl}'");
$processExecutor->expects($this->at(1))
->method('execute')
->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath')))
->will($this->returnValue(0));

$processExecutor->expects($this->exactly(4))
->method('execute')
->will($this->returnValue(0));
$process = new ProcessExecutorMock;
$process->expects(array(
$this->winCompat("git clone --no-checkout -- '{$url}' 'composerPath' && cd 'composerPath' && git remote add composer -- '{$url}' && git fetch composer && git remote set-url origin -- '{$url}' && git remote set-url composer -- '{$url}'"),
$this->winCompat("git remote set-url --push origin -- '{$pushUrl}'"),
'git branch -r',
$this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --"),
), true);

$config = new Config();
$config->merge(array('config' => array('github-protocols' => $protocols)));

$downloader = $this->getDownloaderMock(null, $config, $processExecutor);
$downloader = $this->getDownloaderMock(null, $config, $process);
$downloader->download($packageMock, 'composerPath');
$downloader->prepare('install', $packageMock, 'composerPath');
$downloader->install($packageMock, 'composerPath');
$downloader->cleanup('install', $packageMock, 'composerPath');

$process->assertComplete($this);
}

public function testDownloadThrowsRuntimeExceptionIfGitCommandFails()
{
$expectedGitCommand = $this->winCompat("git clone --no-checkout -- 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer -- 'https://example.com/composer/composer' && git fetch composer && git remote set-url origin -- 'https://example.com/composer/composer' && git remote set-url composer -- 'https://example.com/composer/composer'");
$packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
$packageMock->expects($this->any())
->method('getSourceReference')
->will($this->returnValue('ref'));
$packageMock->expects($this->any())
->method('getSourceUrls')
->will($this->returnValue(array('https://example.com/composer/composer')));
$processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->setMethods(array('execute'))->getMock();
$processExecutor->expects($this->at(0))
->method('execute')
->with($this->equalTo($expectedGitCommand))
->will($this->returnValue(1));
$packageMock->expects($this->any())
->method('getSourceUrl')
->will($this->returnValue('https://example.com/composer/composer'));
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));

$process = new ProcessExecutorMock;
$process->expects(array(
array(
'cmd' => $this->winCompat("git clone --no-checkout -- 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer -- 'https://example.com/composer/composer' && git fetch composer && git remote set-url origin -- 'https://example.com/composer/composer' && git remote set-url composer -- 'https://example.com/composer/composer'"),
'return' => 1,
),
));

// not using PHPUnit's expected exception because Prophecy exceptions extend from RuntimeException too so it is not safe
try {
$downloader = $this->getDownloaderMock(null, null, $processExecutor);
$downloader = $this->getDownloaderMock(null, null, $process);
$downloader->download($packageMock, 'composerPath');
$downloader->prepare('install', $packageMock, 'composerPath');
$downloader->install($packageMock, 'composerPath');
$downloader->cleanup('install', $packageMock, 'composerPath');

$process->assertComplete($this);

$this->fail('This test should throw');
} catch (\RuntimeException $e) {
if ('RuntimeException' !== get_class($e)) {
Expand Down Expand Up @@ -388,21 +406,29 @@ public function testUpdate()
$packageMock->expects($this->any())
->method('getVersion')
->will($this->returnValue('1.0.0.0'));
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));

$process = $this->prophesize('Composer\Util\ProcessExecutor');
$process->execute($this->winCompat('git show-ref --head -d'), Argument::cetera())->willReturn(0);
$process->execute($this->winCompat('git status --porcelain --untracked-files=no'), Argument::cetera())->willReturn(0);
$process->execute($this->winCompat('git remote -v'), Argument::cetera())->willReturn(0);
$process->execute($this->winCompat('git branch -r'), Argument::cetera())->willReturn(0);
$process->execute($expectedGitUpdateCommand, null, $this->winCompat($this->workingDir))->willReturn(0)->shouldBeCalled();
$process->execute($this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --"), null, $this->winCompat($this->workingDir))->willReturn(0)->shouldBeCalled();
$process = new ProcessExecutorMock;
$process->expects(array(
$this->winCompat('git show-ref --head -d'),
$this->winCompat('git status --porcelain --untracked-files=no'),
$this->winCompat('git remote -v'),
$expectedGitUpdateCommand,
$this->winCompat('git branch -r'),
$this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --"),
$this->winCompat('git remote -v'),
), true);

$this->fs->ensureDirectoryExists($this->workingDir.'/.git');
$downloader = $this->getDownloaderMock(null, new Config(), $process->reveal());
$downloader = $this->getDownloaderMock(null, new Config(), $process);
$downloader->download($packageMock, $this->workingDir, $packageMock);
$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 testUpdateWithNewRepoUrl()
Expand All @@ -422,59 +448,38 @@ public function testUpdateWithNewRepoUrl()
$packageMock->expects($this->any())
->method('getVersion')
->will($this->returnValue('1.0.0.0'));
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));

$processExecutor = $this->getMockBuilder('Composer\Util\ProcessExecutor')->setMethods(array('execute'))->getMock();
$processExecutor->expects($this->at(0))
->method('execute')
->with($this->equalTo($this->winCompat("git show-ref --head -d")))
->will($this->returnValue(0));
$processExecutor->expects($this->at(1))
->method('execute')
->with($this->equalTo($this->winCompat("git status --porcelain --untracked-files=no")))
->will($this->returnValue(0));
$processExecutor->expects($this->at(2))
->method('execute')
->with($this->equalTo($this->winCompat("git remote -v")))
->will($this->returnValue(0));
$processExecutor->expects($this->at(3))
->method('execute')
->with($this->equalTo($this->winCompat($expectedGitUpdateCommand)), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
->will($this->returnValue(0));
$processExecutor->expects($this->at(4))
->method('execute')
->with($this->equalTo('git branch -r'))
->will($this->returnValue(0));
$processExecutor->expects($this->at(5))
->method('execute')
->with($this->equalTo($this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
->will($this->returnValue(0));
$processExecutor->expects($this->at(6))
->method('execute')
->with($this->equalTo($this->winCompat("git remote -v")))
->will($this->returnCallback(function ($cmd, &$output, $cwd) {
$output = 'origin https://github.com/old/url (fetch)
$process = new ProcessExecutorMock;
$process->expects(array(
$this->winCompat("git show-ref --head -d"),
$this->winCompat("git status --porcelain --untracked-files=no"),
$this->winCompat("git remote -v"),
$this->winCompat($expectedGitUpdateCommand),
'git branch -r',
$this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --"),
array(
'cmd' => $this->winCompat("git remote -v"),
'stdout' => 'origin https://github.com/old/url (fetch)
origin https://github.com/old/url (push)
composer https://github.com/old/url (fetch)
composer https://github.com/old/url (push)
';

return 0;
}));
$processExecutor->expects($this->at(7))
->method('execute')
->with($this->equalTo($this->winCompat("git remote set-url origin -- 'https://github.com/composer/composer'")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
->will($this->returnValue(0));
$processExecutor->expects($this->at(8))
->method('execute')
->with($this->equalTo($this->winCompat("git remote set-url --push origin -- 'git@github.com:composer/composer.git'")), $this->equalTo(null), $this->equalTo($this->winCompat($this->workingDir)))
->will($this->returnValue(0));
',
),
$this->winCompat("git remote set-url origin -- 'https://github.com/composer/composer'"),
$this->winCompat("git remote set-url --push origin -- 'git@github.com:composer/composer.git'"),
), true);

$this->fs->ensureDirectoryExists($this->workingDir.'/.git');
$downloader = $this->getDownloaderMock(null, new Config(), $processExecutor);
$downloader = $this->getDownloaderMock(null, new Config(), $process);
$downloader->download($packageMock, $this->workingDir, $packageMock);
$downloader->prepare('update', $packageMock, $this->workingDir, $packageMock);
$downloader->update($packageMock, $packageMock, $this->workingDir);
$downloader->cleanup('update', $packageMock, $this->workingDir, $packageMock);

$process->assertComplete($this);
}

/**
Expand Down

0 comments on commit badf595

Please sign in to comment.