Testsuite PoC - Add more unit tests for the registry (#31468)

Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
Stian Thorgersen 2024-07-22 15:02:59 +02:00 committed by GitHub
parent c885d682c5
commit 443efb46f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 173 additions and 10 deletions

View file

@ -17,7 +17,7 @@ public class Config {
return config.getOptionalValue("kc.test." + ValueTypeAlias.getAlias(valueType), String.class).orElse(null); return config.getOptionalValue("kc.test." + ValueTypeAlias.getAlias(valueType), String.class).orElse(null);
} }
private static SmallRyeConfig initConfig() { public static SmallRyeConfig initConfig() {
SmallRyeConfigBuilder configBuilder = new SmallRyeConfigBuilder() SmallRyeConfigBuilder configBuilder = new SmallRyeConfigBuilder()
.addDefaultSources() .addDefaultSources()
.addDefaultInterceptors() .addDefaultInterceptors()

View file

@ -58,6 +58,8 @@ public class Registry {
dependency.registerDependency(dependent); dependency.registerDependency(dependent);
deployedInstances.add(dependency); deployedInstances.add(dependency);
requestedInstances.remove(requestedDependency);
if (LOGGER.isTraceEnabled()) { if (LOGGER.isTraceEnabled()) {
LOGGER.tracev("Injecting requested dependency {0} into {1}", LOGGER.tracev("Injecting requested dependency {0} into {1}",
dependency.getSupplier().getClass().getSimpleName(), dependency.getSupplier().getClass().getSimpleName(),
@ -141,21 +143,17 @@ public class Registry {
} }
private void deployRequestedInstances() { private void deployRequestedInstances() {
Iterator<RequestedInstance<?, ?>> itr = requestedInstances.iterator(); while (!requestedInstances.isEmpty()) {
while (itr.hasNext()) { RequestedInstance requestedInstance = requestedInstances.remove(0);
RequestedInstance requestedInstance = itr.next();
InstanceContext instance = new InstanceContext(this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType()); InstanceContext instance = new InstanceContext(this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType());
instance.setValue(requestedInstance.getSupplier().getValue(instance)); instance.setValue(requestedInstance.getSupplier().getValue(instance));
deployedInstances.add(instance);
if (LOGGER.isTraceEnabled()) { if (LOGGER.isTraceEnabled()) {
LOGGER.tracev("Created instance: {0}", LOGGER.tracev("Created instance: {0}",
requestedInstance.getSupplier().getClass().getSimpleName()); requestedInstance.getSupplier().getClass().getSimpleName());
} }
deployedInstances.add(instance);
itr.remove();
} }
} }
@ -189,6 +187,10 @@ public class Registry {
destroy.forEach(this::destroy); destroy.forEach(this::destroy);
} }
List<Supplier<?, ?>> getSuppliers() {
return suppliers;
}
private RequestedInstance<?, ?> createRequestedInstance(Annotation[] annotations, Class<?> valueType) { private RequestedInstance<?, ?> createRequestedInstance(Annotation[] annotations, Class<?> valueType) {
for (Annotation a : annotations) { for (Annotation a : annotations) {
for (Supplier s : suppliers) { for (Supplier s : suppliers) {

View file

@ -14,7 +14,7 @@ public class ValueTypeAlias {
TestDatabase.class, "database" TestDatabase.class, "database"
); );
public static String getAlias(Class clazz) { public static String getAlias(Class<?> clazz) {
String alias = aliases.get(clazz); String alias = aliases.get(clazz);
if (alias == null) { if (alias == null) {
alias = clazz.getSimpleName(); alias = clazz.getSimpleName();

View file

@ -5,14 +5,18 @@ import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.keycloak.test.framework.config.Config;
import org.keycloak.test.framework.injection.mocks.MockChildAnnotation; import org.keycloak.test.framework.injection.mocks.MockChildAnnotation;
import org.keycloak.test.framework.injection.mocks.MockChildSupplier; import org.keycloak.test.framework.injection.mocks.MockChildSupplier;
import org.keycloak.test.framework.injection.mocks.MockChildValue; import org.keycloak.test.framework.injection.mocks.MockChildValue;
import org.keycloak.test.framework.injection.mocks.MockInstances; import org.keycloak.test.framework.injection.mocks.MockInstances;
import org.keycloak.test.framework.injection.mocks.MockParent2Supplier;
import org.keycloak.test.framework.injection.mocks.MockParentAnnotation; import org.keycloak.test.framework.injection.mocks.MockParentAnnotation;
import org.keycloak.test.framework.injection.mocks.MockParentSupplier; import org.keycloak.test.framework.injection.mocks.MockParentSupplier;
import org.keycloak.test.framework.injection.mocks.MockParentValue; import org.keycloak.test.framework.injection.mocks.MockParentValue;
import java.util.List;
public class RegistryTest { public class RegistryTest {
private Registry registry; private Registry registry;
@ -114,6 +118,72 @@ public class RegistryTest {
Assertions.assertNotSame(child1, parentAndChildTest.child); Assertions.assertNotSame(child1, parentAndChildTest.child);
} }
@Test
public void testRecreateIfDifferentLifeCycleRequested() {
MockParentSupplier.DEFAULT_LIFECYCLE = LifeCycle.GLOBAL;
ParentTest parentTest = new ParentTest();
registry.beforeEach(parentTest);
registry.afterEach();
registry.afterAll();
assertRunning(parentTest.parent);
MockParentSupplier.DEFAULT_LIFECYCLE = LifeCycle.CLASS;
ParentTest parentTest2 = new ParentTest();
registry.beforeEach(parentTest2);
assertRunning(parentTest2.parent);
assertClosed(parentTest.parent);
Assertions.assertNotSame(parentTest2.parent, parentTest.parent);
}
@Test
public void testRecreateIfNotCompatible() {
ParentTest parentTest = new ParentTest();
registry.beforeEach(parentTest);
MockParentValue parent1 = parentTest.parent;
registry.afterEach();
MockParentSupplier.COMPATIBLE = false;
registry.beforeEach(parentTest);
registry.afterEach();
MockParentValue parent2 = parentTest.parent;
assertRunning(parent2);
assertClosed(parent1);
Assertions.assertNotSame(parent2, parent1);
}
@Test
public void testSelectedSupplierDefault() {
List<Supplier<?, ?>> suppliers = registry.getSuppliers();
Assertions.assertEquals(1, suppliers.stream().filter(s -> s.getValueType().equals(MockParentValue.class)).count());
Assertions.assertTrue(suppliers.stream().anyMatch(s -> s.getClass().equals(MockParentSupplier.class)));
Assertions.assertFalse(suppliers.stream().anyMatch(s -> s.getClass().equals(MockParent2Supplier.class)));
}
@Test
public void testSelectedSupplierConfigOverride() {
System.setProperty("kc.test.MockParentValue", MockParent2Supplier.class.getSimpleName());
try {
Config.initConfig();
registry = new Registry();
List<Supplier<?, ?>> suppliers = registry.getSuppliers();
Assertions.assertEquals(1, suppliers.stream().filter(s -> s.getValueType().equals(MockParentValue.class)).count());
Assertions.assertFalse(suppliers.stream().anyMatch(s -> s.getClass().equals(MockParentSupplier.class)));
Assertions.assertTrue(suppliers.stream().anyMatch(s -> s.getClass().equals(MockParent2Supplier.class)));
} finally {
System.getProperties().remove("kc.test.MockParentValue");
Config.initConfig();
}
}
@Test @Test
public void testDependencyCreatedOnDemand() { public void testDependencyCreatedOnDemand() {
ChildTest childTest = new ChildTest(); ChildTest childTest = new ChildTest();
@ -122,6 +192,22 @@ public class RegistryTest {
assertRunning(childTest.child, childTest.child.getParent()); assertRunning(childTest.child, childTest.child.getParent());
} }
@Test
public void testDependencyRequestedBefore() {
ParentAndChildTest test = new ParentAndChildTest();
registry.beforeEach(test);
assertRunning(test.child, test.child.getParent());
}
@Test
public void testDependencyRequestedAfter() {
ChildAndParentTest test = new ChildAndParentTest();
registry.beforeEach(test);
assertRunning(test.child, test.child.getParent());
}
public static void assertRunning(Object... values) { public static void assertRunning(Object... values) {
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasItems(values)); MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasItems(values));
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasSize(values.length)); MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasSize(values.length));
@ -150,4 +236,11 @@ public class RegistryTest {
MockChildValue child; MockChildValue child;
} }
public static final class ChildAndParentTest {
@MockChildAnnotation
MockChildValue child;
@MockParentAnnotation
MockParentValue parent;
}
} }

View file

@ -0,0 +1,20 @@
package org.keycloak.test.framework.injection;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.keycloak.admin.client.Keycloak;
import org.openqa.selenium.WebDriver;
public class ValueTypeAliasTest {
@Test
public void withAlias() {
Assertions.assertEquals("browser", ValueTypeAlias.getAlias(WebDriver.class));
}
@Test
public void withoutAlias() {
Assertions.assertEquals("Keycloak", ValueTypeAlias.getAlias(Keycloak.class));
}
}

View file

@ -0,0 +1,45 @@
package org.keycloak.test.framework.injection.mocks;
import org.keycloak.test.framework.injection.InstanceContext;
import org.keycloak.test.framework.injection.LifeCycle;
import org.keycloak.test.framework.injection.RequestedInstance;
import org.keycloak.test.framework.injection.Supplier;
public class MockParent2Supplier implements Supplier<MockParentValue, MockParentAnnotation> {
public static LifeCycle DEFAULT_LIFECYCLE = LifeCycle.CLASS;
public static void reset() {
DEFAULT_LIFECYCLE = LifeCycle.CLASS;
}
@Override
public Class<MockParentAnnotation> getAnnotationClass() {
return MockParentAnnotation.class;
}
@Override
public Class<MockParentValue> getValueType() {
return MockParentValue.class;
}
@Override
public MockParentValue getValue(InstanceContext<MockParentValue, MockParentAnnotation> instanceContext) {
return new MockParentValue();
}
@Override
public boolean compatible(InstanceContext<MockParentValue, MockParentAnnotation> a, RequestedInstance<MockParentValue, MockParentAnnotation> b) {
return true;
}
@Override
public void close(InstanceContext<MockParentValue, MockParentAnnotation> instanceContext) {
instanceContext.getValue().close();
}
@Override
public LifeCycle getDefaultLifecycle() {
return DEFAULT_LIFECYCLE;
}
}

View file

@ -8,9 +8,11 @@ import org.keycloak.test.framework.injection.Supplier;
public class MockParentSupplier implements Supplier<MockParentValue, MockParentAnnotation> { public class MockParentSupplier implements Supplier<MockParentValue, MockParentAnnotation> {
public static LifeCycle DEFAULT_LIFECYCLE = LifeCycle.CLASS; public static LifeCycle DEFAULT_LIFECYCLE = LifeCycle.CLASS;
public static boolean COMPATIBLE = true;
public static void reset() { public static void reset() {
DEFAULT_LIFECYCLE = LifeCycle.CLASS; DEFAULT_LIFECYCLE = LifeCycle.CLASS;
COMPATIBLE = true;
} }
@Override @Override
@ -30,7 +32,7 @@ public class MockParentSupplier implements Supplier<MockParentValue, MockParentA
@Override @Override
public boolean compatible(InstanceContext<MockParentValue, MockParentAnnotation> a, RequestedInstance<MockParentValue, MockParentAnnotation> b) { public boolean compatible(InstanceContext<MockParentValue, MockParentAnnotation> a, RequestedInstance<MockParentValue, MockParentAnnotation> b) {
return true; return COMPATIBLE;
} }
@Override @Override

View file

@ -1,2 +1,3 @@
org.keycloak.test.framework.injection.mocks.MockParentSupplier org.keycloak.test.framework.injection.mocks.MockParentSupplier
org.keycloak.test.framework.injection.mocks.MockParent2Supplier
org.keycloak.test.framework.injection.mocks.MockChildSupplier org.keycloak.test.framework.injection.mocks.MockChildSupplier