From 14a61d4f9ca6b535fa820bdcba7c6c5f06519a7f Mon Sep 17 00:00:00 2001 From: Holly Cummins Date: Tue, 8 Jul 2025 11:47:50 +0100 Subject: [PATCH] Adjust check for mock kube server to avoid need for class preloading --- .../NoQuarkusTestKubernetesClient.java | 18 +++++--- .../junit/classloading/FacadeClassLoader.java | 45 ++----------------- 2 files changed, 16 insertions(+), 47 deletions(-) diff --git a/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/NoQuarkusTestKubernetesClient.java b/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/NoQuarkusTestKubernetesClient.java index cc5b3b102f253..ef83e2139d190 100644 --- a/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/NoQuarkusTestKubernetesClient.java +++ b/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/NoQuarkusTestKubernetesClient.java @@ -1,6 +1,5 @@ package io.quarkus.kubernetes.client.deployment; -import java.util.Arrays; import java.util.function.BooleanSupplier; /** @@ -13,13 +12,22 @@ * to avoid starting a Kubernetes test container in such a case. */ class NoQuarkusTestKubernetesClient implements BooleanSupplier { - static final String IO_QUARKUS_TEST_KUBERNETES_CLIENT_PACKAGE = "io.quarkus.test.kubernetes.client"; - static final Boolean IO_QUARKUS_TEST_KUBERNETES_CLIENT_AVAILABLE = Arrays.stream(Package.getPackages()) - .map(Package::getName) - .anyMatch(p -> p.startsWith(IO_QUARKUS_TEST_KUBERNETES_CLIENT_PACKAGE)); + static final String IO_QUARKUS_TEST_KUBERNETES_CLIENT_PACKAGE_CLASS = "io.quarkus.test.kubernetes.client.AbstractKubernetesTestResource"; + // We cannot assume what order classes are loaded in, so check if a known class can be loaded rather than looking at what's already loaded + static final boolean IO_QUARKUS_TEST_KUBERNETES_CLIENT_AVAILABLE = isClassAvailable( + IO_QUARKUS_TEST_KUBERNETES_CLIENT_PACKAGE_CLASS); @Override public boolean getAsBoolean() { return !IO_QUARKUS_TEST_KUBERNETES_CLIENT_AVAILABLE; } + + private static boolean isClassAvailable(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } } diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/classloading/FacadeClassLoader.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/classloading/FacadeClassLoader.java index 8164fc3d22aed..b17e709b5042b 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/classloading/FacadeClassLoader.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/classloading/FacadeClassLoader.java @@ -323,8 +323,6 @@ public Class loadClass(String name) throws ClassNotFoundException { } if (isQuarkusTest && !isIntegrationTest) { - - preloadTestResourceClasses(inspectionClass); QuarkusClassLoader runtimeClassLoader = getQuarkusClassLoader(inspectionClass, profile); Class clazz = runtimeClassLoader.loadClass(name); @@ -334,14 +332,13 @@ public Class loadClass(String name) throws ClassNotFoundException { } } catch (NoSuchMethodException e) { - // TODO better handling of these - System.err.println("Could not get method " + e); + log.error("Could not get method " + e); throw new RuntimeException(e); } catch (InvocationTargetException e) { - System.err.println("Could not invoke " + e); + log.error("Could not invoke " + e); throw new RuntimeException(e); } catch (IllegalAccessException e) { - System.err.println("Could not access " + e); + log.error("Could not access " + e); throw new RuntimeException(e); } @@ -378,42 +375,6 @@ private boolean registersQuarkusTestExtensionWithExtendsWith(Class inspection } - /* - * What's this for? - * It's a bit like detecting the location in a privacy test or detecting the lab environment in an emissions test and then - * deciding how to behave. - * We're special-casing behaviour for a hard-coded selection of test packages. Yuck! - * TODO Hopefully, once https://github.com/quarkusio/quarkus/issues/45785 is done, it will not be needed. - * Some tests, especially in kubernetes-client and openshift-client, check config to decide whether to start a dev service. - * That happens at augmentation, which happens before test execution. - * In the old model, the test class would have already been loaded by JUnit first, and it would have had a chance to write - * config to the system properties. - * That config would influence whether dev services were started. - * TODO even without 45785 it might be nice to find a better way, perhaps rewriting the AbstractKubernetesTestResource test - * resource to work differently? - * - */ - private void preloadTestResourceClasses(Class fromCanary) { - try { - Class ca = (Class) peekingClassLoader - .loadClass("io.quarkus.test.common.QuarkusTestResource"); - List ans = AnnotationSupport.findRepeatableAnnotations(fromCanary, ca); - for (Annotation a : ans) { - Method m = a - .getClass() - .getMethod(VALUE); - Class resourceClass = (Class) m.invoke(a); - // Only do this hack for the resources we know need it, since it can cause failures in other areas - if (resourceClass.getName().contains("Kubernetes")) { - getParent().loadClass(resourceClass.getName()); - } - } - } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) { - // In some projects, these classes are not on the canary classpath. That's fine, we know there's nothing to preload. - log.debug("Canary classloader could not preload test resources:" + e); - } - } - private boolean registersQuarkusTestExtensionOnField(Class inspectionClass) { try {