1
0
Fork 0

Add command testing utilities to TestCase, add tests for ConfigCommand

pull/10769/head
Jordi Boggiano 2022-05-11 16:05:35 +02:00
parent ebfdae8883
commit fdab6657c7
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
35 changed files with 253 additions and 73 deletions

View File

@ -305,7 +305,7 @@ EOT
}
if (is_array($value)) {
$value = json_encode($value);
$value = JsonFile::encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
$sourceOfConfigValue = '';

View File

@ -91,7 +91,7 @@ class AutoloadGeneratorTest extends TestCase
{
$this->fs = new Filesystem;
$this->workingDir = $this->getUniqueTmpDirectory();
$this->workingDir = self::getUniqueTmpDirectory();
$this->vendorDir = $this->workingDir.DIRECTORY_SEPARATOR.'composer-test-autoload';
$this->ensureDirectoryExistsAndClear($this->vendorDir);

View File

@ -148,7 +148,7 @@ class ClassMapGeneratorTest extends TestCase
{
$this->checkIfFinderIsAvailable();
$tempDir = $this->getUniqueTmpDirectory();
$tempDir = self::getUniqueTmpDirectory();
$this->ensureDirectoryExistsAndClear($tempDir . '/other');
$finder = new Finder();
@ -190,7 +190,7 @@ class ClassMapGeneratorTest extends TestCase
*/
public function testUnambiguousReference(): void
{
$tempDir = $this->getUniqueTmpDirectory();
$tempDir = self::getUniqueTmpDirectory();
file_put_contents($tempDir . '/A.php', "<?php\nclass A {}");
file_put_contents(

View File

@ -30,7 +30,7 @@ class CacheTest extends TestCase
public function setUp(): void
{
$this->root = $this->getUniqueTmpDirectory();
$this->root = self::getUniqueTmpDirectory();
$this->files = array();
$zeros = str_repeat('0', 1000);

View File

@ -0,0 +1,146 @@
<?php declare(strict_types=1);
/*
* 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\Command;
use Composer\Composer;
use Composer\Config;
use Composer\Script\Event as ScriptEvent;
use Composer\Test\TestCase;
use Composer\Util\Filesystem;
class ConfigCommandTest extends TestCase
{
/**
* @dataProvider provideConfigUpdates
* @param array<mixed> $before
* @param array<mixed> $command
* @param array<mixed> $expected
*/
public function testConfigUpdates(array $before, array $command, array $expected): void
{
$this->initTempComposer($before);
$appTester = $this->getApplicationTester();
$appTester->run(array_merge(['command' => 'config'], $command));
$appTester->assertCommandIsSuccessful($appTester->getDisplay());
$this->assertSame($expected, json_decode((string) file_get_contents('composer.json'), true));
}
public function provideConfigUpdates(): \Generator
{
yield 'set scripts' => [
[],
['setting-key' => 'scripts.test', 'setting-value' => ['foo bar']],
['scripts' => ['test' => 'foo bar']],
];
yield 'unset scripts' => [
['scripts' => ['test' => 'foo bar', 'lala' => 'baz']],
['setting-key' => 'scripts.lala', '--unset' => true],
['scripts' => ['test' => 'foo bar']],
];
yield 'set single config with bool normalizer' => [
[],
['setting-key' => 'use-github-api', 'setting-value' => ['1']],
['config' => ['use-github-api' => true]],
];
yield 'set multi config' => [
[],
['setting-key' => 'github-protocols', 'setting-value' => ['https', 'git']],
['config' => ['github-protocols' => ['https', 'git']]],
];
yield 'set version' => [
[],
['setting-key' => 'version', 'setting-value' => ['1.0.0']],
['version' => '1.0.0'],
];
yield 'unset version' => [
['version' => '1.0.0'],
['setting-key' => 'version', '--unset' => true],
[],
];
yield 'unset arbitrary property' => [
['random-prop' => '1.0.0'],
['setting-key' => 'random-prop', '--unset' => true],
[],
];
yield 'set preferred-install' => [
[],
['setting-key' => 'preferred-install.foo/*', 'setting-value' => ['source']],
['config' => ['preferred-install' => ['foo/*' => 'source']]],
];
yield 'unset preferred-install' => [
['config' => ['preferred-install' => ['foo/*' => 'source']]],
['setting-key' => 'preferred-install.foo/*', '--unset' => true],
['config' => ['preferred-install' => []]],
];
}
/**
* @dataProvider provideConfigReads
* @param array<mixed> $composerJson
* @param array<mixed> $command
*/
public function testConfigReads(array $composerJson, array $command, string $expected): void
{
$this->initTempComposer($composerJson);
$appTester = $this->getApplicationTester();
$appTester->run(array_merge(['command' => 'config'], $command));
$appTester->assertCommandIsSuccessful();
$this->assertSame($expected, trim($appTester->getDisplay(true)));
$this->assertSame($composerJson, json_decode((string) file_get_contents('composer.json'), true), 'The composer.json should not be modified by config reads');
}
public function provideConfigReads(): \Generator
{
yield 'read description' => [
['description' => 'foo bar'],
['setting-key' => 'description'],
'foo bar',
];
yield 'read vendor-dir with source' => [
['config' => ['vendor-dir' => 'lala']],
['setting-key' => 'vendor-dir', '--source' => true],
'lala (./composer.json)',
];
yield 'read default vendor-dir' => [
[],
['setting-key' => 'vendor-dir'],
'vendor',
];
yield 'read repos by named key' => [
['repositories' => ['foo' => ['type' => 'vcs', 'url' => 'https://example.org']]],
['setting-key' => 'repositories.foo'],
'{"type":"vcs","url":"https://example.org"}',
];
yield 'read repos by numeric index' => [
['repositories' => [['type' => 'vcs', 'url' => 'https://example.org']]],
['setting-key' => 'repos.0'],
'{"type":"vcs","url":"https://example.org"}',
];
yield 'read all repos includes the default packagist' => [
['repositories' => ['foo' => ['type' => 'vcs', 'url' => 'https://example.org']]],
['setting-key' => 'repos'],
'{"foo":{"type":"vcs","url":"https://example.org"},"packagist.org":{"type":"composer","url":"https://repo.packagist.org"}}',
];
yield 'read all repos does not include the disabled packagist' => [
['repositories' => ['foo' => ['type' => 'vcs', 'url' => 'https://example.org'], 'packagist.org' => false]],
['setting-key' => 'repos'],
'{"foo":{"type":"vcs","url":"https://example.org"}}',
];
}
}

View File

@ -12,35 +12,14 @@
namespace Composer\Test\Command;
use Composer\Command\RunScriptCommand;
use Composer\Composer;
use Composer\Config;
use Composer\Console\Application;
use Composer\Script\Event as ScriptEvent;
use Composer\Test\TestCase;
use Composer\Util\Filesystem;
use Symfony\Component\Console\Tester\ApplicationTester;
class RunScriptCommandTest extends TestCase
{
/**
* @var string
*/
private $home;
public function setUp(): void
{
$this->home = $this->getUniqueTmpDirectory();
}
protected function tearDown(): void
{
parent::tearDown();
$fs = new Filesystem();
$fs->removeDirectory($this->home);
}
/**
* @dataProvider getDevOptions
* @param bool $dev
@ -112,7 +91,7 @@ class RunScriptCommandTest extends TestCase
public function testCanListScripts(): void
{
$manifest = [
$this->initTempComposer([
'scripts' => [
'test' => '@php test',
'fix-cs' => 'php-cs-fixer fix',
@ -120,20 +99,14 @@ class RunScriptCommandTest extends TestCase
'scripts-descriptions' => [
'fix-cs' => 'Run the codestyle fixer',
],
];
]);
file_put_contents($this->home.'/composer.json', json_encode($manifest));
$appTester = $this->getApplicationTester();
$appTester->run(['command' => 'run-script', '--list' => true]);
$application = new Application();
$application->setAutoExit(false);
$application->add(new RunScriptCommand());
$appTester->assertCommandIsSuccessful();
$tester = new ApplicationTester($application);
$tester->run(['command' => 'run-script', '--list' => true, '-d' => $this->home]);
$tester->assertCommandIsSuccessful();
$output = $tester->getDisplay();
$output = $appTester->getDisplay();
$this->assertStringContainsString('Runs the test script as defined in composer.json.', $output, 'The default description for the test script should be printed');
$this->assertStringContainsString('Run the codestyle fixer', $output, 'The custom description for the fix-cs script should be printed');

View File

@ -37,7 +37,7 @@ class JsonConfigSourceTest extends TestCase
protected function setUp(): void
{
$this->fs = new Filesystem;
$this->workingDir = $this->getUniqueTmpDirectory();
$this->workingDir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -69,7 +69,7 @@ class FileDownloaderTest extends TestCase
$package = $this->getPackage();
$package->setDistUrl('url');
$path = $this->createTempFile($this->getUniqueTmpDirectory());
$path = $this->createTempFile(self::getUniqueTmpDirectory());
$downloader = $this->getDownloader();
try {
@ -105,7 +105,7 @@ class FileDownloaderTest extends TestCase
$package = $this->getPackage();
$package->setDistUrl('http://example.com/script.js');
$path = $this->getUniqueTmpDirectory();
$path = self::getUniqueTmpDirectory();
$ioMock = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();
$ioMock->expects($this->any())
->method('write')
@ -142,7 +142,7 @@ class FileDownloaderTest extends TestCase
public function testDownloadWithCustomProcessedUrl(): void
{
$path = $this->getUniqueTmpDirectory();
$path = self::getUniqueTmpDirectory();
$package = $this->getPackage();
$package->setDistUrl('url');
@ -225,7 +225,7 @@ class FileDownloaderTest extends TestCase
public function testDownloadWithCustomCacheKey(): void
{
$path = $this->getUniqueTmpDirectory();
$path = self::getUniqueTmpDirectory();
$package = $this->getPackage();
$package->setDistUrl('url');
@ -339,7 +339,7 @@ class FileDownloaderTest extends TestCase
$filesystem = $this->getMockBuilder('Composer\Util\Filesystem')->getMock();
$path = $this->getUniqueTmpDirectory();
$path = self::getUniqueTmpDirectory();
$config = $this->getConfig(['vendor-dir' => $path.'/vendor']);
$downloader = $this->getDownloader(null, $config, null, null, null, $filesystem);
@ -384,7 +384,7 @@ class FileDownloaderTest extends TestCase
[$this->stringContains('Downgrading')]
);
$path = $this->getUniqueTmpDirectory();
$path = self::getUniqueTmpDirectory();
$config = $this->getConfig(['vendor-dir' => $path.'/vendor']);
$filesystem = $this->getMockBuilder('Composer\Util\Filesystem')->getMock();

View File

@ -23,7 +23,7 @@ class FossilDownloaderTest extends TestCase
protected function setUp(): void
{
$this->workingDir = $this->getUniqueTmpDirectory();
$this->workingDir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -33,7 +33,7 @@ class GitDownloaderTest extends TestCase
$this->initGitVersion('1.0.0');
$this->fs = new Filesystem;
$this->workingDir = $this->getUniqueTmpDirectory();
$this->workingDir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -23,7 +23,7 @@ class HgDownloaderTest extends TestCase
protected function setUp(): void
{
$this->workingDir = $this->getUniqueTmpDirectory();
$this->workingDir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -43,7 +43,7 @@ class PerforceDownloaderTest extends TestCase
protected function setUp(): void
{
$this->testPath = $this->getUniqueTmpDirectory();
$this->testPath = self::getUniqueTmpDirectory();
$this->repoConfig = $this->getRepoConfig();
$this->config = $this->getConfig();
$this->io = $this->getMockIoInterface();

View File

@ -36,7 +36,7 @@ class XzDownloaderTest extends TestCase
if (Platform::isWindows()) {
$this->markTestSkipped('Skip test on Windows');
}
$this->testDir = $this->getUniqueTmpDirectory();
$this->testDir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -37,7 +37,7 @@ class ZipDownloaderTest extends TestCase
public function setUp(): void
{
$this->testDir = $this->getUniqueTmpDirectory();
$this->testDir = self::getUniqueTmpDirectory();
$this->io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();
$this->config = $this->getMockBuilder('Composer\Config')->getMock();
$dlConfig = $this->getMockBuilder('Composer\Config')->getMock();

View File

@ -46,7 +46,7 @@ class InstalledVersionsTest extends TestCase
public function setUp(): void
{
$this->root = $this->getUniqueTmpDirectory();
$this->root = self::getUniqueTmpDirectory();
$dir = $this->root;
InstalledVersions::reload(require __DIR__.'/Repository/Fixtures/installed.php');

View File

@ -48,7 +48,7 @@ class BinaryInstallerTest extends TestCase
{
$this->fs = new Filesystem;
$this->rootDir = $this->getUniqueTmpDirectory();
$this->rootDir = self::getUniqueTmpDirectory();
$this->vendorDir = $this->rootDir.DIRECTORY_SEPARATOR.'vendor';
$this->ensureDirectoryExistsAndClear($this->vendorDir);

View File

@ -74,7 +74,7 @@ class LibraryInstallerTest extends TestCase
$this->config = new Config(false);
$this->composer->setConfig($this->config);
$this->rootDir = $this->getUniqueTmpDirectory();
$this->rootDir = self::getUniqueTmpDirectory();
$this->vendorDir = $this->rootDir.DIRECTORY_SEPARATOR.'vendor';
self::ensureDirectoryExistsAndClear($this->vendorDir);

View File

@ -45,7 +45,7 @@ use Symfony\Component\Console\Formatter\OutputFormatter;
class InstallerTest extends TestCase
{
/** @var string */
protected $prevCwd;
private $prevCwd;
/** @var ?string */
protected $tempComposerHome;

View File

@ -39,7 +39,7 @@ class ArchivableFilesFinderTest extends TestCase
$this->fs = $fs;
$this->sources = $fs->normalizePath(
$this->getUniqueTmpDirectory()
self::getUniqueTmpDirectory()
);
$fileTree = array(

View File

@ -38,7 +38,7 @@ abstract class ArchiverTest extends TestCase
{
$this->filesystem = new Filesystem();
$this->process = new ProcessExecutor();
$this->testDir = $this->getUniqueTmpDirectory();
$this->testDir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -22,7 +22,7 @@ class PharArchiverTest extends ArchiverTest
// Set up repository
$this->setupDummyRepo();
$package = $this->setupPackage();
$target = $this->getUniqueTmpDirectory().'/composer_archiver_test.tar';
$target = self::getUniqueTmpDirectory().'/composer_archiver_test.tar';
// Test archive
$archiver = new PharArchiver();
@ -37,7 +37,7 @@ class PharArchiverTest extends ArchiverTest
// Set up repository
$this->setupDummyRepo();
$package = $this->setupPackage();
$target = $this->getUniqueTmpDirectory().'/composer_archiver_test.zip';
$target = self::getUniqueTmpDirectory().'/composer_archiver_test.zip';
// Test archive
$archiver = new PharArchiver();

View File

@ -73,7 +73,7 @@ class PluginInstallerTest extends TestCase
{
$loader = new JsonLoader(new ArrayLoader());
$this->packages = array();
$this->directory = $this->getUniqueTmpDirectory();
$this->directory = self::getUniqueTmpDirectory();
for ($i = 1; $i <= 8; $i++) {
$filename = '/Fixtures/plugin-v'.$i.'/composer.json';
mkdir(dirname($this->directory . $filename), 0777, true);

View File

@ -127,7 +127,7 @@ class FilesystemRepositoryTest extends TestCase
public function testRepositoryWritesInstalledPhp(): void
{
$dir = $this->getUniqueTmpDirectory();
$dir = self::getUniqueTmpDirectory();
chdir($dir);
$json = new JsonFile($dir.'/installed.json');

View File

@ -24,7 +24,7 @@ class RepositoryManagerTest extends TestCase
public function setUp(): void
{
$this->tmpdir = $this->getUniqueTmpDirectory();
$this->tmpdir = self::getUniqueTmpDirectory();
}
protected function tearDown(): void

View File

@ -30,7 +30,7 @@ class FossilDriverTest extends TestCase
public function setUp(): void
{
$this->home = $this->getUniqueTmpDirectory();
$this->home = self::getUniqueTmpDirectory();
$this->config = new Config();
$this->config->merge(array(
'config' => array(

View File

@ -37,7 +37,7 @@ class GitBitbucketDriverTest extends TestCase
{
$this->io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();
$this->home = $this->getUniqueTmpDirectory();
$this->home = self::getUniqueTmpDirectory();
$this->config = new Config();
$this->config->merge(array(

View File

@ -28,7 +28,7 @@ class GitHubDriverTest extends TestCase
public function setUp(): void
{
$this->home = $this->getUniqueTmpDirectory();
$this->home = self::getUniqueTmpDirectory();
$this->config = new Config();
$this->config->merge(array(
'config' => array(

View File

@ -51,7 +51,7 @@ class GitLabDriverTest extends TestCase
public function setUp(): void
{
$this->home = $this->getUniqueTmpDirectory();
$this->home = self::getUniqueTmpDirectory();
$this->config = $this->getConfig([
'home' => $this->home,
'gitlab-domains' => array(

View File

@ -30,7 +30,7 @@ class HgDriverTest extends TestCase
public function setUp(): void
{
$this->io = $this->getMockBuilder('Composer\IO\IOInterface')->getMock();
$this->home = $this->getUniqueTmpDirectory();
$this->home = self::getUniqueTmpDirectory();
$this->config = new Config();
$this->config->merge(array(
'config' => array(

View File

@ -63,7 +63,7 @@ class PerforceDriverTest extends TestCase
protected function setUp(): void
{
$this->testPath = $this->getUniqueTmpDirectory();
$this->testPath = self::getUniqueTmpDirectory();
$this->config = $this->getTestConfig($this->testPath);
$this->repoConfig = array(
'url' => self::TEST_URL,

View File

@ -31,7 +31,7 @@ class SvnDriverTest extends TestCase
public function setUp(): void
{
$this->home = $this->getUniqueTmpDirectory();
$this->home = self::getUniqueTmpDirectory();
$this->config = new Config();
$this->config->merge(array(
'config' => array(

View File

@ -53,8 +53,8 @@ class VcsRepositoryTest extends TestCase
}
$oldCwd = Platform::getCwd();
self::$composerHome = $this->getUniqueTmpDirectory();
self::$gitRepo = $this->getUniqueTmpDirectory();
self::$composerHome = self::getUniqueTmpDirectory();
self::$gitRepo = self::getUniqueTmpDirectory();
if (!@chdir(self::$gitRepo)) {
$this->skipped = 'Could not move into the temp git repo '.self::$gitRepo;

View File

@ -13,7 +13,9 @@
namespace Composer\Test;
use Composer\Config;
use Composer\Console\Application;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Pcre\Preg;
use Composer\Semver\VersionParser;
use Composer\Package\PackageInterface;
@ -23,6 +25,7 @@ use Composer\Test\Mock\ProcessExecutorMock;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer;
use Symfony\Component\Console\Tester\ApplicationTester;
use Symfony\Component\Process\ExecutableFinder;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\BasePackage;
@ -53,6 +56,12 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
* @var list<ProcessExecutorMock>
*/
private $processExecutorMocks = [];
/**
* @var list<string>
*/
private $tempComposerDirs = [];
/** @var string|null */
private $prevCwd = null;
protected function tearDown(): void
{
@ -63,6 +72,17 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
foreach ($this->processExecutorMocks as $mock) {
$mock->assertComplete();
}
if (null !== $this->prevCwd) {
chdir($this->prevCwd);
$this->prevCwd = null;
Platform::clearEnv('COMPOSER_HOME');
Platform::clearEnv('COMPOSER_DISABLE_XDEBUG_WARN');
}
$fs = new Filesystem();
foreach ($this->tempComposerDirs as $dir) {
$fs->removeDirectory($dir);
}
}
/**
@ -84,6 +104,42 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
throw new \RuntimeException('Failed to create a unique temporary directory.');
}
/**
* Creates a composer.json / auth.json inside a temp dir and chdir() into it
*
* The directory will be cleaned up on tearDown automatically.
*
* @param mixed[] $composerJson
* @param mixed[] $authJson
* @return string the newly created temp dir
*/
public function initTempComposer(array $composerJson = [], array $authJson = []): string
{
$dir = self::getUniqueTmpDirectory();
$this->tempComposerDirs[] = $dir;
$this->prevCwd = Platform::getCwd();
Platform::putEnv('COMPOSER_HOME', $dir.'/composer-home');
Platform::putEnv('COMPOSER_DISABLE_XDEBUG_WARN', '1');
chdir($dir);
file_put_contents($dir.'/composer.json', JsonFile::encode($composerJson, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT));
file_put_contents($dir.'/auth.json', JsonFile::encode($authJson, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT));
return $dir;
}
public function getApplicationTester(): ApplicationTester
{
$application = new Application();
$application->setAutoExit(false);
$application->setCatchExceptions(false);
return new ApplicationTester($application);
}
/**
* @return VersionParser
*/

View File

@ -35,8 +35,8 @@ class FilesystemTest extends TestCase
public function setUp(): void
{
$this->fs = new Filesystem;
$this->workingDir = $this->getUniqueTmpDirectory();
$this->testFile = $this->getUniqueTmpDirectory() . '/composer_test_file';
$this->workingDir = self::getUniqueTmpDirectory();
$this->testFile = self::getUniqueTmpDirectory() . '/composer_test_file';
}
protected function tearDown(): void

View File

@ -23,3 +23,8 @@ require __DIR__.'/../src/Composer/InstalledVersions.php';
require __DIR__.'/Composer/Test/TestCase.php';
Platform::putEnv('COMPOSER_TESTS_ARE_RUNNING', '1');
// symfony/phpunit-bridge sets some default env vars which we do not need polluting the test env
Platform::clearEnv('COMPOSER');
Platform::clearEnv('COMPOSER_VENDOR_DIR');
Platform::clearEnv('COMPOSER_BIN_DIR');