/* * 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; import static org.junit.Assert.assertEquals; import java.util.concurrent.Callable; import org.junit.Before; import org.junit.Test; import org.pitest.mutationtest.engine.Mutant; import org.pitest.mutationtest.engine.gregor.MutatorTestBase; public class InlineConstantMutatorTest extends MutatorTestBase { @Before public void setupEngineToMutateOnlyInlineConstants() { createTesteeWith(new InlineConstantMutator()); } private static class HasBooleanICONST0 implements Callable<Boolean> { @Override public Boolean call() throws Exception { return false; } } @Test public void shouldProvideAMeaningfulName() { assertEquals("INLINE_CONSTANT_MUTATOR", new InlineConstantMutator().getName()); } @Test public void shouldReplaceBooleanFalseWithTrue() throws Exception { final Mutant mutant = getFirstMutant(HasBooleanICONST0.class); assertMutantCallableReturns(new HasBooleanICONST0(), mutant, Boolean.TRUE); } private static class HasIntegerICONST0 implements Callable<Integer> { @Override public Integer call() throws Exception { return 0; } } @Test public void shouldReplaceInteger0With1() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONST0.class); assertMutantCallableReturns(new HasIntegerICONST0(), mutant, 1); } private static class HasBooleanICONST1 implements Callable<Boolean> { @Override public Boolean call() throws Exception { return true; } } @Test public void shouldReplaceBooleanTrueWithFalse() throws Exception { final Mutant mutant = getFirstMutant(HasBooleanICONST1.class); assertMutantCallableReturns(new HasBooleanICONST1(), mutant, Boolean.FALSE); } private static class HasIntegerICONST1 implements Callable<Integer> { @Override public Integer call() throws Exception { return 1; } } @Test public void shouldReplaceInteger1With0() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONST1.class); assertMutantCallableReturns(new HasIntegerICONST1(), mutant, 0); } private static class HasIntegerICONST2 implements Callable<Integer> { @Override public Integer call() throws Exception { return 2; } } @Test public void shouldReplaceInteger2With3() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONST2.class); assertMutantCallableReturns(new HasIntegerICONST2(), mutant, 3); } private static class HasIntegerICONST3 implements Callable<Integer> { @Override public Integer call() throws Exception { return 3; } } @Test public void shouldReplaceInteger3With4() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONST3.class); assertMutantCallableReturns(new HasIntegerICONST3(), mutant, 4); } private static class HasIntegerICONST4 implements Callable<Integer> { @Override public Integer call() throws Exception { return 4; } } @Test public void shouldReplaceInteger4With5() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONST4.class); assertMutantCallableReturns(new HasIntegerICONST4(), mutant, 5); } private static class HasIntegerICONST5 implements Callable<Integer> { @Override public Integer call() throws Exception { return 5; } } @Test public void shouldReplaceInteger5With6() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONST5.class); assertMutantCallableReturns(new HasIntegerICONST5(), mutant, 6); } private static class HasIntegerLDC implements Callable<Integer> { @Override public Integer call() throws Exception { return 987654321; } } @Test public void shouldReplaceLargeIntegerConstantsWithValuePlus1() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerLDC.class); assertMutantCallableReturns(new HasIntegerLDC(), mutant, 987654321 + 1); } private static class HasIntegerICONSTM1 implements Callable<Integer> { @Override public Integer call() throws Exception { return -1; } } /** * Note: Integer numbers and booleans are actually represented in the same way * be the JVM, it is therefore never safe if one changes a 0 to anything but a * 1 or a 1 to anything but a 0. Nevertheless if we find a -1 (ICONST_M1) it * must be an integer, short, byte or long. It won't be a boolean. So it is * always safe to replace -1 with 0. */ @Test public void shouldReplaceIntegerMinus1With0() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerICONSTM1.class); assertMutantCallableReturns(new HasIntegerICONSTM1(), mutant, 0); } private static class HasBIPUSHMinus2 implements Callable<Integer> { @Override public Integer call() throws Exception { return -2; } } @Test public void shouldReplaceIntegerMinus2WithMinus1() throws Exception { final Mutant mutant = getFirstMutant(HasBIPUSHMinus2.class); assertMutantCallableReturns(new HasBIPUSHMinus2(), mutant, -1); } private static class HasBIPUSH implements Callable<Integer> { @Override public Integer call() throws Exception { return 28; } } @Test public void shouldReplaceSmallIntegerConstantsWithValuePlus1() throws Exception { final Mutant mutant = getFirstMutant(HasBIPUSH.class); assertMutantCallableReturns(new HasBIPUSH(), mutant, 29); } private static class HasSIPUSH implements Callable<Integer> { @Override public Integer call() throws Exception { return 32700; } } @Test public void shouldReplaceMediumIntegerConstantsWithValuePlus1() throws Exception { final Mutant mutant = getFirstMutant(HasSIPUSH.class); assertMutantCallableReturns(new HasSIPUSH(), mutant, 32701); } private static class HasTwoMutationPoints implements Callable<Boolean> { @Override public Boolean call() throws Exception { int i = Short.MAX_VALUE; if (i != Short.MAX_VALUE) { i++; // prevent source formating from making final return Boolean.TRUE; // expected } return Boolean.FALSE; } } @Test public void shouldReplaceFirstMutationPointOnly() throws Exception { final Mutant mutant = getFirstMutant(HasTwoMutationPoints.class); assertMutantCallableReturns(new HasTwoMutationPoints(), mutant, Boolean.TRUE); } private static class HasShortOverflow implements Callable<Short> { @Override public Short call() throws Exception { short s = Short.MAX_VALUE; s = preventSourceFormatingMakingFinal(s); return s; } } /** * The JVM does not have a short type, it uses integer under the hood. * <code>Short.MAX_VALUE</code> (=32767) will always be rolled to * <code>Short.MIN_VALUE</code> (=-32768). Note that the rolling will occur * even if only Integer/int variables are used! So <code>int i = 32767;</code> * will always be mutated to <code>int i = -32768;</code>. */ @Test public void shouldOverflowOnShortMaxValue() throws Exception { final Mutant mutant = getFirstMutant(HasShortOverflow.class); assertMutantCallableReturns(new HasShortOverflow(), mutant, Short.MIN_VALUE); } private static class HasIntegerAtMaxShortValue implements Callable<Integer> { @Override public Integer call() throws Exception { int i = Short.MAX_VALUE; i = preventSourceFormatingMakingFinal(i); return i; } } /** * The JVM does not have a short type, it uses integer under the hood. * <code>Short.MAX_VALUE</code> (=32767) will always be rolled to * <code>Short.MIN_VALUE</code> (=-32768). Note that the rolling will occur * even if only Integer/int variables are used! So <code>int i = 32767;</code> * will always be mutated to <code>int i = -32768;</code>. */ @Test public void shouldOverflowIntegerOnShortMaxValue() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerAtMaxShortValue.class); assertMutantCallableReturns(new HasIntegerAtMaxShortValue(), mutant, (int) Short.MIN_VALUE); } public static short preventSourceFormatingMakingFinal(final short s) { return s; } private static class HasByteOverflow implements Callable<Byte> { @Override public Byte call() throws Exception { byte b = Byte.MAX_VALUE; b = preventSourceFormatingMakingFinal(b); return b; } } /** * eclipse source cleanup will make everything final if possible */ public static byte preventSourceFormatingMakingFinal(final byte b) { return b; } /** * The JVM does not have a byte type, it uses integer under the hood. * <code>Byte.MAX_VALUE</code> (=127) will always be rolled to * <code>Byte.MIN_VALUE</code> (=-128). Note that the rolling will occur even * if only Integer/int variables are used! So <code>int i = 127;</code> will * always be mutated to <code>int i = -128;</code>. */ @Test public void shouldOverflowOnByteMaxValue() throws Exception { final Mutant mutant = getFirstMutant(HasByteOverflow.class); assertMutantCallableReturns(new HasByteOverflow(), mutant, Byte.MIN_VALUE); } private static class HasIntegerMaxValue implements Callable<Integer> { @Override public Integer call() throws Exception { return Integer.MAX_VALUE; } } @Test public void shouldReplaceIntegerMaxWithIntegerMin() throws Exception { final Mutant mutant = getFirstMutant(HasIntegerMaxValue.class); assertMutantCallableReturns(new HasIntegerMaxValue(), mutant, Integer.MIN_VALUE); } private static class HasLongLCONST0 implements Callable<Long> { @Override public Long call() throws Exception { return 0L; } } @Test public void shouldReplaceLong0With1() throws Exception { final Mutant mutant = getFirstMutant(HasLongLCONST0.class); assertMutantCallableReturns(new HasLongLCONST0(), mutant, 1L); } private static class HasLongLCONST1 implements Callable<Long> { @Override public Long call() throws Exception { return 1L; } } @Test public void shouldReplaceLong1With2() throws Exception { final Mutant mutant = getFirstMutant(HasLongLCONST1.class); assertMutantCallableReturns(new HasLongLCONST1(), mutant, 2L); } private static class HasLongLDC implements Callable<Long> { @Override public Long call() throws Exception { return 2999999999L; } } @Test public void shouldReplaceLongWithValuePlus1() throws Exception { final Mutant mutant = getFirstMutant(HasLongLDC.class); assertMutantCallableReturns(new HasLongLDC(), mutant, 3000000000L); } private static class HasLongLDCMinus1 implements Callable<Long> { @Override public Long call() throws Exception { return -1L; } } @Test public void shouldReplaceLongMinus1With0() throws Exception { final Mutant mutant = getFirstMutant(HasLongLDCMinus1.class); assertMutantCallableReturns(new HasLongLDCMinus1(), mutant, 0L); } /* * Double and Float */ private static class HasFloatFCONST0 implements Callable<Float> { @Override public Float call() throws Exception { return 0.0F; } } @Test public void shouldReplaceFloat0With1() throws Exception { final Mutant mutant = getFirstMutant(HasFloatFCONST0.class); assertMutantCallableReturns(new HasFloatFCONST0(), mutant, 1.0F); } private static class HasFloatFCONST1 implements Callable<Float> { @Override public Float call() throws Exception { return 1.0F; } } @Test public void shouldReplaceFloat1With2() throws Exception { final Mutant mutant = getFirstMutant(HasFloatFCONST1.class); assertMutantCallableReturns(new HasFloatFCONST1(), mutant, 2.0F); } private static class HasFloatFCONST2 implements Callable<Float> { @Override public Float call() throws Exception { return 2.0F; } } @Test public void shouldReplaceFloat2With1() throws Exception { final Mutant mutant = getFirstMutant(HasFloatFCONST2.class); assertMutantCallableReturns(new HasFloatFCONST2(), mutant, 1.0F); } private static class HasFloatLDC implements Callable<Float> { @Override public Float call() throws Exception { return 8364.123F; } } @Test public void shouldReplaceFloatWith1() throws Exception { final Mutant mutant = getFirstMutant(HasFloatLDC.class); assertMutantCallableReturns(new HasFloatLDC(), mutant, 1.0F); } private static class HasFloatMultipleLDC implements Callable<Float> { @Override public Float call() throws Exception { float f = 16.0F; float f2 = 4.0F; f = preventSourceFormatingMakingFinal(f); f2 = preventSourceFormatingMakingFinal(f2); return f * f2; } } private static <T> T preventSourceFormatingMakingFinal(final T f) { return f; } @Test public void shouldReplaceFirstFloatMutationPointOnly() throws Exception { final Mutant mutant = getFirstMutant(HasFloatMultipleLDC.class); assertMutantCallableReturns(new HasFloatMultipleLDC(), mutant, 4.0F); } private static class HasDoubleDCONST0 implements Callable<Double> { @Override public Double call() throws Exception { return 0.0D; } } @Test public void shouldReplaceDouble0With1() throws Exception { final Mutant mutant = getFirstMutant(HasDoubleDCONST0.class); assertMutantCallableReturns(new HasDoubleDCONST0(), mutant, 1.0D); } private static class HasDoubleDCONST1 implements Callable<Double> { @Override public Double call() throws Exception { return 1.0D; } } @Test public void shouldReplaceDouble1With2() throws Exception { final Mutant mutant = getFirstMutant(HasDoubleDCONST1.class); assertMutantCallableReturns(new HasDoubleDCONST1(), mutant, 2.0D); } private static class HasDoubleLDC implements Callable<Double> { @Override public Double call() throws Exception { return 123456789.123D; } } @Test public void shouldReplaceDoubleWith1() throws Exception { final Mutant mutant = getFirstMutant(HasDoubleLDC.class); assertMutantCallableReturns(new HasDoubleLDC(), mutant, 1.0D); } private static class HasDoubleMultipleLDC implements Callable<Double> { @Override public Double call() throws Exception { double d = 4578.1158D; double d2 = 2.0D; d = preventSourceFormatingMakingFinal(d); d2 = preventSourceFormatingMakingFinal(d2); return d * d2; } } @Test public void shouldReplaceFirstDoubleMutationPointOnly() throws Exception { final Mutant mutant = getFirstMutant(HasDoubleMultipleLDC.class); assertMutantCallableReturns(new HasDoubleMultipleLDC(), mutant, 2.0D); } }