PIT is generating equivalent mutations
Hi,
I noticed that Pitest generated a few false mutants, which are equivalent to the original source code, and as a result, they survived. I found a similar previous issue: https://github.com/hcoles/pitest/issues/497. However, it seems that in certain cases, the fix doesn’t work, or I might be missing some configurations.
Currently using 1.15.0 version with gradle.
public boolean example(int maxSize, Duration maxAge) {
lock.readLock().lock();
try {
int size = elements.size();
if (size == 0) {
return false; // -> replaced boolean return with false for com.example.Example::example → SURVIVED
} else if (size >= maxSize) {
return true; // -> replaced boolean return with true for com.example.Example::example → SURVIVED
} else {
long elapsedNanos = ticker.read() - timeOfLastReset;
return elapsedNanos >= maxAge.toNanos();
}
} finally {
lock.readLock().unlock();
}
}
}
Is there a config missing at our side or is it a known bug?
I'm having the same issue
public boolean asyncAggregateTimeData() {
if(!lock.tryLock()) {
return false;
}
try {
if(isUpdating) {
return false; // → replaced boolean return with false for Aggregator::asyncAggregateTimeData → SURVIVED
}
var now = OffsetDateTime.now();
if(now.minus(minTimeBetweenRefreshes).isBefore(lastAttempt)) {
return false; // → replaced boolean return with false for Aggregator::asyncAggregateTimeData → SURVIVED
}
isUpdating = true;
lastAttempt = now;
aggregationFaults.clear();
executor.execute(this::aggregateTimeData);
} finally {
lock.unlock();
}
return true;
}
The decompiled bytecode looks like this
public boolean asyncAggregateTimeData() {
if (!this.lock.tryLock()) {
return false;
} else {
boolean now;
try {
if (!this.isUpdating) {
OffsetDateTime now = OffsetDateTime.now();
if (now.minus(this.minTimeBetweenRefreshes).isBefore(this.lastAttempt)) {
boolean var2 = false;
return var2;
}
this.isUpdating = true;
this.lastAttempt = now;
this.aggregationFaults.clear();
this.executor.execute(this::aggregateTimeData);
return true;
}
now = false;
} finally {
this.lock.unlock();
}
return now;
}
}
Looking at the byte code, it is a little more understandable. This almost seems like a compiler bug. Still very annoying, and I have not been able to restructure the code differently enough without changing the natural logic that it doesn't happen anymore.
I'm on 21.0.6+7-LTS Temurin