diff --git a/build.gradle b/build.gradle index 595d53daf..49b9d37c2 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,6 @@ subprojects { java { withJavadocJar() withSourcesJar() - toolchain {languageVersion = JavaLanguageVersion.of(8)} } publishing { diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java index 6e6dae22e..93cb0c7f8 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/AnonymousArbitraryIntrospector.java @@ -18,11 +18,9 @@ package com.navercorp.fixturemonkey.api.introspector; -import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.List; -import java.util.Map; import org.apiguardian.api.API; import org.apiguardian.api.API.Status; @@ -76,7 +74,7 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) invocationHandlerBuilder.put(methodProperty.getMethodName(), combined); } - if (invocationHandlerBuilder.generatedValuesByMethodName.isEmpty()) { + if (invocationHandlerBuilder.isEmpty()) { return null; } @@ -92,19 +90,4 @@ public ArbitraryIntrospectorResult introspect(ArbitraryGeneratorContext context) ); } - private static final class InvocationHandlerBuilder { - private final Map generatedValuesByMethodName; - - private InvocationHandlerBuilder(Map generatedValuesByMethodName) { - this.generatedValuesByMethodName = generatedValuesByMethodName; - } - - private void put(String methodName, Object value) { - generatedValuesByMethodName.put(methodName, value); - } - - private InvocationHandler build() { - return (proxy, method, args) -> generatedValuesByMethodName.get(method.getName()); - } - } } diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/InvocationHandlerBuilder.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/InvocationHandlerBuilder.java new file mode 100644 index 000000000..df0769f5f --- /dev/null +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/introspector/InvocationHandlerBuilder.java @@ -0,0 +1,24 @@ +package com.navercorp.fixturemonkey.api.introspector; + +import java.lang.reflect.InvocationHandler; +import java.util.Map; + +final class InvocationHandlerBuilder { + private final Map generatedValuesByMethodName; + + InvocationHandlerBuilder(Map generatedValuesByMethodName) { + this.generatedValuesByMethodName = generatedValuesByMethodName; + } + + void put(String methodName, Object value) { + generatedValuesByMethodName.put(methodName, value); + } + + InvocationHandler build() { + return (proxy, method, args) -> generatedValuesByMethodName.get(method.getName()); + } + + boolean isEmpty() { + return generatedValuesByMethodName.isEmpty(); + } +} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/AnnotatedTypes.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/AnnotatedTypes.java new file mode 100644 index 000000000..40ec084fb --- /dev/null +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/AnnotatedTypes.java @@ -0,0 +1,91 @@ +package com.navercorp.fixturemonkey.api.type; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedArrayType; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Type; +import java.util.Arrays; + +import javax.annotation.Nullable; + +public final class AnnotatedTypes { + public static AnnotatedArrayType from( + AnnotatedType annotatedGenericComponentType, + Type type, + Annotation[] annotations, + Annotation[] declaredAnnotations, + AnnotatedType annotatedOwnerType + ) { + return new AnnotatedArrayType() { + @Override + public AnnotatedType getAnnotatedGenericComponentType() { + return annotatedGenericComponentType; + } + + @Override + public Type getType() { + return type; + } + + @Override + public T getAnnotation(Class annotationClass) { + return Arrays.stream(annotations) + .filter(it -> it.getClass() == annotationClass) + .findAny() + .map(annotationClass::cast) + .orElse(null); + } + + @Override + public Annotation[] getAnnotations() { + return annotations; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return declaredAnnotations; + } + }; + } + + public static AnnotatedParameterizedType from( + AnnotatedType[] annotatedActualTypeArguments, + Type type, + Annotation[] annotations, + Annotation[] declaredAnnotations, + AnnotatedType annotatedOwnerType + ) { + return new AnnotatedParameterizedType() { + @Override + public AnnotatedType[] getAnnotatedActualTypeArguments() { + return annotatedActualTypeArguments; + } + + @Override + public Type getType() { + return type; + } + + @SuppressWarnings("unchecked") + @Override + @Nullable + public T getAnnotation(Class annotationClass) { + return (T)Arrays.stream(annotations) + .filter(it -> it.getClass() == annotationClass) + .findAny() + .orElse(null); + } + + @Override + public Annotation[] getAnnotations() { + return annotations; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return declaredAnnotations; + } + }; + } +} diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java index 614be77e5..282c1904a 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/type/Types.java @@ -269,7 +269,7 @@ private static AnnotatedType resolvesParentTypeGenerics( } if (genericType instanceof GenericArrayType) { - return resolveGenericsArrayType(currentAnnotatedType, parentGenericsTypes); + return resolveGenericsArrayType(parentAnnotatedType, currentAnnotatedType, parentGenericsTypes); } AnnotatedParameterizedType fieldParameterizedType = (AnnotatedParameterizedType)currentAnnotatedType; @@ -320,43 +320,17 @@ public Type getOwnerType() { } }; - return new AnnotatedParameterizedType() { - @Override - public AnnotatedType[] getAnnotatedActualTypeArguments() { - return resolvedGenericsTypes; - } - - // For compatibility with JDK >= 9. A breaking change in the JDK :-( - // @Override - @SuppressWarnings("Since15") - public AnnotatedType getAnnotatedOwnerType() { - // TODO: Return annotatedType.getAnnotatedOwnerType() as soon as Java >= 9 is being used - return null; - } - - @Override - public Type getType() { - return resolveType; - } - - @Override - public T getAnnotation(Class annotationClass) { - return fieldParameterizedType.getAnnotation(annotationClass); - } - - @Override - public Annotation[] getAnnotations() { - return fieldParameterizedType.getAnnotations(); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return fieldParameterizedType.getDeclaredAnnotations(); - } - }; + return AnnotatedTypes.from( + resolvedGenericsTypes, + resolveType, + fieldParameterizedType.getAnnotations(), + fieldParameterizedType.getDeclaredAnnotations(), + parentAnnotatedType + ); } private static AnnotatedArrayType resolveGenericsArrayType( + AnnotatedType parentAnnotatedType, AnnotatedType currentAnnotatedType, AnnotatedType[] ownerGenericsTypes ) { @@ -387,38 +361,13 @@ public Type getOwnerType() { Type resolveType = (GenericArrayType)() -> genericComponentTypeWithGeneric; - return new AnnotatedArrayType() { - @Override - public AnnotatedType getAnnotatedGenericComponentType() { - return Types.generateAnnotatedTypeWithoutAnnotation(genericComponentTypeWithGeneric); - } - - @SuppressWarnings("Since15") - public AnnotatedType getAnnotatedOwnerType() { - // TODO: Return annotatedType.getAnnotatedOwnerType() as soon as Java >= 9 is being used - return null; - } - - @Override - public Type getType() { - return resolveType; - } - - @Override - public T getAnnotation(Class annotationClass) { - return currentAnnotatedType.getAnnotation(annotationClass); - } - - @Override - public Annotation[] getAnnotations() { - return currentAnnotatedType.getAnnotations(); - } - - @Override - public Annotation[] getDeclaredAnnotations() { - return currentAnnotatedType.getDeclaredAnnotations(); - } - }; + return AnnotatedTypes.from( + Types.generateAnnotatedTypeWithoutAnnotation(genericComponentTypeWithGeneric), + resolveType, + currentAnnotatedType.getAnnotations(), + currentAnnotatedType.getDeclaredAnnotations(), + parentAnnotatedType + ); } public static AnnotatedType resolveWithTypeReferenceGenerics( diff --git a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/introspector/InvocationHandlerBuilder.java b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/introspector/InvocationHandlerBuilder.java new file mode 100644 index 000000000..bc126da68 --- /dev/null +++ b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/introspector/InvocationHandlerBuilder.java @@ -0,0 +1,30 @@ +package com.navercorp.fixturemonkey.api.introspector; + +import java.lang.reflect.InvocationHandler; +import java.util.Map; + +@SuppressWarnings("unused") +final class InvocationHandlerBuilder { + private final Map generatedValuesByMethodName; + + InvocationHandlerBuilder(Map generatedValuesByMethodName) { + this.generatedValuesByMethodName = generatedValuesByMethodName; + } + + void put(String methodName, Object value) { + generatedValuesByMethodName.put(methodName, value); + } + + InvocationHandler build() { + return (proxy, method, args) -> { + if (method.isDefault()) { + return InvocationHandler.invokeDefault(proxy, method, args); + } + return generatedValuesByMethodName.get(method.getName()); + }; + } + + boolean isEmpty() { + return generatedValuesByMethodName.isEmpty(); + } +} diff --git a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/type/AnnotatedTypes.java b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/type/AnnotatedTypes.java new file mode 100644 index 000000000..cd2eb670e --- /dev/null +++ b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/type/AnnotatedTypes.java @@ -0,0 +1,98 @@ +package com.navercorp.fixturemonkey.api.type; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedArrayType; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Type; +import java.util.Arrays; + +public final class AnnotatedTypes { + public static AnnotatedArrayType from( + AnnotatedType annotatedGenericComponentType, + Type type, + Annotation[] annotations, + Annotation[] declaredAnnotations, + AnnotatedType annotatedOwnerType + ) { + return new AnnotatedArrayType() { + @Override + public AnnotatedType getAnnotatedGenericComponentType() { + return annotatedGenericComponentType; + } + + @Override + public AnnotatedType getAnnotatedOwnerType() { + return annotatedOwnerType; + } + + @Override + public Type getType() { + return type; + } + + @Override + public T getAnnotation(Class annotationClass) { + return Arrays.stream(annotations) + .filter(it -> it.getClass() == annotationClass) + .findAny() + .map(annotationClass::cast) + .orElse(null); + } + + @Override + public Annotation[] getAnnotations() { + return annotations; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return declaredAnnotations; + } + }; + } + + public static AnnotatedParameterizedType from( + AnnotatedType[] annotatedActualTypeArguments, + Type type, + Annotation[] annotations, + Annotation[] declaredAnnotations, + AnnotatedType annotatedOwnerType + ) { + return new AnnotatedParameterizedType() { + @Override + public AnnotatedType[] getAnnotatedActualTypeArguments() { + return annotatedActualTypeArguments; + } + + @Override + public AnnotatedType getAnnotatedOwnerType() { + return annotatedOwnerType; + } + + @Override + public Type getType() { + return type; + } + + @Override + public T getAnnotation(Class annotationClass) { + return Arrays.stream(annotations) + .filter(it -> it.getClass() == annotationClass) + .findAny() + .map(annotationClass::cast) + .orElse(null); + } + + @Override + public Annotation[] getAnnotations() { + return annotations; + } + + @Override + public Annotation[] getDeclaredAnnotations() { + return declaredAnnotations; + } + }; + } +} diff --git a/fixture-monkey-junit-jupiter/build.gradle b/fixture-monkey-junit-jupiter/build.gradle index 965e1115d..021c5566b 100644 --- a/fixture-monkey-junit-jupiter/build.gradle +++ b/fixture-monkey-junit-jupiter/build.gradle @@ -5,7 +5,7 @@ plugins { id "com.github.spotbugs" version "4.7.6" id "jacoco" id "checkstyle" - id 'org.jetbrains.kotlin.jvm' version '1.6.20' + id 'org.jetbrains.kotlin.jvm' version "${KOTLIN_VERSION}" } dependencies { @@ -16,7 +16,7 @@ dependencies { testImplementation(project(":fixture-monkey-javax-validation")) testImplementation("org.assertj:assertj-core:3.22.0") testImplementation("org.projectlombok:lombok:1.18.24") - testImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.20") + testImplementation("org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}") testAnnotationProcessor("org.projectlombok:lombok:1.18.24") } diff --git a/fixture-monkey-kotlin/build.gradle b/fixture-monkey-kotlin/build.gradle index 5b0378f9e..c71451a78 100644 --- a/fixture-monkey-kotlin/build.gradle +++ b/fixture-monkey-kotlin/build.gradle @@ -20,7 +20,7 @@ dependencies { api(project(":fixture-monkey")) api("net.jqwik:jqwik-kotlin:${JQWIK_VERSION}") - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${KOTLIN_VERSION}") + implementation("org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}") implementation("org.jetbrains.kotlin:kotlin-reflect:${KOTLIN_VERSION}") testImplementation(project(":fixture-monkey-jackson")) diff --git a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt index b448b0cf7..56ea03309 100644 --- a/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt +++ b/fixture-monkey-kotlin/src/main/kotlin/com/navercorp/fixturemonkey/kotlin/type/KotlinTypes.kt @@ -18,6 +18,7 @@ package com.navercorp.fixturemonkey.kotlin.type +import com.navercorp.fixturemonkey.api.type.AnnotatedTypes import com.navercorp.fixturemonkey.api.type.Types import org.apiguardian.api.API import java.lang.reflect.AnnotatedParameterizedType @@ -96,21 +97,13 @@ fun getAnnotatedType(ownerType: AnnotatedType, kProperty: KProperty<*>): Annotat } val resolvedGenericsTypesArray = resolvedGenericsTypes.toTypedArray() - return object : AnnotatedParameterizedType { - override fun getAnnotatedActualTypeArguments(): Array = resolvedGenericsTypesArray - - override fun getType(): Type = resolveType - - override fun getAnnotations(): Array = annotationArray - - override fun getDeclaredAnnotations(): Array = annotationArray - - override fun getAnnotation(annotationClass: Class): T? = - @Suppress("UNCHECKED_CAST") - annotations - .find { it.annotationClass.java == annotationClass } - .let { it as T } - } + return AnnotatedTypes.from( + resolvedGenericsTypesArray, + resolveType, + annotationArray, + annotationArray, + ownerType + ) } internal class KotlinAnnotatedType( diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/InterfaceDefaultMethodTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/InterfaceDefaultMethodTest.java new file mode 100644 index 000000000..7d84349c1 --- /dev/null +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/InterfaceDefaultMethodTest.java @@ -0,0 +1,25 @@ +package com.navercorp.fixturemonkey.tests.java17; + +import static com.navercorp.fixturemonkey.tests.TestEnvironment.TEST_COUNT; +import static org.assertj.core.api.BDDAssertions.then; + +import org.junit.jupiter.api.RepeatedTest; + +import com.navercorp.fixturemonkey.FixtureMonkey; + +class InterfaceDefaultMethodTest { + private final static FixtureMonkey SUT = FixtureMonkey.create(); + + @RepeatedTest(TEST_COUNT) + void defaultMethod() { + String actual = SUT.giveMeOne(DefaultMethodInterface.class).defaultMethod(); + + then(actual).isEqualTo("test"); + } + + public interface DefaultMethodInterface { + default String defaultMethod() { + return "test"; + } + } +} diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java index 2d0a74c74..bbb98093d 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTest.java @@ -32,6 +32,7 @@ import com.navercorp.fixturemonkey.javax.validation.plugin.JavaxValidationPlugin; import com.navercorp.fixturemonkey.tests.java.AnonymousInstanceTestSpecs.AnnotatedInterface; import com.navercorp.fixturemonkey.tests.java.AnonymousInstanceTestSpecs.ContainerInterface; +import com.navercorp.fixturemonkey.tests.java.AnonymousInstanceTestSpecs.DefaultMethodInterface; import com.navercorp.fixturemonkey.tests.java.AnonymousInstanceTestSpecs.GetterInterface; import com.navercorp.fixturemonkey.tests.java.AnonymousInstanceTestSpecs.InheritedInterface; import com.navercorp.fixturemonkey.tests.java.AnonymousInstanceTestSpecs.InheritedInterfaceWithSameNameMethod; diff --git a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTestSpecs.java b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTestSpecs.java index 3f2475051..44c6e4233 100644 --- a/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTestSpecs.java +++ b/fixture-monkey-tests/java-tests/src/test/java/com/navercorp/fixturemonkey/tests/java/AnonymousInstanceTestSpecs.java @@ -68,4 +68,10 @@ public interface InheritedTwoInterface extends Interface, ContainerInterface { public interface NestedInheritedInterface extends InheritedInterfaceWithSameNameMethod, Interface { } + + public interface DefaultMethodInterface { + default String defaultMethod() { + return "test"; + } + } } diff --git a/fixture-monkey-tests/kotlin-concurrent-tests/build.gradle b/fixture-monkey-tests/kotlin-concurrent-tests/build.gradle index 88f230787..ce4d64843 100644 --- a/fixture-monkey-tests/kotlin-concurrent-tests/build.gradle +++ b/fixture-monkey-tests/kotlin-concurrent-tests/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${KOTLIN_VERSION}") + implementation("org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}") implementation("org.jetbrains.kotlin:kotlin-reflect:${KOTLIN_VERSION}") testImplementation(project(":fixture-monkey-kotlin")) diff --git a/fixture-monkey-tests/kotlin-tests/build.gradle b/fixture-monkey-tests/kotlin-tests/build.gradle index 9e1e37019..8e788279e 100644 --- a/fixture-monkey-tests/kotlin-tests/build.gradle +++ b/fixture-monkey-tests/kotlin-tests/build.gradle @@ -3,7 +3,7 @@ plugins { } dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:${KOTLIN_VERSION}") + implementation("org.jetbrains.kotlin:kotlin-stdlib:${KOTLIN_VERSION}") implementation("org.jetbrains.kotlin:kotlin-reflect:${KOTLIN_VERSION}") testImplementation(project(":fixture-monkey-kotlin")) diff --git a/fixture-monkey/build.gradle b/fixture-monkey/build.gradle index fc71e33a7..47bbf677e 100644 --- a/fixture-monkey/build.gradle +++ b/fixture-monkey/build.gradle @@ -7,6 +7,11 @@ plugins { id "checkstyle" id "me.champeau.jmh" version "0.6.6" id "org.gradle.test-retry" version "1.5.2" + id "me.champeau.mrjar" version "0.1.1" +} + +multiRelease { + targetVersions(8, 17) } dependencies { diff --git a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java index b4d6d903c..7c89abf89 100644 --- a/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java +++ b/fixture-monkey/src/test/java/com/navercorp/fixturemonkey/test/FixtureMonkeyTest.java @@ -23,7 +23,6 @@ import static org.assertj.core.api.BDDAssertions.thenNoException; import static org.assertj.core.api.BDDAssertions.thenThrownBy; -import java.net.URI; import java.time.Instant; import java.time.ZoneId; import java.util.AbstractMap.SimpleEntry; @@ -1361,14 +1360,6 @@ void applyFixedSize() { then(actual).allMatch(expectedElement::equals); } - @Property - void sampleUri() { - // when - URI actual = SUT.giveMeOne(URI.class); - - then(actual).isNotNull(); - } - @Property void sizeNotSetEmptyList() { // when