Skip to content

Commit

Permalink
Allow running custom mutators on Playground
Browse files Browse the repository at this point in the history
  • Loading branch information
maks-rafalko committed Jun 1, 2024
1 parent b88e85d commit ddc36c3
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
Binary file modified app/infection-builds/infection.phar
Binary file not shown.
56 changes: 55 additions & 1 deletion app/src/Infection/ConfigBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
use function json_decode;
use function json_encode;
use const JSON_THROW_ON_ERROR;
use function sprintf;
use function str_starts_with;
use function strlen;
use function substr;

/**
* This class assumes that json was already validated by Infection's JSON schema.
Expand All @@ -56,10 +60,60 @@ final class ConfigBuilder

private const TIMEOUT = 3;

private const NAMESPACE = 'Infected';

public function build(string $userProvidedConfig): string
{
$basicConfig = self::NOT_OVERRIDABLE_KEYS;
/** @var array{mutators?: array<string, bool>} $decodedOriginalConfig */
$decodedOriginalConfig = json_decode($userProvidedConfig, true, JSON_THROW_ON_ERROR);

return (string) json_encode(self::NOT_OVERRIDABLE_KEYS + $decodedOriginalConfig);
if ($this->containsCustomMutator($decodedOriginalConfig['mutators'] ?? [])) {
$basicConfig['source']['excludes'] = $this->findCustomMutators($decodedOriginalConfig['mutators'] ?? []);
}

return (string) json_encode($basicConfig + $decodedOriginalConfig);
}

/**
* @param array<string, bool> $mutators
*/
private function containsCustomMutator(array $mutators): bool
{
foreach ($mutators as $mutatorName => $mutatorConfig) {
if ($this->isCustomMutatorName($mutatorName)) {
return true;
}
}

return false;
}

/**
* @param array<string, bool> $mutators
*
* @return list<string>
*/
private function findCustomMutators(array $mutators): array
{
$customMutatorNames = [];

foreach ($mutators as $mutatorName => $mutatorConfig) {
if ($this->isCustomMutatorName($mutatorName)) {
$customMutatorNames[] = substr($mutatorName, strlen($this->getStaticNamespace()));
}
}

return $customMutatorNames;
}

private function getStaticNamespace(): string
{
return sprintf('%s\\', self::NAMESPACE);
}

private function isCustomMutatorName(string $mutatorName): bool
{
return str_starts_with($mutatorName, $this->getStaticNamespace());
}
}
2 changes: 1 addition & 1 deletion app/src/Infection/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

class Runner
{
public const CURRENT_INFECTION_VERSION = '0.27.10';
public const CURRENT_INFECTION_VERSION = '0.29.1';
public const CURRENT_PHPUNIT_VERSION = '10.5.10';
public const CURRENT_PHP_VERSION = '8.2.13';

Expand Down
3 changes: 3 additions & 0 deletions app/src/Json/infection-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"mutators": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[\\w]+(?:\\\\[\\w]+){1,}$": { "$ref": "#/definitions/default-mutator-config" }
},
"description": "Contains the settings for different mutations and profiles",
"properties": {
"global-ignore": {
Expand Down
28 changes: 28 additions & 0 deletions app/tests/Unit/Infection/ConfigBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,33 @@ public static function provideConfigs(): Generator
]
),
];

yield 'Custom mutators are automatically exluded from mutation' => [
<<<'JSON'
{
"mutators": {"@default": false, "Infected\\CustomMutator1": true, "Infected\\CustomMutator2": true}
}
JSON
,
[
'bootstrap' => './autoload.php',
'timeout' => 3,
'source' => [
'directories' => ['src'],
'excludes' => [
'CustomMutator1',
'CustomMutator2',
],
],
'phpUnit' => ['customPath' => '../phpunit.phar'],
'tmpDir' => '.',
'logs' => ['json' => 'infection.log.json'],
'mutators' => [
'@default' => false,
'Infected\\CustomMutator1' => true,
'Infected\\CustomMutator2' => true,
],
],
];
}
}

0 comments on commit ddc36c3

Please sign in to comment.