From ca5497549f3c49e9bc15a9e63e762c4a2b27014b Mon Sep 17 00:00:00 2001 From: Sam Barker Date: Mon, 2 Oct 2023 14:06:31 +1300 Subject: [PATCH] Allow the extension to inject into fields annotated with Junit annotations. Restricting to only the specific annotations was a little too restrictive. Signed-off-by: Sam Barker --- .../junit5ext/KafkaClusterExtension.java | 87 +++++++++---------- .../junit5ext/StaticFieldExtensionTest.java | 22 ++--- 2 files changed, 51 insertions(+), 58 deletions(-) diff --git a/junit5-extension/src/main/java/io/kroxylicious/testing/kafka/junit5ext/KafkaClusterExtension.java b/junit5-extension/src/main/java/io/kroxylicious/testing/kafka/junit5ext/KafkaClusterExtension.java index ee4a82c4..9bc446ae 100644 --- a/junit5-extension/src/main/java/io/kroxylicious/testing/kafka/junit5ext/KafkaClusterExtension.java +++ b/junit5-extension/src/main/java/io/kroxylicious/testing/kafka/junit5ext/KafkaClusterExtension.java @@ -5,10 +5,28 @@ */ package io.kroxylicious.testing.kafka.junit5ext; -import io.kroxylicious.testing.kafka.api.KafkaCluster; -import io.kroxylicious.testing.kafka.api.KafkaClusterConstraint; -import io.kroxylicious.testing.kafka.api.KafkaClusterProvisioningStrategy; -import io.kroxylicious.testing.kafka.api.KroxyliciousTestInfo; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.apache.kafka.clients.admin.Admin; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.KafkaConsumer; @@ -57,27 +75,10 @@ import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ReflectionUtils; -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Base64; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.ServiceLoader; -import java.util.UUID; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import io.kroxylicious.testing.kafka.api.KafkaCluster; +import io.kroxylicious.testing.kafka.api.KafkaClusterConstraint; +import io.kroxylicious.testing.kafka.api.KafkaClusterProvisioningStrategy; +import io.kroxylicious.testing.kafka.api.KroxyliciousTestInfo; import static java.lang.System.Logger.Level.TRACE; import static org.junit.platform.commons.support.ReflectionSupport.findFields; @@ -515,8 +516,8 @@ private static boolean supportsParameter(Parameter parameter) { return KafkaCluster.class.isAssignableFrom(type) || (isKafkaClient(type) && isCandidate(parameter)); } - private static boolean isCandidate(AnnotatedElement parameter) { - return noAnnotations(parameter) || isAnnotatedByExtensionAnnotation(parameter); + private static boolean isCandidate(AnnotatedElement annotatedElement) { + return noAnnotations(annotatedElement) || hasOnlySupportedAnnotations(annotatedElement); } private static boolean isKafkaClient(Class type) { @@ -527,20 +528,20 @@ private static boolean noAnnotations(AnnotatedElement parameter) { return parameter.getAnnotations().length == 0; } - private static boolean isAnnotatedByExtensionAnnotation(AnnotatedElement parameter) { - final Annotation[] annotations = parameter.getAnnotations(); - for (Annotation annotation : annotations) { - if (KafkaClusterConstraint.class.isAssignableFrom(annotation.annotationType())) { - return true; - } - if (Name.class.isAssignableFrom(annotation.annotationType())) { - return true; - } - if (KafkaCluster.class.isAssignableFrom(annotation.annotationType())) { - return true; + /** + * We want to avoid conflicts with annotations such as mockito's @Mock. However, maintaining a list of + * conflicting annotations would be mad. So it seems simpler to maintain a set of known safe annotations with which + * we can inject still inject. + */ + private static boolean hasOnlySupportedAnnotations(AnnotatedElement parameter) { + boolean supported = true; + for (Annotation annotation : parameter.getAnnotations()) { + final String canonicalName = annotation.annotationType().getCanonicalName(); + if (!canonicalName.startsWith("io.kroxylicious") && !canonicalName.startsWith("org.junit")) { + supported = false; } } - return false; + return supported; } private void injectInstanceFields(ExtensionContext context, Object instance) { @@ -1083,12 +1084,4 @@ private void assertSupportedType(String target, Class type) { } } - @FunctionalInterface - private interface ClientFactory { - X getClient(String description, - AnnotatedElement sourceElement, - Class type, - Type genericType, - ExtensionContext extensionContext); - } } diff --git a/junit5-extension/src/test/java/io/kroxylicious/testing/kafka/junit5ext/StaticFieldExtensionTest.java b/junit5-extension/src/test/java/io/kroxylicious/testing/kafka/junit5ext/StaticFieldExtensionTest.java index 7c48df5f..4b916296 100644 --- a/junit5-extension/src/test/java/io/kroxylicious/testing/kafka/junit5ext/StaticFieldExtensionTest.java +++ b/junit5-extension/src/test/java/io/kroxylicious/testing/kafka/junit5ext/StaticFieldExtensionTest.java @@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; @ExtendWith(KafkaClusterExtension.class) -public class StaticFieldExtensionTest extends AbstractExtensionTest { +class StaticFieldExtensionTest extends AbstractExtensionTest { @Order(1) @BrokerCluster(numBrokers = 1) @@ -39,7 +39,7 @@ public class StaticFieldExtensionTest extends AbstractExtensionTest { static AdminClient staticAdminClient; @Test - public void testKafkaClusterStaticField() + void testKafkaClusterStaticField() throws ExecutionException, InterruptedException { var dc = describeCluster(staticCluster.getKafkaClientConfiguration()); assertEquals(1, dc.nodes().get().size()); @@ -48,47 +48,47 @@ public void testKafkaClusterStaticField() } @Test - public void adminStaticField() throws ExecutionException, InterruptedException { + void adminStaticField() throws ExecutionException, InterruptedException { assertSameCluster(staticCluster, staticAdmin); } @Test - public void adminClientStaticField() throws ExecutionException, InterruptedException { + void adminClientStaticField() throws ExecutionException, InterruptedException { assertSameCluster(staticCluster, staticAdminClient); } @Test - public void adminParameter(Admin admin) throws ExecutionException, InterruptedException { + void adminParameter(Admin admin) throws ExecutionException, InterruptedException { assertSameCluster(staticCluster, admin); } @Test - public void adminClientParameter(AdminClient admin) throws ExecutionException, InterruptedException { + void adminClientParameter(AdminClient admin) throws ExecutionException, InterruptedException { assertSameCluster(staticCluster, admin); } @Test - public void kafkaAdminClientParameter(KafkaAdminClient admin) throws ExecutionException, InterruptedException { + void kafkaAdminClientParameter(KafkaAdminClient admin) throws ExecutionException, InterruptedException { assertSameCluster(staticCluster, admin); } @Test - public void producerParameter(Producer producer) throws ExecutionException, InterruptedException { + void producerParameter(Producer producer) throws ExecutionException, InterruptedException { doProducer(producer, "hello", "world"); } @Test - public void kafkaProducerParameter(KafkaProducer producer) throws ExecutionException, InterruptedException { + void kafkaProducerParameter(KafkaProducer producer) throws ExecutionException, InterruptedException { doProducer(producer, "hello", "world"); } @Test - public void consumerParameter(Consumer consumer) { + void consumerParameter(Consumer consumer) { doConsumer(consumer); } @Test - public void kafkaConsumerParameter(KafkaConsumer consumer) { + void kafkaConsumerParameter(KafkaConsumer consumer) { doConsumer(consumer); }