diff --git a/dspot/src/main/java/fr/inria/diversify/utils/AmplificationHelper.java b/dspot/src/main/java/fr/inria/diversify/utils/AmplificationHelper.java index 61f162f72..e22a7c168 100644 --- a/dspot/src/main/java/fr/inria/diversify/utils/AmplificationHelper.java +++ b/dspot/src/main/java/fr/inria/diversify/utils/AmplificationHelper.java @@ -10,9 +10,7 @@ import org.junit.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import spoon.reflect.code.CtComment; -import spoon.reflect.code.CtInvocation; -import spoon.reflect.code.CtSuperAccess; +import spoon.reflect.code.*; import spoon.reflect.declaration.CtAnnotation; import spoon.reflect.declaration.CtImport; import spoon.reflect.declaration.CtMethod; @@ -45,6 +43,10 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static java.lang.Integer.parseInt; +import static java.lang.Long.parseLong; +import static java.lang.Math.toIntExact; + /** * Created by Benjamin DANGLOT * benjamin.danglot@inria.fr @@ -344,33 +346,55 @@ private static CtMethod cloneMethod(CtMethod method, String suffix) { */ private static CtMethod cloneTestMethod(CtMethod method, String suffix) { CtMethod cloned_method = cloneMethod(method, suffix); - CtAnnotation testAnnotation = cloned_method.getAnnotations().stream() - .filter(annotation -> annotation.toString().contains("Test")) - .findFirst().orElse(null); - if (testAnnotation != null) { - cloned_method.removeAnnotation(testAnnotation); - } final Factory factory = method.getFactory(); prepareTestMethod(cloned_method, factory); return cloned_method; } + /** + * Prepares the test annotation of a method + * + * @param cloned_method The test method to modify + * @param factory The factory to create a new test annotation if needed + */ public static void prepareTestMethod(CtMethod cloned_method, Factory factory) { - CtAnnotation testAnnotation; - testAnnotation = factory.Core().createAnnotation(); - CtTypeReference ref = factory.Core().createTypeReference(); - ref.setSimpleName("Test"); - - CtPackageReference refPackage = factory.Core().createPackageReference(); - refPackage.setSimpleName("org.junit"); - ref.setPackage(refPackage); - testAnnotation.setAnnotationType(ref); - - Map elementValue = new HashMap<>(); - elementValue.put("timeout", timeOutInMs); - testAnnotation.setElementValues(elementValue); - - cloned_method.addAnnotation(testAnnotation); + CtAnnotation testAnnotation = cloned_method.getAnnotations().stream() + .filter(annotation -> annotation.toString().contains("Test")) + .findFirst().orElse(null); + if (testAnnotation != null) { + CtExpression originalTimeout = testAnnotation.getValue("timeout"); + if (originalTimeout == null) { + testAnnotation.addValue("timeout", timeOutInMs); + } else { + int valueOriginalTimeout; + if (originalTimeout.toString().endsWith("L")) { + String stringTimeout = originalTimeout.toString(); + valueOriginalTimeout = toIntExact(parseLong(stringTimeout.substring(0, stringTimeout.length() - 1))); + } else { + valueOriginalTimeout = parseInt(originalTimeout.toString()); + } + if (valueOriginalTimeout < timeOutInMs) { + CtLiteral newTimeout = factory.createLiteral(timeOutInMs); + newTimeout.setValue(timeOutInMs); + originalTimeout.replace(newTimeout); + } + } + } else { + CtAnnotation newTestAnnotation; + newTestAnnotation = factory.Core().createAnnotation(); + CtTypeReference ref = factory.Core().createTypeReference(); + ref.setSimpleName("Test"); + + CtPackageReference refPackage = factory.Core().createPackageReference(); + refPackage.setSimpleName("org.junit"); + ref.setPackage(refPackage); + newTestAnnotation.setAnnotationType(ref); + + Map elementValue = new HashMap<>(); + elementValue.put("timeout", timeOutInMs); + newTestAnnotation.setElementValues(elementValue); + cloned_method.addAnnotation(newTestAnnotation); + } cloned_method.addThrownType(factory.Type().createReference(Exception.class)); } diff --git a/dspot/src/test/java/fr/inria/diversify/dspot/AmplificationTest.java b/dspot/src/test/java/fr/inria/diversify/dspot/AmplificationTest.java index 01b704c26..d2208be0f 100644 --- a/dspot/src/test/java/fr/inria/diversify/dspot/AmplificationTest.java +++ b/dspot/src/test/java/fr/inria/diversify/dspot/AmplificationTest.java @@ -5,10 +5,13 @@ import fr.inria.Utils; import org.junit.Test; import spoon.reflect.declaration.CtClass; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.factory.Factory; import java.util.Arrays; import java.util.Collections; +import static fr.inria.diversify.utils.AmplificationHelper.prepareTestMethod; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -43,4 +46,17 @@ public void compileAndRunTest() throws Exception { assertEquals(4, testListener.getRunningTests().size()); assertEquals(4, testListener.getPassingTests().size()); } + + /** + * Tests that original test annotations are kept and modified correctly. + */ + @Test + public void prepareTestMethodTest() throws Exception { + CtMethod testMethodWithAnnotations = ((CtMethod) (Utils.findClass("fr.inria.filter.passing.PassingTest").getMethodsByName("testNPEExpected").get(0))); + final Factory factory = testMethodWithAnnotations.getFactory(); + prepareTestMethod(testMethodWithAnnotations, factory); + // expected was kept and timeout was increased + assertEquals("[@org.junit.Test(timeout = 10000, expected = java.lang.NullPointerException.class)]", + testMethodWithAnnotations.getAnnotations().toString()); + } } diff --git a/dspot/src/test/java/fr/inria/diversify/dspot/DSpotTest.java b/dspot/src/test/java/fr/inria/diversify/dspot/DSpotTest.java index eddb35d8d..00d96d4bf 100644 --- a/dspot/src/test/java/fr/inria/diversify/dspot/DSpotTest.java +++ b/dspot/src/test/java/fr/inria/diversify/dspot/DSpotTest.java @@ -38,13 +38,13 @@ public void testExcludedClassesInPropertyFile() throws Exception { Collections.singletonList(new TestMethodCallAdder()), new JacocoCoverageSelector() ); - // the test class fr.inria.filter.passing.PassingTest has 2 method, but only one is amplified - assertEquals(2, Utils.findClass("fr.inria.filter.passing.PassingTest").getMethods().size()); + // the test class fr.inria.filter.passing.PassingTest has 3 methods, but only two are amplified + assertEquals(3, Utils.findClass("fr.inria.filter.passing.PassingTest").getMethods().size()); // the test class fr.inria.filter.failing.FailingTest match the regex, but it is excluded in the properties final List ctTypes = dSpot.amplifyTest("fr.inria.filter.*"); assertEquals(1, ctTypes.size()); // uses the mock to retrieve the number of method to be amplified - assertEquals(1, dSpot.numberOfMethod); + assertEquals(2, dSpot.numberOfMethod); } private class MockDSpot extends DSpot { diff --git a/dspot/src/test/java/fr/inria/diversify/dspot/assertGenerator/AssertGeneratorTest.java b/dspot/src/test/java/fr/inria/diversify/dspot/assertGenerator/AssertGeneratorTest.java index e7902bae9..3a5ab4f7e 100644 --- a/dspot/src/test/java/fr/inria/diversify/dspot/assertGenerator/AssertGeneratorTest.java +++ b/dspot/src/test/java/fr/inria/diversify/dspot/assertGenerator/AssertGeneratorTest.java @@ -174,6 +174,14 @@ public void testMakeFailureTest() throws Exception { assertTrue(generatedAssertion.isEmpty()); } + @Test + public void testMakeExpectedFailureTest() throws Exception { + CtClass testClass = Utils.findClass("fr.inria.filter.passing.PassingTest"); + final CtMethod testAssertionError = Utils.findMethod("fr.inria.filter.passing.PassingTest", "testNPEExpected"); + final List> generatedAssertion = assertGenerator.assertionAmplification(testClass, Collections.singletonList(testAssertionError)); + assertTrue(generatedAssertion.isEmpty()); + } + private static final String expectedBody = "{" + AmplificationHelper.LINE_SEPARATOR + " fr.inria.sample.ClassWithBoolean cl = new fr.inria.sample.ClassWithBoolean();" + AmplificationHelper.LINE_SEPARATOR + " org.junit.Assert.assertTrue(((fr.inria.sample.ClassWithBoolean)cl).getBoolean());" + AmplificationHelper.LINE_SEPARATOR + diff --git a/dspot/src/test/resources/sample/src/test/java/fr/inria/filter/passing/PassingTest.java b/dspot/src/test/resources/sample/src/test/java/fr/inria/filter/passing/PassingTest.java index 1fcb6a498..6dde83c31 100644 --- a/dspot/src/test/resources/sample/src/test/java/fr/inria/filter/passing/PassingTest.java +++ b/dspot/src/test/resources/sample/src/test/java/fr/inria/filter/passing/PassingTest.java @@ -2,6 +2,7 @@ import org.junit.Test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; /** @@ -20,4 +21,10 @@ public void testAssertion() throws Exception { public void failingTestCase() throws Exception { assertFalse(true); } + + @Test (expected = NullPointerException.class, timeout = 100) + public void testNPEExpected() throws Exception { + String nullString = null; + assertEquals(-1, nullString.length()); + } }