Skip to content
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

Returning an Optional.empty() inside try-with-resources causes mutant to survive #968

Closed
nikosstais opened this issue Jan 8, 2022 · 4 comments

Comments

@nikosstais
Copy link

nikosstais commented Jan 8, 2022

I have a mutant that cannot be killed with message:
replaced return value with Optional.empty for com/blah::createFile → SURVIVED

try (final var os = new ByteArrayOutputStream()){

... some code to write on os

  if (case I do not need the file anyway){
     return Optional.empty(); <-- here tries to replace the return value with Optional.empty() 
  }

  return Optional.of(os.toByteArray());
}

I am using version 1.7.3

Based on quick start guide https://pitest.org/quickstart/mutators/ :
Pitest will filter out equivalent mutations to methods that are already hard coded to return the empty value.

It seems that above statement is not respected in my case

@hcoles
Copy link
Owner

hcoles commented Mar 9, 2022

Hi @nikosstais, thanks for the report (and sorry for the slow response).

I've taken a look at this, and it is going to be an awkward issue to resolve. The filtering of return Optional.empty() mutants works by looking for bytecode that pushes empty onto the stack, immeditately followed by a return.

Unfortunately, try-with-resources is causing the compiler to store the ref in a local variable before returning.

Filtering this out at the bytecode level would require an analysis that tracked what was stored, but didn't trigger for more complex code where the mutant shouldn't be filtered.

It's certainly possible, but not something that is going to be fixed quickly.

@hcoles
Copy link
Owner

hcoles commented Mar 10, 2022

Ok, couldn't help picking at this. There should be something in the next release which picks up at leasst some cases of this.

@hcoles
Copy link
Owner

hcoles commented Mar 10, 2022

A partial fix has been merged. It works if the compiler chooses to order the instructions so the ARETURN of the empty optional occurs before another write to the slot where it is stored. The simple example used in the test works in java 11 and 17, but the java 8 compiler jumps to the return so the mutant isn't filtered.

@hcoles
Copy link
Owner

hcoles commented Aug 3, 2022

Release 1.9.4 extends the analysis to work with java 8 and catch more complex cases.

@hcoles hcoles closed this as completed Aug 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants