Skip to content

Commit

Permalink
Heuristics to set memory limit for mutants running with PHPUnit.
Browse files Browse the repository at this point in the history
Since we know how much memory the initial test suite used,
and only if we know, we can enforce a memory limit upon all
mutation processes. Limit is set to be twice the known amount,
because if we know that a normal test suite used X megabytes,
if a mutants uses a lot more, this is a definite error.

Memory limit is introduced by altering a known temporary php.ini
to include a directive to enable the limit as the very last line.
  • Loading branch information
sanmai committed Mar 24, 2018
1 parent e35b5c0 commit 33ee1df
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/Command/InfectionCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Infection\Mutant\Exception\MsiCalculationException;
use Infection\Mutant\Generator\MutationsGenerator;
use Infection\Mutant\MetricsCalculator;
use Infection\Php\ConfigBuilder;
use Infection\Process\Builder\ProcessBuilder;
use Infection\Process\Listener\InitialTestsConsoleLoggerSubscriber;
use Infection\Process\Listener\MutantCreatingConsoleLoggerSubscriber;
Expand All @@ -31,6 +32,7 @@
use Infection\TestFramework\AbstractTestFrameworkAdapter;
use Infection\TestFramework\Coverage\CodeCoverageData;
use Infection\TestFramework\PhpSpec\PhpSpecExtraOptions;
use Infection\TestFramework\PhpUnit\Adapter\PhpUnitAdapter;
use Infection\TestFramework\PhpUnit\Coverage\CoverageXmlParser;
use Infection\TestFramework\PhpUnit\PhpUnitExtraOptions;
use Infection\TestFramework\TestFrameworkExtraOptions;
Expand Down Expand Up @@ -192,6 +194,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 1;
}

if ($adapter instanceof PhpUnitAdapter) {
$this->applyMemoryLimitFromPhpUnitProcess($initialTestSuitProcess, $adapter);
}

$codeCoverageData = $this->getCodeCoverageData($testFrameworkKey);
$mutationsGenerator = new MutationsGenerator(
$container->get('src.dirs'),
Expand Down Expand Up @@ -253,6 +259,38 @@ private function getOutputFormatter(): OutputFormatter
throw new \InvalidArgumentException('Incorrect formatter. Possible values: "dot", "progress"');
}

/**
* By default we let a mutant process use as much more memory as an initial test suite consumed.
*
* @var int
*/
const DEFAULT_MEMORY_LIMIT_MULTIPLIER = 2;

private function applyMemoryLimitFromPhpUnitProcess(Process $process, PhpUnitAdapter $adapter)
{
$memoryLimit = $adapter->getMemoryUsed($process->getOutput());

if ($memoryLimit < 0) {
// Cannot detect memory used, not setting any limits
return;
}

/*
* Since we know how much memory the initial test suite used,
* and only if we know, we can enforce a memory limit upon all
* mutation processes. Limit is set to be twice the known amount,
* because if we know that a normal test suite used X megabytes,
* if a mutants uses a lot more, this is a definite error.
*/
$memoryLimit *= self::DEFAULT_MEMORY_LIMIT_MULTIPLIER;

$tempConfigPath = (string) getenv(ConfigBuilder::ENV_TEMP_PHP_CONFIG_PATH);

if (!empty($tempConfigPath) && file_exists($tempConfigPath)) {
file_put_contents($tempConfigPath, PHP_EOL . sprintf('memory_limit = %dM', $memoryLimit), FILE_APPEND);
}
}

private function registerSubscribers(
MetricsCalculator $metricsCalculator,
AbstractTestFrameworkAdapter $testFrameworkAdapter
Expand Down

0 comments on commit 33ee1df

Please sign in to comment.