diff --git a/src/test/java/spoon/test/parent/ParentContractTest.java b/src/test/java/spoon/test/parent/ParentContractTest.java index b55211a274a..52aba43afa3 100644 --- a/src/test/java/spoon/test/parent/ParentContractTest.java +++ b/src/test/java/spoon/test/parent/ParentContractTest.java @@ -11,12 +11,14 @@ import spoon.reflect.code.CtTypeAccess; import spoon.reflect.declaration.CtAnnotationType; import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtType; import spoon.reflect.factory.CoreFactory; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtActualTypeContainer; import spoon.reflect.reference.CtReference; import spoon.reflect.visitor.CtVisitable; +import spoon.test.SpoonTestHelpers; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -26,6 +28,8 @@ import java.util.List; import java.util.Queue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static spoon.testing.utils.ModelUtils.createFactory; @@ -35,17 +39,14 @@ public class ParentContractTest { private static Factory factory = createFactory(); + private static final List> allInstantiableMetamodelInterfaces = SpoonTestHelpers.getAllInstantiableMetamodelInterfaces(); @Parameterized.Parameters(name = "{0}") public static Collection data() throws Exception { List values = new ArrayList<>(); - for (Method method : CoreFactory.class.getDeclaredMethods()) { - if (method.getName().startsWith("create") - && method.getParameterCount() == 0 - && method.getReturnType().getSimpleName().startsWith("Ct") - && !CtReference.class.isAssignableFrom(method.getReturnType()) - ){ - values.add(new Object[] { method.getReturnType(), method.invoke(factory.Core()) }); + for (CtType t : allInstantiableMetamodelInterfaces) { + if (!(CtReference.class.isAssignableFrom(t.getActualClass()))) { + values.add(new Object[] { t.getActualClass(), factory.Core().create(t.getActualClass()) }); } } return values; @@ -72,7 +73,7 @@ private List getMethodsToInvoke(Class entry) throws Exception { while (!tocheck.isEmpty()) { Class intf = tocheck.poll(); - Assert.assertTrue(intf.isInterface()); + assertTrue(intf.isInterface()); if (!intf.getSimpleName().startsWith("Ct")) { continue; } @@ -101,10 +102,20 @@ private List getMethodsToInvoke(Class entry) throws Exception { return toInvoke; } + private CtElement createCompatibleObject(Class c) { + for(CtType t : allInstantiableMetamodelInterfaces) { + if (c.isAssignableFrom(t.getActualClass())) { + return factory.Core().create(t.getActualClass()); + } + } + throw new IllegalArgumentException(); + } @Test public void testContract() throws Throwable { + // contract: all setters/adders must set the parent (not necessarily the direct parent, can be upper in the parent tree, for instance when injecting blocks Object o = instance; - for (Method setter : getMethodsToInvoke(toTest)) { + List methodsToInvoke = getMethodsToInvoke(toTest); + for (Method setter : methodsToInvoke) { // special case: impossible methods on some objects (they throw an UnsupportedOperationException) if (setter.getAnnotation(Deprecated.class) != null) continue; @@ -118,14 +129,20 @@ public void testContract() throws Throwable { if (o instanceof CtTypeAccess && "setType".equals(setter.getName())) continue; if (o instanceof CtType && "setSuperclass".equals(setter.getName())) continue; - CtElement mockedArgument = (CtElement) mock(setter.getParameters()[0].getType(), Mockito.withSettings().extraInterfaces(Comparable.class)); + + CtElement argument = createCompatibleObject((Class) setter.getParameters()[0].getType()); + // an empty package is merged with the existing one + // we have to give it a name + if (argument instanceof CtPackage) { + ((CtPackage)argument).setSimpleName("foobar"); + } try { // we create a fresh object CtElement receiver = ((CtElement) o).clone(); // we invoke the setter - setter.invoke(receiver, new Object[] { mockedArgument }); + setter.invoke(receiver, new Object[] { argument }); // we check that setParent has been called - verify(mockedArgument).setParent((CtElement) receiver); + assertTrue(argument.hasParent(receiver)); } catch (AssertionError e) { Assert.fail("call setParent contract failed for " + setter.toString() + " " + e.toString()); } catch (InvocationTargetException e) {