|
|
|
<?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\Command\InitCommand;
|
|
|
|
use Composer\Util\Filesystem;
|
|
|
|
use Symfony\Component\Console\Tester\ApplicationTester;
|
|
|
|
use Composer\Command\RequireCommand;
|
|
|
|
use Symfony\Component\Console\Input\ArrayInput;
|
|
|
|
use Composer\Console\Application;
|
|
|
|
use Composer\Test\TestCase;
|
|
|
|
use Symfony\Component\Process\Process;
|
|
|
|
|
|
|
|
class RequireCommandTest extends TestCase
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
private $start_directory;
|
|
|
|
private $working_directory;
|
|
|
|
private $local_repository;
|
|
|
|
|
|
|
|
public function setUp(): void
|
|
|
|
{
|
|
|
|
$this->local_repository = $this->getUniqueTmpDirectory();
|
|
|
|
|
|
|
|
$repo_manifest = [
|
|
|
|
'name' => 'testvendor/testpackage',
|
|
|
|
'version' => '1.0.0',
|
|
|
|
'type' => 'library',
|
|
|
|
'autoload' => [
|
|
|
|
'psr-4' => [
|
|
|
|
'TestVendor\\Testpackage\\' => 'src/',
|
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
|
|
|
file_put_contents(
|
|
|
|
$this->local_repository.'/composer.json',
|
|
|
|
json_encode(
|
|
|
|
$repo_manifest,
|
|
|
|
JSON_UNESCAPED_SLASHES,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->working_directory = $this->getUniqueTmpDirectory();
|
|
|
|
|
|
|
|
$manifest = [
|
|
|
|
'name' => 'test/something',
|
|
|
|
'require' => (object) null,
|
|
|
|
'repositories' => [
|
|
|
|
[
|
|
|
|
'type' => 'path',
|
|
|
|
'url' => $this->local_repository,
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'packagist.org' => false
|
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
|
|
|
file_put_contents(
|
|
|
|
$this->working_directory.'/composer.json',
|
|
|
|
json_encode($manifest, JSON_UNESCAPED_SLASHES)
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->start_directory = getcwd();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function tearDown(): void
|
|
|
|
{
|
|
|
|
parent::tearDown();
|
|
|
|
|
|
|
|
// Reset the working directory. Some commands leave the working
|
|
|
|
// directory contaminated when they exit with an error.
|
|
|
|
chdir($this->start_directory);
|
|
|
|
|
|
|
|
$fs = new Filesystem();
|
|
|
|
$fs->removeDirectory($this->working_directory);
|
|
|
|
$fs->removeDirectory($this->local_repository);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* testcase: UC01-001
|
|
|
|
*/
|
|
|
|
public function testInstallPackage(): void
|
|
|
|
{
|
|
|
|
// Arrange
|
|
|
|
$application = new Application();
|
|
|
|
$application->setAutoExit(false);
|
|
|
|
$application->add(new RequireCommand());
|
|
|
|
|
|
|
|
$local_repository_class_code = '<?php namespace TestVendor\\Testpackage { '
|
|
|
|
. 'class TestClass { '
|
|
|
|
. 'public function printTestClass() { echo "TestClass"; } } }';
|
|
|
|
$local_repository_class_file_dir = $this->local_repository . '/src';
|
|
|
|
$local_repository_class_file = $local_repository_class_file_dir . '/TestClass.php';
|
|
|
|
|
|
|
|
mkdir($local_repository_class_file_dir, 0777, true);
|
|
|
|
file_put_contents($local_repository_class_file, $local_repository_class_code);
|
|
|
|
|
|
|
|
$check_autoload_code = 'include "./vendor/autoload.php";'
|
|
|
|
. 'use TestVendor\\Testpackage\\TestClass;'
|
|
|
|
. '(new TestClass())->printTestClass();';
|
|
|
|
$check_autoload_process = new Process(['php', '-r', $check_autoload_code]);
|
|
|
|
$check_autoload_process->setWorkingDirectory($this->working_directory);
|
|
|
|
|
|
|
|
// Act
|
|
|
|
$tester = new ApplicationTester($application);
|
|
|
|
$tester->run([
|
|
|
|
'command' => 'require',
|
|
|
|
// Confirmation 1: provide dependency name of format vendor/package
|
|
|
|
'packages' => [ 'testvendor/testpackage' ],
|
|
|
|
'-d' => $this->working_directory,
|
|
|
|
]);
|
|
|
|
|
|
|
|
$check_autoload_process->run();
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$output = $tester->getDisplay();
|
|
|
|
|
|
|
|
// Confirmation 4: exit code 0
|
|
|
|
$tester->assertCommandIsSuccessful();
|
|
|
|
|
|
|
|
$this->assertStringContainsString('Installing testvendor/testpackage', $output);
|
|
|
|
|
|
|
|
// Confirmation 2: dependency is present in vendor directory
|
|
|
|
$this->assertTrue(file_exists($this->working_directory . '/vendor/testvendor/testpackage'));
|
|
|
|
|
|
|
|
// Confirmation 3: dependency classes can be autoloaded
|
|
|
|
$this->assertEquals(0, $check_autoload_process->getExitCode());
|
|
|
|
$this->assertEquals('TestClass', $check_autoload_process->getOutput());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* testcase: UC01-002
|
|
|
|
*/
|
|
|
|
public function testInstallPackageSaveToComposerJson(): void
|
|
|
|
{
|
|
|
|
// Arrange
|
|
|
|
$application = new Application();
|
|
|
|
$application->setAutoExit(false);
|
|
|
|
$application->add(new RequireCommand());
|
|
|
|
|
|
|
|
// Act
|
|
|
|
$tester = new ApplicationTester($application);
|
|
|
|
|
|
|
|
// Confirmation 1: Install dependency
|
|
|
|
$tester->run([
|
|
|
|
'command' => 'require',
|
|
|
|
'packages' => [ 'testvendor/testpackage 1.0.0' ],
|
|
|
|
'-d' => $this->working_directory,
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$manifest = json_decode(
|
|
|
|
file_get_contents($this->working_directory . '/composer.json'),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
|
|
|
|
// Confirmation 2: dependency has been added to composer.json
|
|
|
|
$this->assertArrayHasKey('testvendor/testpackage', $manifest['require']);
|
|
|
|
$this->assertEquals('1.0.0', $manifest['require']['testvendor/testpackage']);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* testcase: UC01-003
|
|
|
|
*/
|
|
|
|
public function testInstallPackagesSaveToComposerLock(): void
|
|
|
|
{
|
|
|
|
// Arrange
|
|
|
|
$application = new Application();
|
|
|
|
$application->setAutoExit(false);
|
|
|
|
$application->add(new RequireCommand());
|
|
|
|
|
|
|
|
// Act
|
|
|
|
$tester = new ApplicationTester($application);
|
|
|
|
$tester->run([
|
|
|
|
'command' => 'require',
|
|
|
|
'packages' => [ 'testvendor/testpackage 1.0.0' ],
|
|
|
|
'-d' => $this->working_directory,
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$lockfile = json_decode(
|
|
|
|
file_get_contents($this->working_directory . '/composer.lock'),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
$packages = $lockfile['packages'];
|
|
|
|
$installed_package = null;
|
|
|
|
foreach($packages as $package) {
|
|
|
|
if ($package['name'] === 'testvendor/testpackage') {
|
|
|
|
$installed_package = $package;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->assertNotNull($installed_package);
|
|
|
|
$this->assertEquals('1.0.0', $installed_package['version']);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* testcase: UC01-004
|
|
|
|
*/
|
|
|
|
public function testInstallMisspelledPackage(): void
|
|
|
|
{
|
|
|
|
// Arrange
|
|
|
|
$application = new Application();
|
|
|
|
$application->setAutoExit(false);
|
|
|
|
$application->add(new RequireCommand());
|
|
|
|
|
|
|
|
// Act
|
|
|
|
$tester = new ApplicationTester($application);
|
|
|
|
$tester->run([
|
|
|
|
'command' => 'require',
|
|
|
|
'packages' => [ 'testvendor/testpcakage 1.0.0' ],
|
|
|
|
'-d' => $this->working_directory,
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$this->assertNotEquals(0, $tester->getStatusCode());
|
|
|
|
$output = $tester->getDisplay();
|
|
|
|
|
|
|
|
$this->assertStringContainsString(
|
|
|
|
'Your requirements could not be resolved to an installable set of packages.',
|
|
|
|
$output
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->assertStringContainsString(
|
|
|
|
'requires testvendor/testpcakage, it could not be found in any version',
|
|
|
|
$output
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->assertStringContainsString(
|
|
|
|
'- A typo in the package name',
|
|
|
|
$output
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* testcase: UC01-005
|
|
|
|
*/
|
|
|
|
public function testInstallNoPackage(): void
|
|
|
|
{
|
|
|
|
// Arrange
|
|
|
|
$application = new Application();
|
|
|
|
$application->setAutoExit(false);
|
|
|
|
$application->add(new RequireCommand());
|
|
|
|
|
|
|
|
// Act
|
|
|
|
$tester = new ApplicationTester($application);
|
|
|
|
$tester->run([
|
|
|
|
'command' => 'require',
|
|
|
|
'packages' => [ '-' ],
|
|
|
|
'-d' => $this->working_directory,
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$this->assertNotEquals(0, $tester->getStatusCode());
|
|
|
|
$output = $tester->getDisplay();
|
|
|
|
|
|
|
|
$this->assertStringContainsString(
|
|
|
|
'Could not find package -.',
|
|
|
|
$output
|
|
|
|
);
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$manifest = json_decode(
|
|
|
|
file_get_contents($this->working_directory . '/composer.json'),
|
|
|
|
true
|
|
|
|
);
|
|
|
|
|
|
|
|
// Confirmation 2: dependency has not been added to composer.json
|
|
|
|
$this->assertEquals(0, count($manifest['require']));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* testcase: UC01-006
|
|
|
|
*/
|
|
|
|
public function testInstallLongPackageName(): void
|
|
|
|
{
|
|
|
|
// Arrange
|
|
|
|
$application = new Application();
|
|
|
|
$application->setAutoExit(false);
|
|
|
|
$application->add(new RequireCommand());
|
|
|
|
|
|
|
|
$package_name = $this->generateRandomString(8000);
|
|
|
|
|
|
|
|
// Act
|
|
|
|
$tester = new ApplicationTester($application);
|
|
|
|
$tester->run([
|
|
|
|
'command' => 'require',
|
|
|
|
'packages' => [ $package_name ],
|
|
|
|
'-d' => $this->working_directory,
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Assert
|
|
|
|
$this->assertNotEquals(0, $tester->getStatusCode());
|
|
|
|
$output = $tester->getDisplay();
|
|
|
|
|
|
|
|
$this->assertStringContainsString(
|
|
|
|
'Could not find a matching version of package ',
|
|
|
|
$output
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function generateRandomString(int $length): string {
|
|
|
|
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
|
|
$charactersLength = strlen($characters);
|
|
|
|
$randomString = '';
|
|
|
|
for ($i = 0; $i < $length; $i++) {
|
|
|
|
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
|
|
|
}
|
|
|
|
return $randomString;
|
|
|
|
}
|
|
|
|
}
|