Legoktm has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/405573 )

Change subject: [WIP] Run tests in parallel
......................................................................

[WIP] Run tests in parallel

Change-Id: I48d787e3f84bd543c5d21b98a9ae74454bad19e1
---
M composer.json
M src/CheckCommand.php
2 files changed, 80 insertions(+), 19 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/tools/phpunit-patch-coverage 
refs/changes/73/405573/1

diff --git a/composer.json b/composer.json
index b7d7f39..e2cb101 100644
--- a/composer.json
+++ b/composer.json
@@ -12,8 +12,10 @@
   ],
   "require": {
     "php": ">=5.5.9",
+    "jagandecapri/symfony-parallel-process": "^2.0",
     "legoktm/clover-diff": "^1.0.0",
     "nikic/php-parser": "^3.1.3",
+    "phpunit/php-code-coverage": "^2.2.4",
     "symfony/console": "^3.3",
     "symfony/finder": "^3.3",
     "symfony/process": "^3.3",
diff --git a/src/CheckCommand.php b/src/CheckCommand.php
index 587f2e7..e976615 100644
--- a/src/CheckCommand.php
+++ b/src/CheckCommand.php
@@ -18,8 +18,11 @@
 
 namespace MediaWiki\Tool\PatchCoverage;
 
+use Jack\Symfony\ProcessManager;
 use Legoktm\CloverDiff\Differ;
 use Legoktm\CloverDiff\DiffPrinter;
+use PHP_CodeCoverage;
+use PHP_CodeCoverage_Report_Clover;
 use Symfony\Component\Console\Command\Command;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Input\InputOption;
@@ -57,6 +60,11 @@
                                null, InputOption::VALUE_REQUIRED,
                                'Command to run to execute PHPUnit tests',
                                'php vendor/bin/phpunit'
+                       )->addOption(
+                               'parallel',
+                               null, InputOption::VALUE_REQUIRED,
+                               'Number of processes to use',
+                               '1'
                        );
        }
 
@@ -69,38 +77,81 @@
                return $newPaths;
        }
 
-       private function getFilterRegex( $tests ) {
+       private function getFilterRegexes( $tests ) {
                // PHPUnit requires filename to be the same as the classname,
                // so we can use that as a shortcut.
                $filter = [];
                foreach ( $tests as $test ) {
                        $base = basename( $test );
                        // Strip extension
-                       $filter[] = preg_quote(
+                       $filter[] = '\'/' . preg_quote(
                                substr( $base, 0, strlen( $base ) - 4 )
+                               . '/\''
                        );
                }
 
-               return '\'/' . implode( '|', $filter ) . '/\'';
+               return $filter;
        }
 
-       private function runTests( $output, $command, $tests ) {
-               // TODO: Run this in parallel?
-               $clover = tempnam( sys_get_temp_dir(), 'clover' );
-               $cmd = $command .
-                       " --coverage-clover $clover --filter " .
-                       $this->getFilterRegex( $tests );
-               $process = new CommandProcess( $cmd );
-               // Disable timeout
-               $process->setTimeout( null );
-               // Run and buffer output for progress
-               $process->runWithOutput( $output );
-
+       private function getTempFile() {
+               $fname = tempnam( sys_get_temp_dir(), 'phpcover' );
                $this->scopedCallbacks[] = new ScopedCallback(
-                       function () use ( $clover ) {
-                               unlink( $clover );
+                       function () use ( $fname ) {
+                               // unlink( $fname );
                        }
                );
+
+               return $fname;
+       }
+
+       /**
+        * @param int $parallel
+        * @param OutputInterface $output
+        * @param $command
+        * @param $tests
+        *
+        * @return string
+        */
+       private function runTests( $parallel, $output, $command, $tests ) {
+               // TODO: Run this in parallel?
+
+               $regexes = $this->getFilterRegexes( $tests );
+               $toMerge = [];
+               $toRun = [];
+               foreach ( $regexes as $regex ) {
+                       $tmp = $this->getTempFile();
+                       $cmd = $command . " --coverage-php $tmp --filter " .
+                               $regex;
+                       $process = new Process( $cmd );
+                       $output->writeln( $cmd );
+                       $process->setTimeout( null );
+                       $toRun[] = $process;
+                       $toMerge[] = $tmp;
+               }
+
+               $manager = new ProcessManager();
+               $manager->runParallel( $toRun, $parallel );
+
+               /** @var PHP_CodeCoverage $coverage */
+               $coverage = null;
+               foreach ( $toMerge as $merge ) {
+                       if ( $coverage ) {
+                               $coverage->merge( include $merge );
+                       } else {
+                               $coverage = include $merge;
+                               if ( !$coverage instanceof PHP_CodeCoverage ) {
+                                       throw new \Exception();
+                               }
+                       }
+               }
+               $clover = $this->getTempFile();
+               if ( $coverage ) {
+                       $writer = new PHP_CodeCoverage_Report_Clover();
+                       $writer->process( $coverage, $clover );
+                       $output->writeln( $clover );
+               } else {
+                       $clover = null;
+               }
 
                return $clover;
        }
@@ -150,10 +201,16 @@
 
                // TODO: We need to trim suite.xml coverage filter, because 
that takes forever
 
+               $parallel = (int)$input->getOption( 'parallel' );
+               if ( $parallel < 1 ) {
+                       $parallel = 1;
+               }
                $command = $input->getOption( 'command' );
                if ( $testsToRun ) {
                        // Run it!
-                       $newClover = $this->runTests( $output, $command, 
$testsToRun );
+                       $newClover = $this->runTests(
+                               $parallel, $output, $command, $testsToRun
+                       );
                } else {
                        $newClover = null;
                }
@@ -172,7 +229,9 @@
                        $this->absolutify( $changedTests->deleted )
                ) );
                if ( $testsOldToRun ) {
-                       $oldClover = $this->runTests( $output, $command, 
$testsOldToRun );
+                       $oldClover = $this->runTests(
+                               $parallel, $output, $command, $testsOldToRun
+                       );
                } else {
                        $oldClover = null;
                }

-- 
To view, visit https://gerrit.wikimedia.org/r/405573
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I48d787e3f84bd543c5d21b98a9ae74454bad19e1
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/tools/phpunit-patch-coverage
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to