From 94dc60822b2e6712535d4d1432b8e2bb4687c763 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Thu, 18 Dec 2025 14:08:32 +0100 Subject: [PATCH] Update testframework registry to explicitly declare dependencies in all suppliers (#44974) Closes #44947, Closes #40756 Signed-off-by: stianst --- .../admin/AdminClientFactorySupplier.java | 8 ++ .../admin/AdminClientSupplier.java | 13 +++ .../events/AbstractEventsSupplier.java | 8 ++ .../http/HttpClientSupplier.java | 8 ++ .../http/SimpleHttpSupplier.java | 9 +++ .../InfinispanExternalServerSupplier.java | 2 +- .../injection/AbstractInterceptorHelper.java | 4 +- .../injection/DefaultAnnotationProxy.java | 16 ++-- .../injection/DependenciesBuilder.java | 36 +++++++++ .../testframework/injection/Dependency.java | 13 +++ .../injection/DependencyGraphResolver.java | 74 +++++++++++++++++ .../injection/InstanceContext.java | 19 +++-- .../testframework/injection/Registry.java | 80 ++++++++----------- .../injection/RequestedInstance.java | 20 +++-- .../testframework/injection/Supplier.java | 5 +- .../predicates/DependencyPredicates.java | 14 ++++ .../predicates/InstanceContextPredicates.java | 23 ++++++ .../RequestedInstancePredicates.java | 14 ++++ .../TestFrameworkExecutorPredicates.java | 14 ++++ .../testframework/realm/ClientSupplier.java | 7 ++ .../testframework/realm/RealmSupplier.java | 10 +++ .../testframework/realm/UserSupplier.java | 9 +++ .../AbstractKeycloakServerSupplier.java | 58 +++++++++----- .../server/KeycloakUrlsSupplier.java | 9 +++ .../injection/DefaultAnnotationProxyTest.java | 9 +++ .../injection/mocks/MockChildSupplier.java | 9 +++ .../oauth/OAuthClientSupplier.java | 13 +++ .../oauth/OAuthIdentityProviderSupplier.java | 9 +++ .../testframework/oauth/TestAppSupplier.java | 9 +++ .../runonserver/RunOnServerSupplier.java | 12 +++ .../runonserver/TestClassServerSupplier.java | 9 +++ .../remote/timeoffset/TimeOffsetSupplier.java | 10 +++ .../testframework/ui/page/PageSupplier.java | 9 +++ 33 files changed, 473 insertions(+), 89 deletions(-) create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/DependenciesBuilder.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/Dependency.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/DependencyGraphResolver.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/DependencyPredicates.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/InstanceContextPredicates.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/RequestedInstancePredicates.java create mode 100644 test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/TestFrameworkExecutorPredicates.java diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientFactorySupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientFactorySupplier.java index e225ec885c5..7911ea337ce 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientFactorySupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientFactorySupplier.java @@ -1,9 +1,12 @@ package org.keycloak.testframework.admin; +import java.util.List; import javax.net.ssl.SSLContext; import org.keycloak.testframework.annotations.InjectAdminClientFactory; import org.keycloak.testframework.https.ManagedCertificates; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -11,6 +14,11 @@ import org.keycloak.testframework.server.KeycloakServer; public class AdminClientFactorySupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(KeycloakServer.class).add(ManagedCertificates.class).build(); + } + @Override public AdminClientFactory getValue(InstanceContext instanceContext) { KeycloakServer server = instanceContext.getDependency(KeycloakServer.class); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientSupplier.java index 2312a1dcd2c..a58b97e6b6f 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/admin/AdminClientSupplier.java @@ -1,5 +1,7 @@ package org.keycloak.testframework.admin; +import java.util.List; + import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.Keycloak; import org.keycloak.representations.idm.ClientRepresentation; @@ -8,6 +10,8 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testframework.TestFrameworkException; import org.keycloak.testframework.annotations.InjectAdminClient; import org.keycloak.testframework.config.Config; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; @@ -17,6 +21,15 @@ import org.keycloak.testframework.realm.ManagedUser; public class AdminClientSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + DependenciesBuilder builder = DependenciesBuilder.create(AdminClientFactory.class); + if (instanceContext.getAnnotation().mode().equals(InjectAdminClient.Mode.MANAGED_REALM)) { + builder.add(ManagedRealm.class); + } + return builder.build(); + } + @Override public Keycloak getValue(InstanceContext instanceContext) { InjectAdminClient annotation = instanceContext.getAnnotation(); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/events/AbstractEventsSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/events/AbstractEventsSupplier.java index 0bffc3c8780..8e56c4b8235 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/events/AbstractEventsSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/events/AbstractEventsSupplier.java @@ -1,7 +1,10 @@ package org.keycloak.testframework.events; import java.lang.annotation.Annotation; +import java.util.List; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; @@ -13,6 +16,11 @@ import org.keycloak.testframework.realm.RealmConfigInterceptor; @SuppressWarnings("rawtypes") public abstract class AbstractEventsSupplier implements Supplier, RealmConfigInterceptor { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(ManagedRealm.class, SupplierHelpers.getAnnotationField(instanceContext.getAnnotation(), "realmRef")).build(); + } + @Override public E getValue(InstanceContext instanceContext) { String realmRef = SupplierHelpers.getAnnotationField(instanceContext.getAnnotation(), "realmRef"); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/http/HttpClientSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/http/HttpClientSupplier.java index 2ab6ab731b4..20b3e146e75 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/http/HttpClientSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/http/HttpClientSupplier.java @@ -1,10 +1,13 @@ package org.keycloak.testframework.http; import java.io.IOException; +import java.util.List; import javax.net.ssl.SSLContext; import org.keycloak.testframework.annotations.InjectHttpClient; import org.keycloak.testframework.https.ManagedCertificates; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; @@ -17,6 +20,11 @@ import org.apache.http.impl.client.HttpClientBuilder; public class HttpClientSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(ManagedCertificates.class).build(); + } + @Override public HttpClient getValue(InstanceContext instanceContext) { HttpClientBuilder builder = HttpClientBuilder.create(); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/http/SimpleHttpSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/http/SimpleHttpSupplier.java index 8914e6a3708..e83aa0272eb 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/http/SimpleHttpSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/http/SimpleHttpSupplier.java @@ -1,7 +1,11 @@ package org.keycloak.testframework.http; +import java.util.List; + import org.keycloak.http.simple.SimpleHttp; import org.keycloak.testframework.annotations.InjectSimpleHttp; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -10,6 +14,11 @@ import org.apache.http.client.HttpClient; public class SimpleHttpSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(HttpClient.class).build(); + } + @Override public SimpleHttp getValue(InstanceContext instanceContext) { HttpClient httpClient = instanceContext.getDependency(HttpClient.class); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/infinispan/InfinispanExternalServerSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/infinispan/InfinispanExternalServerSupplier.java index e378353e426..ebe191a2b9e 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/infinispan/InfinispanExternalServerSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/infinispan/InfinispanExternalServerSupplier.java @@ -34,7 +34,7 @@ public class InfinispanExternalServerSupplier implements Supplier a, RequestedInstance b) { - return a.getSupplier().getRef(a.getAnnotation()).equals(b.getSupplier().getRef(a.getAnnotation())); + return true; } @Override diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/AbstractInterceptorHelper.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/AbstractInterceptorHelper.java index bb86497889c..dc1908c46e6 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/AbstractInterceptorHelper.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/AbstractInterceptorHelper.java @@ -22,9 +22,9 @@ public abstract class AbstractInterceptorHelper { value = intercept(value, interception.supplier, interception.existingInstance); registry.getLogger().logIntercepted(value, interception.supplier); if (interception.existingInstance != null) { - interception.existingInstance.registerDependency(instanceContext); + interception.existingInstance.registerDependent(instanceContext); } else { - interception.requestedInstance.registerDependency(instanceContext); + interception.requestedInstance.registerDependent(instanceContext); } } return value; diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/DefaultAnnotationProxy.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/DefaultAnnotationProxy.java index aa81180214e..363030a1872 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/DefaultAnnotationProxy.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/DefaultAnnotationProxy.java @@ -9,13 +9,17 @@ public class DefaultAnnotationProxy implements InvocationHandler { private final Class annotationClass; private final String ref; - public DefaultAnnotationProxy(Class annotationClass, String ref) { - this.annotationClass = annotationClass; - this.ref = ref; + public static S proxy(Class annotationClass, String ref) { + // Annotations can't have a null default value, hence we use an empty string instead + if (ref == null) { + ref = ""; + } + return (S) Proxy.newProxyInstance(DefaultAnnotationProxy.class.getClassLoader(), new Class[]{annotationClass}, new DefaultAnnotationProxy(annotationClass, ref)); } - public static S proxy(Class annotationClass, String ref) { - return (S) Proxy.newProxyInstance(DefaultAnnotationProxy.class.getClassLoader(), new Class[]{annotationClass}, new DefaultAnnotationProxy(annotationClass, ref)); + private DefaultAnnotationProxy(Class annotationClass, String ref) { + this.annotationClass = annotationClass; + this.ref = ref; } @Override @@ -23,7 +27,7 @@ public class DefaultAnnotationProxy implements InvocationHandler { if (method.getName().equals("annotationType")) { return annotationClass; } else if (method.getName().equals("ref")) { - return ref; + return ref != null ? ref : ""; } else { return annotationClass.getMethod(method.getName()).getDefaultValue(); } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/DependenciesBuilder.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/DependenciesBuilder.java new file mode 100644 index 00000000000..cccfe6f7ad6 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/DependenciesBuilder.java @@ -0,0 +1,36 @@ +package org.keycloak.testframework.injection; + +import java.util.LinkedList; +import java.util.List; + +public class DependenciesBuilder { + + public static DependenciesBuilder create(Class valueType) { + return new DependenciesBuilder().add(valueType); + } + + public static DependenciesBuilder create(Class valueType, String ref) { + return new DependenciesBuilder().add(valueType, ref); + } + + private final List dependencies; + + public DependenciesBuilder add(Class valueType) { + dependencies.add(new Dependency(valueType, null)); + return this; + } + + public DependenciesBuilder add(Class valueType, String ref) { + dependencies.add(new Dependency(valueType, ref)); + return this; + } + + public DependenciesBuilder() { + this.dependencies = new LinkedList<>(); + } + + public List build() { + return dependencies; + } + +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/Dependency.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/Dependency.java new file mode 100644 index 00000000000..5455fbea3bf --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/Dependency.java @@ -0,0 +1,13 @@ +package org.keycloak.testframework.injection; + +public record Dependency(Class valueType, String ref) { + + public Dependency { + ref = StringUtil.convertEmptyToNull(ref); + } + + @Override + public String toString() { + return valueType.getSimpleName() + ":" + ref; + } +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/DependencyGraphResolver.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/DependencyGraphResolver.java new file mode 100644 index 00000000000..14ad8354bae --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/DependencyGraphResolver.java @@ -0,0 +1,74 @@ +package org.keycloak.testframework.injection; + +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.keycloak.testframework.injection.predicates.RequestedInstancePredicates; + +import org.jboss.logging.Logger; + +public class DependencyGraphResolver { + + private static final Logger log = Logger.getLogger(DependencyGraphResolver.class); + + private final Registry registry; + private final List> missingInstances; + + private Set visited = new HashSet<>(); + private Set visiting = new HashSet<>(); + + public DependencyGraphResolver(Registry registry) { + this.registry = registry; + this.missingInstances = new LinkedList<>(); + + for (RequestedInstance requestedInstance : registry.getRequestedInstances()) { + List dependencies = requestedInstance.getSupplier().getDependencies(requestedInstance); + requestedInstance.setDeclaredDependencies(dependencies); + for (Dependency dependency : dependencies) { + scan(dependency); + } + } + } + + public List> getMissingInstances() { + return missingInstances; + } + + private void scan(Dependency dependency) { + if (visited.contains(dependency)) { + log.tracev("Skipping {0} already scanned", dependency); + } else { + log.tracev("Scanning dependency {0}", dependency); + } + + if (visiting.contains(dependency)) { + throw new RuntimeException("Dependency cycle detected in " + visiting.stream().map(Dependency::toString).collect(Collectors.joining(", "))); + } + + visiting.add(dependency); + + RequestedInstance matchingInstance = registry.getRequestedInstances().stream().filter(RequestedInstancePredicates.matches(dependency.valueType(), dependency.ref())).findFirst().orElse(null); + if (matchingInstance == null) { + matchingInstance = missingInstances.stream().filter(RequestedInstancePredicates.matches(dependency.valueType(), dependency.ref())).findFirst().orElse(null); + } + + if (matchingInstance == null) { + Supplier supplier = registry.getExtensions().findSupplierByType(dependency.valueType()); + Annotation defaultAnnotation = DefaultAnnotationProxy.proxy(supplier.getAnnotationClass(), dependency.ref()); + matchingInstance = registry.createRequestedInstance(new Annotation[]{ defaultAnnotation }, dependency.valueType()); + missingInstances.add(matchingInstance); + } + + List dependencies = matchingInstance.getSupplier().getDependencies(matchingInstance); + matchingInstance.setDeclaredDependencies(dependencies); + + dependencies.forEach(this::scan); + + visiting.remove(dependency); + visited.add(dependency); + } +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/InstanceContext.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/InstanceContext.java index 7134d45b999..e5d4c600be7 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/InstanceContext.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/InstanceContext.java @@ -3,6 +3,7 @@ package org.keycloak.testframework.injection; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -12,14 +13,15 @@ public class InstanceContext { private final Registry registry; private final Supplier supplier; private final A annotation; - private final Set> dependencies = new HashSet<>(); + private final Set> dependents = new HashSet<>(); private T value; private Class requestedValueType; private LifeCycle lifeCycle; private final String ref; private final Map notes = new HashMap<>(); + private final List declaredDependencies; - public InstanceContext(int instanceId, Registry registry, Supplier supplier, A annotation, Class requestedValueType) { + public InstanceContext(int instanceId, Registry registry, Supplier supplier, A annotation, Class requestedValueType, List declaredDependencies) { this.instanceId = instanceId != -1 ? instanceId : hashCode(); this.registry = registry; this.supplier = supplier; @@ -27,6 +29,7 @@ public class InstanceContext { this.requestedValueType = requestedValueType; this.lifeCycle = supplier.getLifeCycle(annotation); this.ref = StringUtil.convertEmptyToNull(supplier.getRef(annotation)); + this.declaredDependencies = declaredDependencies; } public int getInstanceId() { @@ -73,12 +76,16 @@ public class InstanceContext { return annotation; } - public Set> getDependencies() { - return dependencies; + public Set> getDependents() { + return dependents; } - public void registerDependency(InstanceContext instanceContext) { - dependencies.add(instanceContext); + public List getDeclaredDependencies() { + return declaredDependencies; + } + + public void registerDependent(InstanceContext instanceContext) { + dependents.add(instanceContext); } public void addNote(String key, Object value) { diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/Registry.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/Registry.java index b9c91df1260..b158d40561b 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/Registry.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/Registry.java @@ -11,6 +11,10 @@ import java.util.Objects; import java.util.Set; import org.keycloak.testframework.TestFrameworkExecutor; +import org.keycloak.testframework.injection.predicates.DependencyPredicates; +import org.keycloak.testframework.injection.predicates.InstanceContextPredicates; +import org.keycloak.testframework.injection.predicates.RequestedInstancePredicates; +import org.keycloak.testframework.injection.predicates.TestFrameworkExecutorPredicates; import org.keycloak.testframework.server.KeycloakServer; import org.junit.jupiter.api.extension.ExtensionContext; @@ -37,6 +41,10 @@ public class Registry implements ExtensionContext.Store.CloseableResource { return logger; } + Extensions getExtensions() { + return extensions; + } + public ExtensionContext getCurrentContext() { return currentContext; } @@ -47,6 +55,12 @@ public class Registry implements ExtensionContext.Store.CloseableResource { public T getDependency(Class typeClass, String ref, InstanceContext dependent) { ref = StringUtil.convertEmptyToNull(ref); + + List declaredDependencies = dependent.getDeclaredDependencies(); + if (declaredDependencies.stream().noneMatch(DependencyPredicates.matches(typeClass, ref))) { + throw new RuntimeException("Tried to retrieve non-declared dependency " + typeClass.getSimpleName() + ":" + ref); + } + T dependency; dependency = getDeployedDependency(typeClass, ref, dependent); if (dependency != null) { @@ -55,11 +69,6 @@ public class Registry implements ExtensionContext.Store.CloseableResource { dependency = getRequestedDependency(typeClass, ref, dependent); if (dependency != null) { return dependency; - } else { - dependency = getUnConfiguredDependency(typeClass, ref, dependent); - if (dependency != null) { - return dependency; - } } } @@ -77,7 +86,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource { private T getDeployedDependency(Class typeClass, String ref, InstanceContext dependent) { InstanceContext dependency = getDeployedInstance(typeClass, ref); if (dependency != null) { - dependency.registerDependency(dependent); + dependency.registerDependent(dependent); logger.logDependencyInjection(dependent, dependency, RegistryLogger.InjectionType.EXISTING); @@ -89,9 +98,9 @@ public class Registry implements ExtensionContext.Store.CloseableResource { private T getRequestedDependency(Class typeClass, String ref, InstanceContext dependent) { RequestedInstance requestedDependency = getRequestedInstance(typeClass, ref); if (requestedDependency != null) { - InstanceContext dependency = new InstanceContext(requestedDependency.getInstanceId(), this, requestedDependency.getSupplier(), requestedDependency.getAnnotation(), requestedDependency.getValueType()); + InstanceContext dependency = new InstanceContext(requestedDependency.getInstanceId(), this, requestedDependency.getSupplier(), requestedDependency.getAnnotation(), requestedDependency.getValueType(), requestedDependency.getDeclaredDependencies()); dependency.setValue(requestedDependency.getSupplier().getValue(dependency)); - dependency.registerDependency(dependent); + dependency.registerDependent(dependent); deployedInstances.add(dependency); requestedInstances.remove(requestedDependency); @@ -103,22 +112,6 @@ public class Registry implements ExtensionContext.Store.CloseableResource { return null; } - private T getUnConfiguredDependency(Class typeClass, String ref, InstanceContext dependent) { - InstanceContext dependency; - Supplier supplier = extensions.findSupplierByType(typeClass); - Annotation defaultAnnotation = DefaultAnnotationProxy.proxy(supplier.getAnnotationClass(), ref); - dependency = new InstanceContext(-1, this, supplier, defaultAnnotation, typeClass); - - dependency.registerDependency(dependent); - dependency.setValue(supplier.getValue(dependency)); - - deployedInstances.add(dependency); - - logger.logDependencyInjection(dependent, dependency, RegistryLogger.InjectionType.UN_CONFIGURED); - - return (T) dependency.getValue(); - } - public void beforeEach(Object testInstance, Method testMethod) { findRequestedInstances(testInstance, testMethod); destroyIncompatibleInstances(); @@ -178,16 +171,9 @@ public class Registry implements ExtensionContext.Store.CloseableResource { } } - List dependencies = requestedInstances.stream().flatMap(r -> r.getSupplier().getDependencies().getList().stream()).toList(); - for (RequiredDependencies.RequiredDependency dependency : dependencies) { - boolean dependencyRequested = requestedInstances.stream().anyMatch(r -> r.getValueType().equals(dependency.valueType()) && Objects.equals(r.getRef(), dependency.ref())); - if (!dependencyRequested) { - Supplier supplier = extensions.findSupplierByType(dependency.valueType()); - Annotation defaultAnnotation = DefaultAnnotationProxy.proxy(supplier.getAnnotationClass(), dependency.ref()); - RequestedInstance requestDependency = createRequestedInstance(new Annotation[]{ defaultAnnotation }, dependency.valueType()); - requestedInstances.add(requestDependency); - } - } + DependencyGraphResolver dependencyGraphResolver = new DependencyGraphResolver(this); + List> missingInstances = dependencyGraphResolver.getMissingInstances(); + requestedInstances.addAll(missingInstances); logger.logRequestedInstances(requestedInstances); } @@ -225,13 +211,13 @@ public class Registry implements ExtensionContext.Store.CloseableResource { RequestedInstance requestedInstance = requestedInstances.remove(0); if (getDeployedInstance(requestedInstance) == null) { - InstanceContext instance = new InstanceContext(requestedInstance.getInstanceId(), this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType()); + InstanceContext instance = new InstanceContext(requestedInstance.getInstanceId(), this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType(), requestedInstance.getDeclaredDependencies()); instance.setValue(requestedInstance.getSupplier().getValue(instance)); deployedInstances.add(instance); - if (!requestedInstance.getDependencies().isEmpty()) { - Set> dependencies = requestedInstance.getDependencies(); - dependencies.forEach(instance::registerDependency); + if (!requestedInstance.getDependents().isEmpty()) { + Set> dependencies = requestedInstance.getDependents(); + dependencies.forEach(instance::registerDependent); } logger.logCreatedInstance(requestedInstance, instance); @@ -251,16 +237,16 @@ public class Registry implements ExtensionContext.Store.CloseableResource { public void afterAll() { logger.logAfterAll(); - List> destroy = deployedInstances.stream().filter(i -> i.getLifeCycle().equals(LifeCycle.CLASS)).toList(); + List> destroy = deployedInstances.stream().filter(InstanceContextPredicates.hasLifeCycle(LifeCycle.CLASS)).toList(); destroy.forEach(this::destroy); } public void afterEach() { logger.logAfterEach(); - List> destroy = deployedInstances.stream().filter(i -> i.getLifeCycle().equals(LifeCycle.METHOD)).toList(); + List> destroy = deployedInstances.stream().filter(InstanceContextPredicates.hasLifeCycle(LifeCycle.METHOD)).toList(); destroy.forEach(this::destroy); - List> cleanup = deployedInstances.stream().filter(i -> i.getValue() instanceof ManagedTestResource).toList(); + List> cleanup = deployedInstances.stream().filter(InstanceContextPredicates.isInstanceof(ManagedTestResource.class)).toList(); for (InstanceContext c : cleanup) { ManagedTestResource managedTestResource = (ManagedTestResource) c.getValue(); if (managedTestResource.isDirty()) { @@ -283,7 +269,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource { return extensions.getSuppliers(); } - private RequestedInstance createRequestedInstance(Annotation[] annotations, Class valueType) { + RequestedInstance createRequestedInstance(Annotation[] annotations, Class valueType) { if (annotations != null) { for (Annotation annotation : annotations) { Supplier supplier = extensions.findSupplierByAnnotation(annotation); @@ -294,7 +280,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource { } else { Supplier supplier = extensions.findSupplierByType(valueType); if (supplier != null) { - Annotation defaultAnnotation = DefaultAnnotationProxy.proxy(supplier.getAnnotationClass(), ""); + Annotation defaultAnnotation = DefaultAnnotationProxy.proxy(supplier.getAnnotationClass(), null); return new RequestedInstance(supplier, defaultAnnotation, valueType); } } @@ -318,7 +304,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource { private void destroy(InstanceContext instanceContext) { boolean removed = deployedInstances.remove(instanceContext); if (removed) { - Set dependencies = instanceContext.getDependencies(); + Set dependencies = instanceContext.getDependents(); dependencies.forEach(this::destroy); instanceContext.getSupplier().close(instanceContext); @@ -347,13 +333,13 @@ public class Registry implements ExtensionContext.Store.CloseableResource { private InstanceContext getDeployedInstance(Class typeClass, String ref) { return deployedInstances.stream() - .filter(i -> i.getSupplier().getValueType().equals(typeClass) && Objects.equals(i.getRef(), ref)) + .filter(InstanceContextPredicates.matches(typeClass, ref)) .findFirst().orElse(null); } private RequestedInstance getRequestedInstance(Class typeClass, String ref) { return requestedInstances.stream() - .filter(i -> i.getSupplier().getValueType().equals(typeClass) && Objects.equals(i.getRef(), ref)) + .filter(RequestedInstancePredicates.matches(typeClass, ref)) .findFirst().orElse(null); } @@ -364,7 +350,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource { } private TestFrameworkExecutor getExecutor(Method testMethod) { - return extensions.getTestFrameworkExecutors().stream().filter(e -> e.shouldExecute(testMethod)).findFirst().orElse(null); + return extensions.getTestFrameworkExecutors().stream().filter(TestFrameworkExecutorPredicates.shouldExecute(testMethod)).findFirst().orElse(null); } private static class RequestedInstanceComparator implements Comparator { diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/RequestedInstance.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/RequestedInstance.java index 90e5fd7246d..1c8021604eb 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/RequestedInstance.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/RequestedInstance.java @@ -2,6 +2,7 @@ package org.keycloak.testframework.injection; import java.lang.annotation.Annotation; import java.util.HashSet; +import java.util.List; import java.util.Set; public class RequestedInstance { @@ -9,10 +10,11 @@ public class RequestedInstance { private final int instanceId; private final Supplier supplier; private final A annotation; - private final Set> dependencies = new HashSet<>(); + private final Set> dependents = new HashSet<>(); private final Class valueType; private final LifeCycle lifeCycle; private final String ref; + private List declaredDependencies; public RequestedInstance(Supplier supplier, A annotation, Class valueType) { this.instanceId = this.hashCode(); @@ -47,11 +49,19 @@ public class RequestedInstance { return ref; } - public void registerDependency(InstanceContext instanceContext) { - dependencies.add(instanceContext); + public void registerDependent(InstanceContext instanceContext) { + dependents.add(instanceContext); } - public Set> getDependencies() { - return dependencies; + public Set> getDependents() { + return dependents; + } + + public List getDeclaredDependencies() { + return declaredDependencies; + } + + public void setDeclaredDependencies(List declaredDependencies) { + this.declaredDependencies = declaredDependencies; } } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/Supplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/Supplier.java index a34232a6986..94bcdd8f052 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/injection/Supplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/Supplier.java @@ -1,6 +1,7 @@ package org.keycloak.testframework.injection; import java.lang.annotation.Annotation; +import java.util.List; public interface Supplier { @@ -44,8 +45,8 @@ public interface Supplier { return SupplierOrder.DEFAULT; } - default RequiredDependencies getDependencies() { - return RequiredDependencies.none(); + default List getDependencies(RequestedInstance instanceContext) { + return List.of(); } } diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/DependencyPredicates.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/DependencyPredicates.java new file mode 100644 index 00000000000..4e4c3642c88 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/DependencyPredicates.java @@ -0,0 +1,14 @@ +package org.keycloak.testframework.injection.predicates; + +import java.util.Objects; +import java.util.function.Predicate; + +import org.keycloak.testframework.injection.Dependency; + +public interface DependencyPredicates { + + static Predicate matches(Class typeClass, String ref) { + return d -> d.valueType().equals(typeClass) && Objects.equals(d.ref(), ref); + } + +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/InstanceContextPredicates.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/InstanceContextPredicates.java new file mode 100644 index 00000000000..79439c284bb --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/InstanceContextPredicates.java @@ -0,0 +1,23 @@ +package org.keycloak.testframework.injection.predicates; + +import java.util.Objects; +import java.util.function.Predicate; + +import org.keycloak.testframework.injection.InstanceContext; +import org.keycloak.testframework.injection.LifeCycle; + +public interface InstanceContextPredicates { + + static Predicate> hasLifeCycle(LifeCycle lifeCycle) { + return i -> i.getLifeCycle().equals(lifeCycle); + } + + static Predicate> isInstanceof(Class valueTypeClass) { + return i -> valueTypeClass.isInstance(i.getValue()); + } + + static Predicate> matches(Class typeClass, String ref) { + return i -> i.getSupplier().getValueType().equals(typeClass) && Objects.equals(i.getRef(), ref); + } + +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/RequestedInstancePredicates.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/RequestedInstancePredicates.java new file mode 100644 index 00000000000..2c0fbae6f91 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/RequestedInstancePredicates.java @@ -0,0 +1,14 @@ +package org.keycloak.testframework.injection.predicates; + +import java.util.Objects; +import java.util.function.Predicate; + +import org.keycloak.testframework.injection.RequestedInstance; + +public interface RequestedInstancePredicates { + + static Predicate> matches(Class typeClass, String ref) { + return r -> r.getSupplier().getValueType().equals(typeClass) && Objects.equals(r.getRef(), ref); + } + +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/TestFrameworkExecutorPredicates.java b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/TestFrameworkExecutorPredicates.java new file mode 100644 index 00000000000..f94694656c0 --- /dev/null +++ b/test-framework/core/src/main/java/org/keycloak/testframework/injection/predicates/TestFrameworkExecutorPredicates.java @@ -0,0 +1,14 @@ +package org.keycloak.testframework.injection.predicates; + +import java.lang.reflect.Method; +import java.util.function.Predicate; + +import org.keycloak.testframework.TestFrameworkExecutor; + +public interface TestFrameworkExecutorPredicates { + + static Predicate shouldExecute(Method method) { + return r -> r.shouldExecute(method); + } + +} diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java index 511f6c97428..b856adf015d 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/realm/ClientSupplier.java @@ -9,6 +9,8 @@ import jakarta.ws.rs.core.Response.Status; import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.testframework.annotations.InjectClient; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -17,6 +19,11 @@ import org.keycloak.testframework.util.ApiUtil; public class ClientSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(ManagedRealm.class, instanceContext.getAnnotation().realmRef()).build(); + } + @Override public ManagedClient getValue(InstanceContext instanceContext) { ManagedRealm realm = instanceContext.getDependency(ManagedRealm.class, instanceContext.getAnnotation().realmRef()); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java index cc0d413a2fb..82922651dd2 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/realm/RealmSupplier.java @@ -1,10 +1,14 @@ package org.keycloak.testframework.realm; +import java.util.List; + import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.testframework.annotations.InjectRealm; import org.keycloak.testframework.injection.AbstractInterceptorHelper; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.Registry; import org.keycloak.testframework.injection.RequestedInstance; @@ -15,6 +19,12 @@ import org.keycloak.testframework.server.KeycloakServer; public class RealmSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(KeycloakServer.class) + .add(Keycloak.class, "bootstrap-client").build(); + } + @Override public ManagedRealm getValue(InstanceContext instanceContext) { KeycloakServer server = instanceContext.getDependency(KeycloakServer.class); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/realm/UserSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/realm/UserSupplier.java index f72fd04b4b0..a903dfea280 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/realm/UserSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/realm/UserSupplier.java @@ -1,5 +1,7 @@ package org.keycloak.testframework.realm; +import java.util.List; + import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; @@ -7,6 +9,8 @@ import jakarta.ws.rs.core.Response.Status; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testframework.annotations.InjectUser; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -17,6 +21,11 @@ public class UserSupplier implements Supplier { private static final String USER_UUID_KEY = "userUuid"; + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(ManagedRealm.class, instanceContext.getAnnotation().realmRef()).build(); + } + @Override public ManagedUser getValue(InstanceContext instanceContext) { ManagedRealm realm = instanceContext.getDependency(ManagedRealm.class, instanceContext.getAnnotation().realmRef()); diff --git a/test-framework/core/src/main/java/org/keycloak/testframework/server/AbstractKeycloakServerSupplier.java b/test-framework/core/src/main/java/org/keycloak/testframework/server/AbstractKeycloakServerSupplier.java index 0cf98be61e4..620c3b59eb0 100644 --- a/test-framework/core/src/main/java/org/keycloak/testframework/server/AbstractKeycloakServerSupplier.java +++ b/test-framework/core/src/main/java/org/keycloak/testframework/server/AbstractKeycloakServerSupplier.java @@ -1,16 +1,19 @@ package org.keycloak.testframework.server; +import java.util.List; + import org.keycloak.testframework.annotations.KeycloakIntegrationTest; import org.keycloak.testframework.config.Config; import org.keycloak.testframework.database.TestDatabase; import org.keycloak.testframework.https.ManagedCertificates; import org.keycloak.testframework.infinispan.InfinispanServer; import org.keycloak.testframework.injection.AbstractInterceptorHelper; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.Registry; import org.keycloak.testframework.injection.RequestedInstance; -import org.keycloak.testframework.injection.RequiredDependencies; import org.keycloak.testframework.injection.Supplier; import org.keycloak.testframework.injection.SupplierHelpers; import org.keycloak.testframework.injection.SupplierOrder; @@ -20,23 +23,25 @@ import org.jboss.logging.Logger; public abstract class AbstractKeycloakServerSupplier implements Supplier { @Override - public KeycloakServer getValue(InstanceContext instanceContext) { - KeycloakIntegrationTest annotation = instanceContext.getAnnotation(); - KeycloakServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config()); + public List getDependencies(RequestedInstance instanceContext) { + KeycloakServerConfigBuilder command = getKeycloakServerConfigBuilder(instanceContext.getAnnotation()); - KeycloakServerConfigBuilder command = KeycloakServerConfigBuilder.startDev() - .bootstrapAdminClient(Config.getAdminClientId(), Config.getAdminClientSecret()) - .bootstrapAdminUser(Config.getAdminUsername(), Config.getAdminPassword()); - - command.log().handlers(KeycloakServerConfigBuilder.LogHandlers.CONSOLE); - - String supplierConfig = Config.getSupplierConfig(KeycloakServer.class); - if (supplierConfig != null) { - KeycloakServerConfig serverConfigOverride = SupplierHelpers.getInstance(supplierConfig); - serverConfigOverride.configure(command); + DependenciesBuilder builder = DependenciesBuilder.create(ManagedCertificates.class); + if (requiresDatabase()) { + builder.add(TestDatabase.class); } - command = serverConfig.configure(command); + if (command.isExternalInfinispanEnabled()) { + builder.add(InfinispanServer.class); + } + + return builder.build(); + } + + @Override + public KeycloakServer getValue(InstanceContext instanceContext) { + + KeycloakServerConfigBuilder command = getKeycloakServerConfigBuilder(instanceContext.getAnnotation()); // Database startup and Keycloak connection setup if (requiresDatabase()) { @@ -81,6 +86,24 @@ public abstract class AbstractKeycloakServerSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(KeycloakServer.class).build(); + } + @Override public KeycloakUrls getValue(InstanceContext instanceContext) { KeycloakServer server = instanceContext.getDependency(KeycloakServer.class); diff --git a/test-framework/core/src/test/java/org/keycloak/testframework/injection/DefaultAnnotationProxyTest.java b/test-framework/core/src/test/java/org/keycloak/testframework/injection/DefaultAnnotationProxyTest.java index 99a8e0f57c1..9d74f00848f 100644 --- a/test-framework/core/src/test/java/org/keycloak/testframework/injection/DefaultAnnotationProxyTest.java +++ b/test-framework/core/src/test/java/org/keycloak/testframework/injection/DefaultAnnotationProxyTest.java @@ -21,6 +21,15 @@ public class DefaultAnnotationProxyTest { Assertions.assertEquals("else", proxy.something()); } + @Test + public void testEmptyRefConvertedToEmptyString() { + MockAnnotation proxy = DefaultAnnotationProxy.proxy(MockAnnotation.class, null); + Assertions.assertEquals(LifeCycle.CLASS, proxy.lifecycle()); + Assertions.assertEquals(LinkedList.class, proxy.config()); + Assertions.assertEquals("", proxy.ref()); + Assertions.assertEquals("else", proxy.something()); + } + @Test public void testCustomRef() { MockAnnotation proxy = DefaultAnnotationProxy.proxy(MockAnnotation.class, "myref"); diff --git a/test-framework/core/src/test/java/org/keycloak/testframework/injection/mocks/MockChildSupplier.java b/test-framework/core/src/test/java/org/keycloak/testframework/injection/mocks/MockChildSupplier.java index ccf2d4c7a4b..9b8b122786e 100644 --- a/test-framework/core/src/test/java/org/keycloak/testframework/injection/mocks/MockChildSupplier.java +++ b/test-framework/core/src/test/java/org/keycloak/testframework/injection/mocks/MockChildSupplier.java @@ -1,5 +1,9 @@ package org.keycloak.testframework.injection.mocks; +import java.util.List; + +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; @@ -13,6 +17,11 @@ public class MockChildSupplier implements Supplier getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(MockParentValue.class, instanceContext.getAnnotation().parentRef()).build(); + } + @Override public MockChildValue getValue(InstanceContext instanceContext) { MockParentValue mockParentValue = instanceContext.getDependency(MockParentValue.class, instanceContext.getAnnotation().parentRef()); diff --git a/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthClientSupplier.java b/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthClientSupplier.java index fcc097fea90..7c6793b46b9 100644 --- a/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthClientSupplier.java +++ b/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthClientSupplier.java @@ -1,6 +1,10 @@ package org.keycloak.testframework.oauth; +import java.util.List; + import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -18,6 +22,15 @@ import org.apache.http.impl.client.CloseableHttpClient; public class OAuthClientSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(KeycloakUrls.class) + .add(HttpClient.class) + .add(ManagedWebDriver.class) + .add(TestApp.class) + .add(ManagedRealm.class, instanceContext.getAnnotation().realmRef()).build(); + } + @Override public OAuthClient getValue(InstanceContext instanceContext) { InjectOAuthClient annotation = instanceContext.getAnnotation(); diff --git a/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthIdentityProviderSupplier.java b/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthIdentityProviderSupplier.java index fe273885b38..022ed982a09 100644 --- a/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthIdentityProviderSupplier.java +++ b/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/OAuthIdentityProviderSupplier.java @@ -1,5 +1,9 @@ package org.keycloak.testframework.oauth; +import java.util.List; + +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -10,6 +14,11 @@ import com.sun.net.httpserver.HttpServer; public class OAuthIdentityProviderSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(HttpServer.class).build(); + } + @Override public OAuthIdentityProvider getValue(InstanceContext instanceContext) { HttpServer httpServer = instanceContext.getDependency(HttpServer.class); diff --git a/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/TestAppSupplier.java b/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/TestAppSupplier.java index 36f52131d27..207c682721e 100644 --- a/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/TestAppSupplier.java +++ b/test-framework/oauth/src/main/java/org/keycloak/testframework/oauth/TestAppSupplier.java @@ -1,5 +1,9 @@ package org.keycloak.testframework.oauth; +import java.util.List; + +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -9,6 +13,11 @@ import com.sun.net.httpserver.HttpServer; public class TestAppSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(HttpServer.class).build(); + } + @Override public TestApp getValue(InstanceContext instanceContext) { HttpServer httpServer = instanceContext.getDependency(HttpServer.class); diff --git a/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/RunOnServerSupplier.java b/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/RunOnServerSupplier.java index 2f0236e6c48..4d6ac896ef0 100644 --- a/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/RunOnServerSupplier.java +++ b/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/RunOnServerSupplier.java @@ -2,7 +2,10 @@ package org.keycloak.testframework.remote.runonserver; import java.util.Arrays; import java.util.HashSet; +import java.util.List; +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; @@ -16,6 +19,15 @@ import org.apache.http.client.HttpClient; public class RunOnServerSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(HttpClient.class) + .add(KeycloakServer.class) + .add(ManagedRealm.class, instanceContext.getAnnotation().realmRef()) + .add(RemoteProviders.class) + .add(TestClassServer.class).build(); + } + @Override public RunOnServerClient getValue(InstanceContext instanceContext) { KeycloakServer server = instanceContext.getDependency(KeycloakServer.class); diff --git a/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/TestClassServerSupplier.java b/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/TestClassServerSupplier.java index 87c48bdbc3f..39f56a2ae7f 100644 --- a/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/TestClassServerSupplier.java +++ b/test-framework/remote/src/main/java/org/keycloak/testframework/remote/runonserver/TestClassServerSupplier.java @@ -1,5 +1,9 @@ package org.keycloak.testframework.remote.runonserver; +import java.util.List; + +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -8,6 +12,11 @@ import com.sun.net.httpserver.HttpServer; public class TestClassServerSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(HttpServer.class).build(); + } + @Override public TestClassServer getValue(InstanceContext instanceContext) { HttpServer httpServer = instanceContext.getDependency(HttpServer.class); diff --git a/test-framework/remote/src/main/java/org/keycloak/testframework/remote/timeoffset/TimeOffsetSupplier.java b/test-framework/remote/src/main/java/org/keycloak/testframework/remote/timeoffset/TimeOffsetSupplier.java index dd6faec7669..a0cdc1afb61 100644 --- a/test-framework/remote/src/main/java/org/keycloak/testframework/remote/timeoffset/TimeOffsetSupplier.java +++ b/test-framework/remote/src/main/java/org/keycloak/testframework/remote/timeoffset/TimeOffsetSupplier.java @@ -1,5 +1,9 @@ package org.keycloak.testframework.remote.timeoffset; +import java.util.List; + +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.LifeCycle; import org.keycloak.testframework.injection.RequestedInstance; @@ -12,6 +16,12 @@ import org.apache.http.client.HttpClient; public class TimeOffsetSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(HttpClient.class) + .add(RemoteProviders.class).add(KeycloakUrls.class).build(); + } + @Override public TimeOffSet getValue(InstanceContext instanceContext) { var httpClient = instanceContext.getDependency(HttpClient.class); diff --git a/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/PageSupplier.java b/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/PageSupplier.java index 4c194e34739..44fd5b9174f 100644 --- a/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/PageSupplier.java +++ b/test-framework/ui/src/main/java/org/keycloak/testframework/ui/page/PageSupplier.java @@ -1,5 +1,9 @@ package org.keycloak.testframework.ui.page; +import java.util.List; + +import org.keycloak.testframework.injection.DependenciesBuilder; +import org.keycloak.testframework.injection.Dependency; import org.keycloak.testframework.injection.InstanceContext; import org.keycloak.testframework.injection.RequestedInstance; import org.keycloak.testframework.injection.Supplier; @@ -8,6 +12,11 @@ import org.keycloak.testframework.ui.webdriver.ManagedWebDriver; public class PageSupplier implements Supplier { + @Override + public List getDependencies(RequestedInstance instanceContext) { + return DependenciesBuilder.create(ManagedWebDriver.class).build(); + } + @Override public AbstractPage getValue(InstanceContext instanceContext) { ManagedWebDriver webDriver = instanceContext.getDependency(ManagedWebDriver.class);