diff --git a/.appveyor.yml b/.appveyor.yml
index 34d3a703337e9..e333bbd37f5ec 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -54,7 +54,7 @@ test_script:
- SET X=0
- SET SYMFONY_PHPUNIT_SKIPPED_TESTS=phpunit.skipped
- copy /Y c:\php\php.ini-min c:\php\php.ini
- - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel!
+ - php phpunit src\Symfony --bootstrap vendor\autoload.php --exclude-group benchmark,intl-data || SET X=!errorlevel!
- copy /Y c:\php\php.ini-max c:\php\php.ini
- - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel!
+ - php phpunit src\Symfony --bootstrap vendor\autoload.php --exclude-group benchmark,intl-data || SET X=!errorlevel!
- exit %X%
diff --git a/.travis.yml b/.travis.yml
index 913f031fd20e0..00cb2cf4e53a2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -69,7 +69,7 @@ before_install:
[ -d ~/.composer ] || mkdir ~/.composer
cp .composer/* ~/.composer/
export PHPUNIT=$(readlink -f ./phpunit)
- export PHPUNIT_X="$PHPUNIT --exclude-group tty,benchmark,intl-data"
+ export PHPUNIT_X="$PHPUNIT --bootstrap vendor/autoload.php --exclude-group tty,benchmark,intl-data"
export COMPOSER_UP='composer update --no-progress --no-suggest --ansi'
export COMPONENTS=$(find src/Symfony -mindepth 2 -type f -name phpunit.xml.dist -printf '%h\n')
find ~/.phpenv -name xdebug.ini -delete
@@ -238,10 +238,10 @@ install:
echo "$COMPONENTS" | xargs -n1 -I{} tar --append -f ~/php-ext/composer-lowest.lock.tar {}/composer.lock
else
echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}"
- tfold src/Symfony/Component/Console.tty $PHPUNIT src/Symfony/Component/Console --group tty
+ tfold src/Symfony/Component/Console.tty $PHPUNIT src/Symfony/Component/Console --bootstrap vendor/autoload.php --group tty
if [[ $PHP = ${MIN_PHP%.*} ]]; then
export PHP=$MIN_PHP
- tfold src/Symfony/Component/Process.sigchild SYMFONY_DEPRECATIONS_HELPER=weak php-$MIN_PHP/sapi/cli/php ./phpunit --colors=always src/Symfony/Component/Process/
+ tfold src/Symfony/Component/Process.sigchild SYMFONY_DEPRECATIONS_HELPER=weak php-$MIN_PHP/sapi/cli/php ./phpunit --bootstrap vendor/autoload.php --colors=always src/Symfony/Component/Process/
fi
fi
}
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest.php b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest.php
new file mode 100644
index 0000000000000..5bd098a0d30ef
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest.php
@@ -0,0 +1,131 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\PhpUnit\Tests;
+
+use PHPUnit\Framework\TestCase;
+
+class SimplePhpUnitTest extends TestCase
+{
+ private static $testFiles = [
+ __DIR__.'/SimplePhpUnitTest/Modul1/phpunit.xml.dist',
+ __DIR__.'/SimplePhpUnitTest/Modul2/phpunit.xml.dist',
+ ];
+
+ private $currentCwd;
+
+ public static function setUpBeforeClass()
+ {
+ foreach (self::$testFiles as $testFile) {
+ $renamedFile = str_replace('.xml.dist', '.txml.dist', $testFile);
+
+ if (file_exists($renamedFile)) {
+ rename($renamedFile, $testFile);
+ }
+ }
+ }
+
+ public static function tearDownAfterClass()
+ {
+ foreach (self::$testFiles as $testFile) {
+ if (file_exists($testFile)) {
+ rename($testFile, str_replace('.xml.dist', '.txml.dist', $testFile));
+ }
+ }
+ }
+
+ protected function setUp()
+ {
+ $this->currentCwd = getcwd();
+ chdir(\dirname(__DIR__));
+ }
+
+ protected function tearDown()
+ {
+ chdir($this->currentCwd);
+ }
+
+ public function testInstall()
+ {
+ $cmd = 'bin/simple-phpunit install';
+ $this->execute($cmd, $output, $exitCode);
+ $this->assertSame(0, $exitCode);
+ }
+
+ public function testSimplePhpunitShortConfigurationFile()
+ {
+ $cmd = 'bin/simple-phpunit -c Tests/SimplePhpUnitTest/Modul1/phpunit.xml.dist';
+ $this->execute($cmd, $output);
+ $this->assertContains('OK (7 tests, 11 assertions)', implode(PHP_EOL, $output));
+ }
+
+ public function testSimplePhpunitWithConfigurationWithFilter()
+ {
+ $cmd = 'bin/simple-phpunit --filter=testEnv --configuration Tests/SimplePhpUnitTest/Modul1/phpunit.xml.dist';
+ $this->execute($cmd, $output);
+ $this->assertContains('OK (1 test, 1 assertion)', implode(PHP_EOL, $output));
+ }
+
+ public function testParallelTests()
+ {
+ $cmd = 'bin/simple-phpunit Tests/SimplePhpUnitTest';
+ $this->execute($cmd, $output);
+
+ // Check parallel test suites are runned successfully
+ $testSuites = explode('Test Suite', implode(PHP_EOL, $output));
+
+ unset($testSuites[0]); // Remove header output
+ $testSuites = array_values($testSuites);
+ $this->assertCount(2, $testSuites);
+
+ $this->assertContains('OK (7 tests, 11 assertions)', $testSuites[0]);
+ $this->assertContains('OK (7 tests, 11 assertions)', $testSuites[1]);
+
+ // Check different phpunit versions are installed
+ $this->assertFileExists(\dirname(__DIR__).'/.phpunit/phpunit-6.5-remove-symfony_yaml-phpspec_prophecy/phpunit');
+ $this->assertFileExists(\dirname(__DIR__).'/.phpunit/phpunit-7.4-remove-phpspec_prophecy-symfony_yaml/phpunit');
+ }
+
+ private function execute($command, &$output = null, &$return_var = null)
+ {
+ $oldPhpUnitRootDirectory = getenv('SYMFONY_PHPUNIT_ROOT_DIRECTORY');
+ $oldPhpUnitDirectory = getenv('SYMFONY_PHPUNIT_DIR');
+
+ // Use putenv vor windows compatible setting of environment variables
+ putenv('SYMFONY_PHPUNIT_ROOT_DIRECTORY='.\dirname(__DIR__));
+ putenv('SYMFONY_PHPUNIT_DIR='.\dirname(__DIR__).'/.phpunit');
+
+ $result = exec(
+ sprintf('php %s', $command),
+ $output,
+ $return_var
+ );
+
+ // Reset env variables
+ if (false !== $oldPhpUnitRootDirectory) {
+ // Set to old value
+ putenv('SYMFONY_PHPUNIT_ROOT_DIRECTORY='.$oldPhpUnitRootDirectory);
+ } else {
+ // Remove when no old value exists
+ putenv('SYMFONY_PHPUNIT_ROOT_DIRECTORY');
+ }
+
+ if (false !== $oldPhpUnitDirectory) {
+ // Set to old value
+ putenv('SYMFONY_PHPUNIT_DIR='.$oldPhpUnitDirectory);
+ } else {
+ // Remove when no old value exists
+ putenv('SYMFONY_PHPUNIT_DIR');
+ }
+
+ return $result;
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/phpunit.txml.dist b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/phpunit.txml.dist
new file mode 100644
index 0000000000000..f033948ab75fd
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/phpunit.txml.dist
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tests
+
+
+
+
+
+ .
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/tests/ModulTest.tphp b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/tests/ModulTest.tphp
new file mode 100644
index 0000000000000..ab4d9f0b423b0
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/tests/ModulTest.tphp
@@ -0,0 +1,53 @@
+assertSame('ENV_VAR_MODUL_1', getenv('ENV_VAR'));
+ }
+
+ public function testServer()
+ {
+ $this->assertSame('SERVER_VAR_MODUL_1', $_SERVER['SERVER_VAR']);
+ }
+
+ public function testIni()
+ {
+ $this->assertSame('7', ini_get('precision'));
+ }
+
+ public function testBootstrapEnv()
+ {
+ $this->assertSame('BOOTSTRAP_ENV_VAR_MODUL_1', getenv('BOOTSTRAP_ENV_VAR'));
+
+ sleep(1); // To Check if the output is streamed
+
+ $this->assertTrue(true);
+ }
+
+ public function testBootstrapServer()
+ {
+ $this->assertSame('BOOTSTRAP_SERVER_VAR_MODUL_1', $_SERVER['BOOTSTRAP_SERVER_VAR']);
+ }
+
+ public function testBootstrapIni()
+ {
+ $this->assertSame('15', ini_get('serialize_precision'));
+ }
+
+ public function testSymfonyEnvs()
+ {
+ $this->assertSame('disabled', getenv('SYMFONY_DEPRECATIONS_HELPER'));
+ $this->assertSame('symfony/yaml phpspec/prophecy', getenv('SYMFONY_PHPUNIT_REMOVE'));
+ $this->assertSame('6.5', getenv('SYMFONY_PHPUNIT_VERSION'));
+ exec((defined('PHP_BINARY') ? PHP_BINARY : 'php') . ' ' . $_SERVER['SCRIPT_NAME'] . ' --version', $output);
+ $this->assertContains('PHPUnit 6.5', $output[0]);
+
+ @trigger_error('Deprecation Error which should be ignored');
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/tests/bootstrap.php b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/tests/bootstrap.php
new file mode 100644
index 0000000000000..2c7e2631c9748
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul1/tests/bootstrap.php
@@ -0,0 +1,5 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tests
+
+
+
+
+
+ .
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul2/tests/ModulTest.tphp b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul2/tests/ModulTest.tphp
new file mode 100644
index 0000000000000..2479c608a4f75
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul2/tests/ModulTest.tphp
@@ -0,0 +1,53 @@
+assertSame('ENV_VAR_MODUL_2', getenv('ENV_VAR'));
+ }
+
+ public function testServer()
+ {
+ $this->assertSame('SERVER_VAR_MODUL_2', $_SERVER['SERVER_VAR']);
+ }
+
+ public function testIni()
+ {
+ $this->assertSame('9', ini_get('precision'));
+ }
+
+ public function testBootstrapEnv()
+ {
+ $this->assertSame('BOOTSTRAP_ENV_VAR_MODUL_2', getenv('BOOTSTRAP_ENV_VAR'));
+
+ sleep(1); // To Check if the output is streamed
+
+ $this->assertTrue(true);
+ }
+
+ public function testBootstrapServer()
+ {
+ $this->assertSame('BOOTSTRAP_SERVER_VAR_MODUL_2', $_SERVER['BOOTSTRAP_SERVER_VAR']);
+ }
+
+ public function testBootstrapIni()
+ {
+ $this->assertSame('11', ini_get('serialize_precision'));
+ }
+
+ public function testSymfonyDeprecationHelper()
+ {
+ $this->assertSame('weak', getenv('SYMFONY_DEPRECATIONS_HELPER'));
+ $this->assertSame('phpspec/prophecy symfony/yaml', getenv('SYMFONY_PHPUNIT_REMOVE'));
+ $this->assertSame('7.4', getenv('SYMFONY_PHPUNIT_VERSION'));
+ exec((defined('PHP_BINARY') ? PHP_BINARY : 'php') . ' ' . $_SERVER['SCRIPT_NAME'] . ' --version', $output);
+ $this->assertContains('PHPUnit 7.4', $output[0]);
+
+ @trigger_error('Deprecation Error which should be ignored');
+ }
+}
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul2/tests/bootstrap.php b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul2/tests/bootstrap.php
new file mode 100644
index 0000000000000..703630903f2bd
--- /dev/null
+++ b/src/Symfony/Bridge/PhpUnit/Tests/SimplePhpUnitTest/Modul2/tests/bootstrap.php
@@ -0,0 +1,5 @@
+load($phpunitConfigFilename);
- } else {
- $phpunitConfig = false;
- }
- }
- if (false !== $phpunitConfig) {
- $var = new DOMXpath($phpunitConfig);
+/**
+ * Read environment variable from system or given phpunit config file.
+ *
+ * @param string $phpUnitConfigFile
+ * @param string $name
+ * @param bool|string $default
+ *
+ * @return bool|string
+ */
+$getEnvVar = function ($phpUnitConfigFile, $name, $default = false)
+{
+ $value = getenv($name);
+
+ if (file_exists($phpUnitConfigFile)) {
+ // Load phpunit config files and search for the env variable
+ $phpUnitConfig = new DomDocument();
+ $phpUnitConfig->load($phpUnitConfigFile);
+
+ $var = new DOMXpath($phpUnitConfig);
foreach ($var->query('//php/env[@name="'.$name.'"]') as $var) {
- return $var->getAttribute('value');
+ $currentValue = $var->getAttribute('value');
+
+ if ('true' === $var->getAttribute('force')) {
+ return $currentValue;
+ } elseif (false === $value) {
+ return $currentValue;
+ }
}
}
+ if (false !== $value) {
+ return $value;
+ }
+
return $default;
};
-if (PHP_VERSION_ID >= 70100) {
- // PHPUnit 7 requires PHP 7.1+
- $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '7.4');
-} elseif (PHP_VERSION_ID >= 70000) {
- // PHPUnit 6 requires PHP 7.0+
- $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '6.5');
-} elseif (PHP_VERSION_ID >= 50600) {
- // PHPUnit 5 requires PHP 5.6+
- $PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '5.7');
-} else {
- $PHPUNIT_VERSION = '4.8';
-}
+/**
+ * Get the phpunit binary if not exist download phpunit install it with given configuration.
+ *
+ * @param string $PHP
+ * @param callable $getEnvVar
+ * @param string $phpUnitVersion
+ * @param string|null $phpUnitConfigFile
+ *
+ * @return string
+ */
+$getPHPUnit = function ($PHP, $getEnvVar, $phpUnitVersion, $phpUnitConfigFile = null)
+{
+ // Get project root directory where composer.json exists
+ static $root;
+
+ if (!$root) {
+ $root = getenv('SYMFONY_PHPUNIT_ROOT_DIRECTORY');
+
+ $COMPOSER_JSON = getenv('COMPOSER') ?: 'composer.json';
+
+ if (!$root) {
+ // Go the folders up until find a composer.json file
+ $root = __DIR__;
+ while (!file_exists($root.'/'.$COMPOSER_JSON) || file_exists($root.'/DeprecationErrorHandler.php')) {
+ if ($root === dirname($root)) {
+ break;
+ }
+ $root = dirname($root);
+ }
+ }
+ }
-$COMPOSER_JSON = getenv('COMPOSER') ?: 'composer.json';
+ // Get directory where the phpunit versions get installed
+ $PHPUNIT_DIR = $getEnvVar($phpUnitConfigFile, 'SYMFONY_PHPUNIT_DIR', $root.'/vendor/bin/.phpunit');
-$root = __DIR__;
-while (!file_exists($root.'/'.$COMPOSER_JSON) || file_exists($root.'/DeprecationErrorHandler.php')) {
- if ($root === dirname($root)) {
- break;
- }
- $root = dirname($root);
-}
+ $phpUnit = $PHPUNIT_DIR . '/phpunit-' . $phpUnitVersion;
-$oldPwd = getcwd();
-$PHPUNIT_DIR = $getEnvVar('SYMFONY_PHPUNIT_DIR', $root.'/vendor/bin/.phpunit');
-$PHP = defined('PHP_BINARY') ? PHP_BINARY : 'php';
-$PHP = escapeshellarg($PHP);
-if ('phpdbg' === PHP_SAPI) {
- $PHP .= ' -qrr';
-}
+ // make own phpunit version when dependencies are removed
+ $SYMFONY_PHPUNIT_REMOVE = $getEnvVar($phpUnitConfigFile, 'SYMFONY_PHPUNIT_REMOVE', '');
+
+ if ($SYMFONY_PHPUNIT_REMOVE) {
+ $phpUnit .= '-remove-' . str_replace(array('/', ' '), array('_', '-'), $SYMFONY_PHPUNIT_REMOVE);
+ }
-$defaultEnvs = array(
- 'COMPOSER' => 'composer.json',
- 'COMPOSER_VENDOR_DIR' => 'vendor',
- 'COMPOSER_BIN_DIR' => 'bin',
-);
+ $phpUnit .= '/phpunit';
-foreach ($defaultEnvs as $envName => $envValue) {
- if ($envValue !== getenv($envName)) {
- putenv("$envName=$envValue");
- $_SERVER[$envName] = $_ENV[$envName] = $envValue;
+ // If phpunit was installed before return path to binary.
+ if (file_exists($phpUnit)) {
+ return $phpUnit;
}
-}
-$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`))
- ? $PHP.' '.escapeshellarg($COMPOSER)
- : 'composer';
+ // Build a standalone phpunit without symfony/yaml nor prophecy by default
+ $oldPwd = getcwd();
+ // Override COMPOSER_VENDOR_DIR and COMPOSER_BIN_DIR with their default values in PHPUnit Bridge
+ $defaultEnvs = array(
+ 'COMPOSER' => 'composer.json',
+ 'COMPOSER_VENDOR_DIR' => 'vendor',
+ 'COMPOSER_BIN_DIR' => 'bin',
+ );
-$SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy symfony/yaml');
+ foreach ($defaultEnvs as $envName => $envValue) {
+ if ($envValue !== getenv($envName)) {
+ putenv("$envName=$envValue");
+ $_SERVER[$envName] = $_ENV[$envName] = $envValue;
+ }
+ }
-if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__FILE__)."\n".$SYMFONY_PHPUNIT_REMOVE !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION.md5")) {
- // Build a standalone phpunit without symfony/yaml nor prophecy by default
+ // Get composer binary for phpunit installation
+ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`))
+ ? $PHP.' '.escapeshellarg($COMPOSER)
+ : 'composer';
@mkdir($PHPUNIT_DIR, 0777, true);
chdir($PHPUNIT_DIR);
- if (file_exists("phpunit-$PHPUNIT_VERSION")) {
- passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s > NUL': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION.old"));
- rename("phpunit-$PHPUNIT_VERSION", "phpunit-$PHPUNIT_VERSION.old");
- passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION.old"));
+
+ $phpUnitDirectory = basename(dirname($phpUnit));
+ $extractDirectory = getcwd() . '/extract-' . $phpUnitDirectory;
+
+ if (file_exists($extractDirectory)) {
+ passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s > NUL': 'rm -rf %s', "$extractDirectory.old"));
+ rename($extractDirectory, "$extractDirectory.old");
+ passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? 'rmdir /S /Q %s': 'rm -rf %s', "$extractDirectory.old"));
}
- passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit phpunit-$PHPUNIT_VERSION \"$PHPUNIT_VERSION.*\"");
- chdir("phpunit-$PHPUNIT_VERSION");
+
+ passthru("$COMPOSER create-project --no-install --prefer-dist --no-scripts --no-plugins --no-progress --ansi phpunit/phpunit $extractDirectory \"$phpUnitVersion.*\"");
+ chdir($extractDirectory);
+
+ // Remove dependencies like symfony/yaml and prophecy
if ($SYMFONY_PHPUNIT_REMOVE) {
passthru("$COMPOSER remove --no-update ".$SYMFONY_PHPUNIT_REMOVE);
}
- if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) {
+ if (5.1 <= $phpUnitVersion && $phpUnitVersion < 5.4) {
passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\"");
}
if (file_exists($path = $root.'/vendor/symfony/phpunit-bridge')) {
@@ -124,7 +161,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__
passthru("$COMPOSER require --no-update symfony/phpunit-bridge \"*\"");
}
$prevRoot = getenv('COMPOSER_ROOT_VERSION');
- putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99");
+ putenv("COMPOSER_ROOT_VERSION=$phpUnitVersion.99");
// --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS
$exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true)));
putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : ''));
@@ -152,69 +189,187 @@ Symfony\Bridge\PhpUnit\TextUI\Command::main();
EOPHP
);
- chdir('..');
- file_put_contents(".$PHPUNIT_VERSION.md5", md5_file(__FILE__)."\n".$SYMFONY_PHPUNIT_REMOVE);
+
+ // After finishing dependency install move directory to correct place
+ rename($extractDirectory, $PHPUNIT_DIR . '/' . $phpUnitDirectory);
+
chdir($oldPwd);
-}
+ return $phpUnit;
+};
-global $argv, $argc;
-$argv = isset($_SERVER['argv']) ? $_SERVER['argv'] : array();
-$argc = isset($_SERVER['argc']) ? $_SERVER['argc'] : 0;
-$components = array();
-$cmd = array_map('escapeshellarg', $argv);
-$exit = 0;
+/**
+ * Get the phpunit version from SYMFONY_PHPUNIT_VERSION env variable or the given phpunit config file.
+ *
+ * @param callable $getEnvVar
+ * @param string|null $phpUnitConfigFile
+ *
+ * @return mixed|string
+ */
+$getPHPUnitVersion = function ($getEnvVar, $phpUnitConfigFile = null)
+{
+ if (PHP_VERSION_ID >= 70100) {
+ // PHPUnit 7 is required for PHP 7.1+
+ $phpUnitVersion = $getEnvVar($phpUnitConfigFile, 'SYMFONY_PHPUNIT_VERSION', '7.4');
+ } elseif (PHP_VERSION_ID >= 70000) {
+ // PHPUnit 6 does not support PHP 7.0
+ $phpUnitVersion = $getEnvVar($phpUnitConfigFile, 'SYMFONY_PHPUNIT_VERSION', '6.5');
+ } elseif (PHP_VERSION_ID >= 50600) {
+ // PHPUnit 5 requires PHP 5.6+
+ $phpUnitVersion = $getEnvVar($phpUnitConfigFile, 'SYMFONY_PHPUNIT_VERSION', '5.7');
+ } else {
+ $phpUnitVersion = '4.8';
+ }
-if (isset($argv[1]) && 'symfony' === $argv[1] && !file_exists('symfony') && file_exists('src/Symfony')) {
- $argv[1] = 'src/Symfony';
-}
-if (isset($argv[1]) && is_dir($argv[1]) && !file_exists($argv[1].'/phpunit.xml.dist')) {
- // Find Symfony components in plain PHP for Windows portability
+ return $phpUnitVersion;
+};
- $finder = new RecursiveDirectoryIterator($argv[1], FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::UNIX_PATHS);
- $finder = new RecursiveIteratorIterator($finder);
- $finder->setMaxDepth(getenv('SYMFONY_PHPUNIT_MAX_DEPTH') ?: 3);
+/**
+ * Find all phpunit config files by given arguments.
+ *
+ * bin/simple-phpunit -> return root phpunit config file
+ * bin/simple-phpunit -c path/to/phpunit.xml.dist -> return given phpunit file
+ * bin/simple-phpunit path/to/folder -> return all phpunit config files in given folder
+ *
+ * @param array $argv
+ *
+ * @return array
+ */
+$loadPHPUnitConfigFiles = function (&$argv) {
+ $outputError = function($text, $exitCode = 1)
+ {
+ echo "\033[41m" . $text . "\033[0m" . PHP_EOL;
- foreach ($finder as $file => $fileInfo) {
- if ('phpunit.xml.dist' === $file) {
- $components[] = dirname($fileInfo->getPathname());
+ exit($exitCode);
+ };
+
+ $phpUnitConfigFiles = array();
+
+ // Use configuration file current folder when no arguments given
+ if (!isset($argv[1])) {
+ if (file_exists('phpunit.xml')) {
+ $phpUnitConfigFiles[] = realpath('phpunit.xml');
+ } elseif (file_exists('phpunit.xml.dist')) {
+ $phpUnitConfigFiles[] = realpath('phpunit.xml.dist');
+ } else {
+ $outputError('No phpunit.xml.dist file found!');
}
+
+ return $phpUnitConfigFiles;
}
- if ($components) {
- array_shift($cmd);
+
+ // Use config file when given it over -c or --configuration argument
+ if (($configArgumentNr = array_search('-c', $argv))
+ || ($configArgumentNr = array_search('--configuration', $argv)))
+ {
+ ++$configArgumentNr;
+
+ if (!isset($argv[$configArgumentNr])) {
+ $outputError('Please provide a configuration file when using "-c" argument!');
+
+ exit(1);
+ }
+
+ $phpUnitConfigFiles[] = realpath($argv[$configArgumentNr]);
+
+ // Following arguments are given manually to the phpunit process
+ unset($argv[$configArgumentNr]);
+ unset($argv[$configArgumentNr - 1]);
+
+ return $phpUnitConfigFiles;
}
-}
-$cmd[0] = sprintf('%s %s --colors=always', $PHP, escapeshellarg("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit"));
-$cmd = str_replace('%', '%%', implode(' ', $cmd)).' %1$s';
+ // If symfony if given set the folder to src/Symfony
+ if (isset($argv[1]) && 'symfony' === $argv[1] && !file_exists('symfony') && file_exists('src/Symfony')) {
+ $argv[1] = 'src/Symfony';
+ }
-if ('\\' === DIRECTORY_SEPARATOR) {
- $cmd = 'cmd /v:on /d /c "('.$cmd.')%2$s"';
-} else {
- $cmd .= '%2$s';
-}
+ // Find all config file when folder given
+ if (is_dir($argv[1])) {
+ $finder = new RecursiveDirectoryIterator($argv[1], FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::UNIX_PATHS);
+ $finder = new RecursiveIteratorIterator($finder);
+ $finder->setMaxDepth(getenv('SYMFONY_PHPUNIT_MAX_DEPTH') ?: 3);
+
+ foreach ($finder as $file => $fileInfo) {
+ // Prefer phpunit.xml over phpunit.xml.dist file
+ $component = dirname($fileInfo->getPathname());
+ if ('phpunit.xml.dist' === $file && !isset($phpUnitConfigFiles[$component])) {
+ $phpUnitConfigFiles[$component] = realpath($fileInfo->getPathname());
+ } elseif ('phpunit.xml' === $file) {
+ $phpUnitConfigFiles[$component] = realpath($fileInfo->getPathname());
+ }
+ }
-if ($components) {
- $skippedTests = isset($_SERVER['SYMFONY_PHPUNIT_SKIPPED_TESTS']) ? $_SERVER['SYMFONY_PHPUNIT_SKIPPED_TESTS'] : false;
- $runningProcs = array();
+ ksort($phpUnitConfigFiles);
- foreach ($components as $component) {
- // Run phpunit tests in parallel
+ array_values($phpUnitConfigFiles);
- if ($skippedTests) {
- putenv("SYMFONY_PHPUNIT_SKIPPED_TESTS=$component/$skippedTests");
+ if (0 === count($phpUnitConfigFiles)) {
+ $outputError('No configuration files found in: ' . getcwd() . $argv[1]);
}
- $c = escapeshellarg($component);
+ unset($argv[1]); // $argv[1] should not provided to phpunit process
+ } elseif(file_exists($argv[1])) {
+ $phpUnitConfigFiles[] = $argv[1];
+
+ unset($argv[1]); // $argv[1] should not provided to phpunit process
+ }
+
+ return $phpUnitConfigFiles;
+};
+
+// ------------------------------------------------------------------ //
+// Helper Functions End //
+// ------------------------------------------------------------------ //
+
+$argv = isset($_SERVER['argv']) ? $_SERVER['argv'] : array();
+$argc = isset($_SERVER['argc']) ? $_SERVER['argc'] : 0;
+$PHP = defined('PHP_BINARY') ? PHP_BINARY : 'php';
+
+$phpUnitConfigFiles = $loadPHPUnitConfigFiles($argv);
- if ($proc = proc_open(sprintf($cmd, $c, " > $c/phpunit.stdout 2> $c/phpunit.stderr"), array(), $pipes)) {
+$runningProcs = array();
+$exit = 0;
+
+if (!isset($argv[1]) || 'install' !== $argv[1]) {
+ array_splice($argv, 1, 0, array('--colors=always'));
+}
+
+$phpUnitVersion = $getPHPUnitVersion($getEnvVar);
+$phpUnitConfigFile = null;
+
+if (1 === count($phpUnitConfigFiles)) {
+ // When only one phpunit config file run it directly in current process for streamed output
+ $phpUnitConfigFile = reset($phpUnitConfigFiles);
+ $phpUnitVersion = $getPHPUnitVersion($getEnvVar, $phpUnitConfigFile);
+ $argv[] = '-c';
+ $argv[] = $phpUnitConfigFile;
+} else {
+ foreach ($phpUnitConfigFiles as $phpUnitConfigFile) {
+ $phpUnitVersion = $getPHPUnitVersion($getEnvVar, $phpUnitConfigFile);
+ $phpUnit = $getPHPUnit($PHP, $getEnvVar, $phpUnitVersion, $phpUnitConfigFile);
+ $component = dirname($phpUnitConfigFile);
+
+ $cmd = sprintf('%s %s -c %s %s > %s/phpunit.stdout 2> %s/phpunit.stderr',
+ escapeshellcmd($PHP),
+ escapeshellcmd($phpUnit),
+ escapeshellarg($phpUnitConfigFile),
+ implode(' ', array_map('escapeshellarg', array_slice($argv, 1))),
+ escapeshellarg($component),
+ escapeshellarg($component)
+ );
+
+ if ($proc = proc_open($cmd, array(), $pipes)) {
$runningProcs[$component] = $proc;
} else {
$exit = 1;
echo "\033[41mKO\033[0m $component\n\n";
}
}
+}
+if (count($runningProcs)) {
+ // Wait for the processes to be finished and output there result
while ($runningProcs) {
usleep(300000);
$terminatedProcs = array();
@@ -228,7 +383,7 @@ if ($components) {
}
foreach ($terminatedProcs as $component => $procStatus) {
- foreach (array('out', 'err') as $file) {
+ foreach (['out', 'err'] as $file) {
$file = "$component/phpunit.std$file";
readfile($file);
unlink($file);
@@ -246,14 +401,20 @@ if ($components) {
}
}
}
-} elseif (!isset($argv[1]) || 'install' !== $argv[1] || file_exists('install')) {
+} elseif (isset($argv[1]) && 'install' === $argv[1] || file_exists('install')) {
+ // If not yet installed install phpunit
+ if (0 === count($phpUnitConfigFiles)) {
+ $getPHPUnit($PHP, $getEnvVar, $phpUnitVersion, $phpUnitConfigFile);
+ }
+} else {
+ // If only one configuration file is found call phpunit directly
if (!class_exists('SymfonyBlacklistSimplePhpunit', false)) {
class SymfonyBlacklistSimplePhpunit {}
}
- array_splice($argv, 1, 0, array('--colors=always'));
+
$_SERVER['argv'] = $argv;
$_SERVER['argc'] = ++$argc;
- include "$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit";
+ include $getPHPUnit($PHP, $getEnvVar, $phpUnitVersion, $phpUnitConfigFile);
}
exit($exit);