/*
* Copyright 2011 Henry Coles and Stefan Penndorf
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.pitest.mutationtest.engine.gregor.mutators.experimental;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.Callable;
import org.junit.Before;
import org.junit.Test;
import org.pitest.functional.FunctionalList;
import org.pitest.mutationtest.engine.Mutant;
import org.pitest.mutationtest.engine.MutationDetails;
import org.pitest.mutationtest.engine.gregor.MutatorTestBase;
/**
*
*
* @author Stefan Penndorf <stefan.penndorf@gmail.com>
*/
public class MemberVariableMutatorTest extends MutatorTestBase {
@Before
public void setupEngineToMutateOnlyMemberVariables() {
createTesteeWith(new MemberVariableMutator());
}
@Test
public void shouldProvideAMeaningfulName() {
assertEquals("EXPERIMENTAL_MEMBER_VARIABLE_MUTATOR",
new MemberVariableMutator().getName());
}
private static final Object TEST_OBJECT = new Object();
private static class HasMemberVariable implements Callable<Object> {
private Object member;
@Override
public Object call() throws Exception {
this.member = TEST_OBJECT;
return this.member;
}
}
@Test
public void shouldRemoveAssignmentToMemberVariable() throws Exception {
final Mutant mutant = getFirstMutant(HasMemberVariable.class);
assertMutantCallableReturns(new HasMemberVariable(), mutant, null);
}
static class HasFinalMemberVariable implements Callable<Integer> {
private final Integer member2 = 5;
@Override
public Integer call() throws Exception {
return this.member2;
}
}
@Test
public void shouldRemoveAssignmentToFinalMemberVariable() throws Exception {
final Mutant mutant = getFirstMutant(HasFinalMemberVariable.class);
assertMutantCallableReturns(new MutantStarter<Integer>(
HasFinalMemberVariable.class), mutant, null);
}
static class HasFinalPrimitiveMemberVariable implements Callable<Integer> {
private final int member2;
public HasFinalPrimitiveMemberVariable(final int i) {
this.member2 = i;
}
@Override
public Integer call() throws Exception {
return this.member2;
}
}
static class HasFinalPrimitiveMemberVariableStarter extends
MutantStarter<Integer> {
@Override
protected Callable<Integer> constructMutee() throws Exception {
return new HasFinalPrimitiveMemberVariable(5);
}
}
@Test
public void shouldRemoveAssignmentToFinalPrimitiveMemberVariable()
throws Exception {
final Mutant mutant = getFirstMutant(HasFinalPrimitiveMemberVariable.class);
assertMutantCallableReturns(new HasFinalPrimitiveMemberVariableStarter(),
mutant, 0);
}
static class NoInit implements Callable<Integer> {
private int x;
@Override
public Integer call() throws Exception {
return this.x;
}
}
@Test
public void shouldNotCreateMutationForNonInitializedVariable()
throws Exception {
final FunctionalList<MutationDetails> mutations = findMutationsFor(NoInit.class);
assertTrue("Expected no mutant created/available.", mutations.isEmpty());
}
static class HasConstantFinalPrimitiveMemberVariable implements
Callable<String> {
public final int member2 = 42;
@Override
public String call() throws Exception {
final Class<?> c = getClass();
final Integer i = (Integer) c.getField("member2").get(this);
return "" + this.member2 + "-" + i; // will be optimized by compiler to
// "42-" + i;
}
}
@Test
public void isUnableToCreateConsistentMutationForConstantFinalPrimitiveMember()
throws Exception {
// Attention: Mutant is created but return value ist still 42!!!
// Property member2 is mutated (as shown by the reflection stuff, but
// constant will be inlined by the compiler!
final Mutant mutant = getFirstMutant(HasConstantFinalPrimitiveMemberVariable.class);
assertMutantCallableReturns(new MutantStarter<String>(
HasConstantFinalPrimitiveMemberVariable.class), mutant, "42-0");
}
static class AssignmentAfterSomeValuesOnStack_SingleWord implements
Callable<String> {
private int member = 1;
@Override
public String call() throws Exception {
// bipush 100
// aload_0
// iconst_2
// dup_x1
// -> stack: 100, 2, this, 2
// putfield
// -> stack: 100, 2
// iadd
// istore_1
final int i = 100 + (this.member = 2);
return "" + this.member + " " + i;
}
}
@Test
public void consumesFromStackTheSameValuesAsPutfieldWouldConsume_SingleWord()
throws Exception {
createTesteeWith(mutateOnlyCallMethod(), new MemberVariableMutator());
final Mutant mutant = getFirstMutant(AssignmentAfterSomeValuesOnStack_SingleWord.class);
assertMutantCallableReturns(
new AssignmentAfterSomeValuesOnStack_SingleWord(), mutant, "1 102");
}
static class AssignmentAfterSomeValuesOnStack_TwoWord implements
Callable<String> {
private long member = 1;
@Override
public String call() throws Exception {
// ldc2_w 100
// aload_0
// ldc2_w 2
// dup2_x1
// -> stack: 0 100, 0 2, this, 0 2
// putfield
// -> stack: 0 100, 0 2
// ladd
// lstore_1
final long i = 100 + (this.member = 2);
return "" + this.member + " " + i;
}
}
@Test
public void consumesFromStackTheSameValuesAsPutfieldWouldConsume_TwoWord()
throws Exception {
createTesteeWith(mutateOnlyCallMethod(), new MemberVariableMutator());
final Mutant mutant = getFirstMutant(AssignmentAfterSomeValuesOnStack_TwoWord.class);
assertMutantCallableReturns(new AssignmentAfterSomeValuesOnStack_TwoWord(),
mutant, "1 102");
}
}