8000 Add negation mutators by manhunto · Pull Request #1753 · infection/infection · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add negation mutators #1753

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

manhunto
Copy link
Contributor
@manhunto manhunto commented Nov 27, 2022

This PR:

  • Add mutators that negate whole condition in if and else if (it only mutates simple expressions like function call, method call etc. to not duplicate with other existing mutators)
  • Add mutators that negate whole condition in LogicalAnd and LogicalOr expressions
  • Add mutators that negate every sub expression together in LogicalAnd and LogicalOr expressions (even in complex conditions)
  • Add mutators that negate every sub expression separately in LogicalAnd and LogicalOr expressions (even in complex conditions, only simple sub expressions like in if and else if)
  • Covered by tests
  • Doc PR: Add docs for "if condition negation" mutators site#253
  1. Negation of entire simple expression in if.
-if ($this->fooBar()) {
+if (!$this->fooBar()) {
  1. Negation of entire simple expression in elseif.
if ($this->fooBar() {
- } elseif ($this->fooBaz()) {
+ } elseif (!$this->fooBaz()) {
}
  1. Negation of entire && and || condition (even in if statements)
- $var = $a && $b;
+ $var = !($a && $b);
- $var = $a || $b;
+ $var = !($a || $b);
  1. Negation of every sub expression in && and || condition (even in if statements)
- $var = $a && $b;
+ $var = !$a && !$b;
- $var = $a || $b;
+ $var = !$a || !$b;
  1. Negation of every sub expression separately in && and || condition (even in if statements)
- $var = $a && $b;
# Mutation 1
+ $var = !$a && $b;
# Mutation 2
+ $var = $a && !$b;
- $var = $a || $b;
# Mutation 1
+ $var = !$a || $b;
# Mutation 2
+ $var = $a || !$b;

I've decided to create one PR for all mutators because they are related. They share traits and I think it is better to review it together, but I can split it if you think that it will be easier to maintain.

Closes: #1752

Copy link
Member
@theofidry theofidry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay in the review; good job! 👏

Despite the number of comments I think it's mostly nitpicks, it looks pretty good to me.

It's been too long since I've had a good view on the mutators and I didn't completely follow the conversation with @maks-rafalko previously neither so I do think it deserve another round of review. As such I wouldn't recommend to address all the points yet just in case another maintainer disagrees with them :)

<<<'PHP'
<?php

$var = a() && b();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for the sake of it I would add another test making use of the and and AND notation instead of &&

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that require implementation of \PhpParser\Node\Expr\BinaryOp\LogicalAnd node in mutators. Currently, we operate on BooleanAnd node.

{
private function isSimpleExpression(Node\Expr $expr): bool
{
return $expr instanceof Node\Expr\FuncCall
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at the implementation the method could be static

8000
/**
* @internal
*/
trait SimpleExpression
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From this alone I am not convinced there is any benefit of it being a trait. It could very well be a regular stateless class with a static method and a private constructor.

But maybe the rest of the team prefers traits... I'll let them voice their opinion on it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you, I also prefer working with static methods that with traits. Making it static class require to write unit tests for it (project requirement). So let me know which way I supposed to choose ;)

|| $expr instanceof Node\Expr\StaticCall
|| $expr instanceof Node\Expr\Variable
|| $expr instanceof Node\Expr\ArrayDimFetch
|| $expr instanceof Node\Expr\ClassConstFetch;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for other reviewers, I did not verify the list completeness

@manhunto
Copy link
Contributor Author

Thank you for review @theofidry I've introducer some of changes proposed by you and I'm waiting for comments from another reviewers:)

@manhunto
Copy link
Contributor Author
manhunto commented Feb 2, 2023

Hi @maks-rafalko, any updates on this PR? :)

@maks-rafalko
Copy link
Member
maks-rafalko commented Apr 2, 2023

Oh, somehow I missed this one, sorry. Could you please rebase so we can move forward? And thank you for you patience and work!

manhunto and others added 9 commits April 5, 2023 00:45
Co-authored-by: Théo FIDRY <5175937+theofidry@users.noreply.github.com>
Co-authored-by: Théo FIDRY <5175937+theofidry@users.noreply.github.com>
Co-authored-by: Théo FIDRY <5175937+theofidry@users.noreply.github.com>
@maks-rafalko maks-rafalko force-pushed the feature/negation-in-if-and-boolean branch from 6a1ca8c to 71b2fb9 Compare April 4, 2023 21:46
@maks-rafalko
Copy link
Member

Ok, I managed to rebase it myself.

Notes for reviewers: we need to analyze if the provided mutators somehow generate duplicate muations (with existing in master mutators and between each other).

My idea is to create boolean matrices (as I did here #1752 (comment)) and compare all of them, finding duplicate results.

@icanhazstring
Copy link
Contributor

Just out of curiosity as I don't know the full functionality behind.

Isn't there a hashmap containing a list of, let's say, md5 hashes of the content of each mutated file? So that there can be no duplicate mutation?

Or is it because that some mutations look different but produce the same logical outcome?

@maks-rafalko
Copy link
Member
maks-rafalko commented Apr 5, 2023

@icanhazstring I'm more about boolean matrices created by new mutators here. The simplest thing to understand it is De Morgan's law

where !$a && !$b === !($a || $b). By introducing many new different mutations, we can have duplicates in boolean matrices, which is not efficient as the same (logically) mutators will consume more and more time.

However, your question about hashes gives some source for thinking. We do have md5 hashing for each mutation, but I don't think we check uniqueness to avoid duplicates on physical, not logical level:

private function createHash(): string
{
$hashKeys = [
$this->originalFilePath,
$this->mutatorName,
$this->mutationByMutatorIndex,
];
foreach ($this->attributes as $attribute) {
$hashKeys[] = $attribute;
}
return md5(implode('_', $hashKeys));
}

@icanhazstring
Copy link
Contributor

Maybe we could improve this hash based on the uniqueness of these logical mutations?
Don't know if we could come up with a parser implementation based on de morgan's law to figure out duplicates.

@maks-rafalko maks-rafalko enabled auto-merge (squash) May 12, 2023 19:54
Copy link
Member
@maks-rafalko maks-rafalko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manhunto this is absolutely awesome work. I've spent this day investigating the code and checking for duplicates. Made and update to not negate $a === false & $b !== true because it's duplicate of TrueValue / FalseValue mutators. Did the same for Or analogue.

Also, added more tests and simplified child classes to reduce the number of abstract methods.

I agree that from maintenance POV it's better to keep classes separate, at least for now, because the logic is quite complex.

Thank you for your great contribution, going to merge it as soon as the build passes.

@maks-rafalko maks-rafalko merged commit 62441a0 into infection:master May 12, 2023
maks-rafalko added a commit to infection/site that referenced this pull request May 12, 2023
@manhunto
Copy link
Contributor Author

@maks-rafalko thank you for helping me with this PR -- for the changes you introduced in this PR and docs :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

If condition negation mutator
5 participants
0