Running phpdbg -qrr ./vendor/bin/roave-infection-static-analysis-plugin
____ ____ __ _
/ _/___ / __/__ _____/ /_(_)___ ____
/ // __ \/ /_/ _ \/ ___/ __/ / __ \/ __ \
_/ // / / / __/ __/ /__/ /_/ / /_/ / / / /
/___/_/ /_/_/ \___/\___/\__/_/\____/_/ /_/
#StandWithUkraine
Infection - PHP Mutation Testing Framework version 0.26.14
Notice: You are running Infection with phpdbg enabled.
Running initial test suite...
PHPUnit version: 9.5.25
.: killed, M: escaped, U: uncovered, E: fatal error, X: syntax error, T: timed out, S: skipped, I: ignored
Generate mutants...
Processing source code files: 0
.....................................U....UUU..... ( 50)
.UUUU............................................. ( 100)
.................................................. ( 150)
.................................................. ( 200)
.................................................. ( 250)
............................UUUUUU................ ( 300)
......................E...........UUUUUUU......... ( 350)
.............................................UU... ( 400)
.UU.....
408 mutations were generated:
382 mutants were killed
0 mutants were configured to be ignored
25 mutants were not covered by tests
0 covered mutants were not detected
1 errors were encountered
0 syntax errors were encountered
0 time outs were encountered
0 mutants required more time than configured
Metrics:
Mutation Score Indicator (MSI): 93%
Mutation Code Coverage: 93%
Covered Code MSI: 100%
Note: to see escaped mutants run Infection with "--show-mutations" or configure file loggers.
Please note that some mutants will inevitably be harmless (i.e. false positives).
Escaped mutants:
================
Timed Out mutants:
==================
Skipped mutants:
================
Not Covered mutants:
====================
1) /github/workspace/src/Changes.php:58 [M] Foreach_
--- Original
+++ New
@@ @@
$instance = new self([]);
$instance->bufferedChanges = [];
$instance->unBufferedChanges = (function () use($other) : Generator {
- foreach ($this as $change) {
+ foreach (array() as $change) {
(yield $change);
}
foreach ($other as $change) {
2) /github/workspace/src/Changes.php:62 [M] Foreach_
--- Original
+++ New
@@ @@
foreach ($this as $change) {
(yield $change);
}
- foreach ($other as $change) {
+ foreach (array() as $change) {
(yield $change);
}
})();
3) /github/workspace/src/CompareClasses.php:35 [M] LogicalOr
--- Original
+++ New
@@ @@
public function __invoke(Reflector $definedSymbols, Reflector $pastSourcesWithDependencies, Reflector $newSourcesWithDependencies) : Changes
{
$definedApiClassNames = Dict\map(Dict\filter($definedSymbols->reflectAllClasses(), function (ReflectionClass $class) : bool {
- return !($class->isAnonymous() || $this->isInternalDocComment($class->getDocComment()));
+ return !($class->isAnonymous() && $this->isInternalDocComment($class->getDocComment()));
}), static function (ReflectionClass $class) : string {
return $class->getName();
});
4) /github/workspace/src/CompareClasses.php:35 [M] LogicalNot
--- Original
+++ New
@@ @@
public function __invoke(Reflector $definedSymbols, Reflector $pastSourcesWithDependencies, Reflector $newSourcesWithDependencies) : Changes
{
$definedApiClassNames = Dict\map(Dict\filter($definedSymbols->reflectAllClasses(), function (ReflectionClass $class) : bool {
- return !($class->isAnonymous() || $this->isInternalDocComment($class->getDocComment()));
+ return $class->isAnonymous() || $this->isInternalDocComment($class->getDocComment());
}), static function (ReflectionClass $class) : string {
return $class->getName();
});
5) /github/workspace/src/DetectChanges/BCBreak/ClassBased/ConstantRemoved.php:35 [M] LogicalOr
--- Original
+++ New
@@ @@
private function accessibleConstants(ReflectionClass $class) : array
{
return Dict\filter($class->getConstants(), static function (ReflectionClassConstant $constant) : bool {
- return $constant->isPublic() || $constant->isProtected();
+ return $constant->isPublic() && $constant->isProtected();
});
}
}
6) /github/workspace/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php:48 [M] LogicalOr
--- Original
+++ New
@@ @@
private function accessibleMethods(ReflectionClass $class) : array
{
$methods = Vec\filter($class->getMethods(), function (ReflectionMethod $method) : bool {
- return ($method->isPublic() || $method->isProtected()) && !$this->isInternalDocComment($method->getDocComment());
+ return $method->isPublic() && $method->isProtected() && !$this->isInternalDocComment($method->getDocComment());
});
return Dict\associate(Vec\map($methods, static function (ReflectionMethod $method) : string {
return $method->getName();
7) /github/workspace/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php:48 [M] LogicalAnd
--- Original
+++ New
@@ @@
private function accessibleMethods(ReflectionClass $class) : array
{
$methods = Vec\filter($class->getMethods(), function (ReflectionMethod $method) : bool {
- return ($method->isPublic() || $method->isProtected()) && !$this->isInternalDocComment($method->getDocComment());
+ return $method->isPublic() || $method->isProtected() || !$this->isInternalDocComment($method->getDocComment());
});
return Dict\associate(Vec\map($methods, static function (ReflectionMethod $method) : string {
return $method->getName();
8) /github/workspace/src/DetectChanges/BCBreak/ClassBased/MethodRemoved.php:50 [M] LogicalNot
--- Original
+++ New
@@ @@
private function accessibleMethods(ReflectionClass $class) : array
{
$methods = Vec\filter($class->getMethods(), function (ReflectionMethod $method) : bool {
- return ($method->isPublic() || $method->isProtected()) && !$this->isInternalDocComment($method->getDocComment());
+ return ($method->isPublic() || $method->isProtected()) && $this->isInternalDocComment($method->getDocComment());
});
return Dict\associate(Vec\map($methods, static function (ReflectionMethod $method) : string {
return $method->getName();
9) /github/workspace/src/DetectChanges/BCBreak/ClassBased/PropertyRemoved.php:47 [M] LogicalOr
--- Original
+++ New
@@ @@
{
$classIsOpen = !$class->isFinal();
return Dict\filter($class->getProperties(), function (ReflectionProperty $property) use($classIsOpen) : bool {
- return ($property->isPublic() || $classIsOpen && $property->isProtected()) && !$this->isInternalDocComment($property->getDocComment());
+ return $property->isPublic() && ($classIsOpen && $property->isProtected()) && !$this->isInternalDocComment($property->getDocComment());
});
}
private function isInternalDocComment(string|null $comment) : bool
10) /github/workspace/src/DetectChanges/BCBreak/ClassBased/PropertyRemoved.php:47 [M] LogicalAnd
--- Original
+++ New
@@ @@
{
$classIsOpen = !$class->isFinal();
return Dict\filter($class->getProperties(), function (ReflectionProperty $property) use($classIsOpen) : bool {
- return ($property->isPublic() || $classIsOpen && $property->isProtected()) && !$this->isInternalDocComment($property->getDocComment());
+ return $property->isPublic() || $classIsOpen && $property->isProtected() || !$this->isInternalDocComment($property->getDocComment());
});
}
private function isInternalDocComment(string|null $comment) : bool
11) /github/workspace/src/DetectChanges/BCBreak/ClassBased/PropertyRemoved.php:48 [M] LogicalAnd
--- Original
+++ New
@@ @@
{
$classIsOpen = !$class->isFinal();
return Dict\filter($class->getProperties(), function (ReflectionProperty $property) use($classIsOpen) : bool {
- return ($property->isPublic() || $classIsOpen && $property->isProtected()) && !$this->isInternalDocComment($property->getDocComment());
+ return ($property->isPublic() || ($classIsOpen || $property->isProtected())) && !$this->isInternalDocComment($property->getDocComment());
});
}
private function isInternalDocComment(string|null $comment) : bool
12) /github/workspace/src/DetectChanges/BCBreak/ClassBased/PropertyRemoved.php:49 [M] LogicalNot
--- Original
+++ New
@@ @@
{
$classIsOpen = !$class->isFinal();
return Dict\filter($class->getProperties(), function (ReflectionProperty $property) use($classIsOpen) : bool {
- return ($property->isPublic() || $classIsOpen && $property->isProtected()) && !$this->isInternalDocComment($property->getDocComment());
+ return ($property->isPublic() || $classIsOpen && $property->isProtected()) && $this->isInternalDocComment($property->getDocComment());
});
}
private function isInternalDocComment(string|null $comment) : bool
13) /github/workspace/src/Formatter/MarkdownPipedToSymfonyConsoleFormatter.php:66 [M] ArrayItemRemoval
--- Original
+++ New
@@ @@
private function convertFilteredChangesToMarkdownBulletList(Closure $filterFunction, Change ...$changes) : array
{
return Vec\map(Vec\filter($changes, $filterFunction), static function (Change $change) : string {
- return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
+ return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
});
}
}
14) /github/workspace/src/Formatter/MarkdownPipedToSymfonyConsoleFormatter.php:66 [M] Concat
--- Original
+++ New
@@ @@
private function convertFilteredChangesToMarkdownBulletList(Closure $filterFunction, Change ...$changes) : array
{
return Vec\map(Vec\filter($changes, $filterFunction), static function (Change $change) : string {
- return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
+ return Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . ' - ' . "\n";
});
}
}
15) /github/workspace/src/Formatter/MarkdownPipedToSymfonyConsoleFormatter.php:66 [M] ConcatOperandRemoval
--- Original
+++ New
@@ @@
private function convertFilteredChangesToMarkdownBulletList(Closure $filterFunction, Change ...$changes) : array
{
return Vec\map(Vec\filter($changes, $filterFunction), static function (Change $change) : string {
- return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
+ return Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
});
}
}
16) /github/workspace/src/Formatter/MarkdownPipedToSymfonyConsoleFormatter.php:66 [M] ConcatOperandRemoval
--- Original
+++ New
@@ @@
private function convertFilteredChangesToMarkdownBulletList(Closure $filterFunction, Change ...$changes) : array
{
return Vec\map(Vec\filter($changes, $filterFunction), static function (Change $change) : string {
- return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
+ return ' - ' . "\n";
});
}
}
17) /github/workspace/src/Formatter/MarkdownPipedToSymfonyConsoleFormatter.php:66 [M] Concat
--- Original
+++ New
@@ @@
private function convertFilteredChangesToMarkdownBulletList(Closure $filterFunction, Change ...$changes) : array
{
return Vec\map(Vec\filter($changes, $filterFunction), static function (Change $change) : string {
- return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
+ return ' - ' . "\n" . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']);
});
}
}
18) /github/workspace/src/Formatter/MarkdownPipedToSymfonyConsoleFormatter.php:66 [M] ConcatOperandRemoval
--- Original
+++ New
@@ @@
private function convertFilteredChangesToMarkdownBulletList(Closure $filterFunction, Change ...$changes) : array
{
return Vec\map(Vec\filter($changes, $filterFunction), static function (Change $change) : string {
- return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']) . "\n";
+ return ' - ' . Str\replace_every(Str\trim($change->__toString()), ['ADDED: ' => '', 'CHANGED: ' => '', 'REMOVED: ' => '', 'SKIPPED: ' => '']);
});
}
}
19) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:42 [M] MethodCallRemoval
--- Original
+++ New
@@ @@
Psl\invariant(Filesystem\is_file($installationPath . '/composer.json'), 'Could not locate composer.json within installation path.');
$this->runInDirectory(function () use($installationPath, $includeDevelopmentDependencies) : void {
$installer = ($this->makeComposerInstaller)($installationPath);
- // Some defaults needed for this specific implementation:
- $installer->setDevMode($includeDevelopmentDependencies);
+
$installer->setDumpAutoloader(false);
/**
* @psalm-suppress DeprecatedMethod we will keep using the deprecated API until the next major release
20) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:43 [M] FalseValue
--- Original
+++ New
@@ @@
$installer = ($this->makeComposerInstaller)($installationPath);
// Some defaults needed for this specific implementation:
$installer->setDevMode($includeDevelopmentDependencies);
- $installer->setDumpAutoloader(false);
+ $installer->setDumpAutoloader(true);
/**
* @psalm-suppress DeprecatedMethod we will keep using the deprecated API until the next major release
* of composer, as we otherwise need to re-design how an {@see Installer} is constructed.
21) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:43 [M] MethodCallRemoval
--- Original
+++ New
@@ @@
$installer = ($this->makeComposerInstaller)($installationPath);
// Some defaults needed for this specific implementation:
$installer->setDevMode($includeDevelopmentDependencies);
- $installer->setDumpAutoloader(false);
+
/**
* @psalm-suppress DeprecatedMethod we will keep using the deprecated API until the next major release
* of composer, as we otherwise need to re-design how an {@see Installer} is constructed.
22) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:48 [M] FalseValue
--- Original
+++ New
@@ @@
* @psalm-suppress DeprecatedMethod we will keep using the deprecated API until the next major release
* of composer, as we otherwise need to re-design how an {@see Installer} is constructed.
*/
- $installer->setRunScripts(false);
+ $installer->setRunScripts(true);
$installer->setPlatformRequirementFilter(new IgnoreAllPlatformRequirementFilter());
$installer->run();
}, $installationPath);
23) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:48 [M] MethodCallRemoval
--- Original
+++ New
@@ @@
// Some defaults needed for this specific implementation:
$installer->setDevMode($includeDevelopmentDependencies);
$installer->setDumpAutoloader(false);
- /**
- * @psalm-suppress DeprecatedMethod we will keep using the deprecated API until the next major release
- * of composer, as we otherwise need to re-design how an {@see Installer} is constructed.
- */
- $installer->setRunScripts(false);
+
$installer->setPlatformRequirementFilter(new IgnoreAllPlatformRequirementFilter());
$installer->run();
}, $installationPath);
24) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:49 [M] MethodCallRemoval
--- Original
+++ New
@@ @@
* of composer, as we otherwise need to re-design how an {@see Installer} is constructed.
*/
$installer->setRunScripts(false);
- $installer->setPlatformRequirementFilter(new IgnoreAllPlatformRequirementFilter());
+
$installer->run();
}, $installationPath);
$astLocator = new ReplaceSourcePathOfLocatedSources($this->astLocator, $installationPath);
25) /github/workspace/src/LocateDependencies/LocateDependenciesViaComposer.php:51 [M] MethodCallRemoval
--- Original
+++ New
@@ @@
*/
$installer->setRunScripts(false);
$installer->setPlatformRequirementFilter(new IgnoreAllPlatformRequirementFilter());
- $installer->run();
+
}, $installationPath);
$astLocator = new ReplaceSourcePathOfLocatedSources($this->astLocator, $installationPath);
return new AggregateSourceLocator([new PhpInternalSourceLocator($astLocator, new ReflectionSourceStubber()), (new MakeLocatorForInstalledJson())($installationPath, $astLocator)]);
Warning: Dashboard report has not been sent: The current process is a pull request build
Time: 1m 28s. Memory: 0.17GB
Error: ] The minimum required MSI percentage should be 100%, but actual is
93.87%. Improve your tests!
Infection seems to not detect coverage inside closures. For example, in https://github.com/Roave/BackwardCompatibilityCheck/actions/runs/3221773917/jobs/5270116570 :
According to my PHPUnit run, I have 100% code coverage:
The behavior seems to be consistent across multiple projects.
phpunit.xml
Output with issue