Skip to content

Commit

Permalink
Support passing parameters to a QuarkusTestResource
Browse files Browse the repository at this point in the history
Fixes: #9066

Co-authored-by: Guillaume Smet <[email protected]>
  • Loading branch information
geoand and gsmet committed May 5, 2020
1 parent 6fedd30 commit e7c1ecc
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
*/
Class<? extends QuarkusTestResourceLifecycleManager> value();

/**
* @return The arguments to be passed to the {@code QuarkusTestResourceLifecycleManager}
*
* @see QuarkusTestResourceLifecycleManager#init(String[])
*/
String[] initArgs() default {};

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ public interface QuarkusTestResourceLifecycleManager {
*/
void stop();

/**
* Arguments passed to the lifecycle manager before it starts
* These arguments are taken from {@code QuarkusTestResource#args()}
*
* The {@code args} array is never null
*
* @see QuarkusTestResource#initArgs()
*/
default void init(String[] args) {

}

/**
* Allow each resource to provide custom injection of fields of the test class
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,53 @@
import java.io.Closeable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;

import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;

public class TestResourceManager implements Closeable {

private final List<QuarkusTestResourceLifecycleManager> testResources;
public static final String[] EMPTY_STRINGS_ARRAY = {};
private final List<TestResourceEntry> testResourceEntries;
private Map<String, String> oldSystemProps;

public TestResourceManager(Class<?> testClass) {
testResources = getTestResources(testClass);
testResourceEntries = getTestResources(testClass);
}

public void init() {
for (TestResourceEntry entry : testResourceEntries) {
try {
entry.getTestResource().init(entry.getArgs());
} catch (Exception e) {
throw new RuntimeException("Unable initialize test resource " + entry.getTestResource(), e);
}
}
}

public Map<String, String> start() {
Map<String, String> ret = new HashMap<>();
for (QuarkusTestResourceLifecycleManager testResource : testResources) {
for (TestResourceEntry entry : testResourceEntries) {
try {
Map<String, String> start = testResource.start();
Map<String, String> start = entry.getTestResource().start();
if (start != null) {
ret.putAll(start);
}
} catch (Exception e) {
throw new RuntimeException("Unable to start Quarkus test resource " + testResource, e);
throw new RuntimeException("Unable to start Quarkus test resource " + entry.getTestResource(), e);
}
}
oldSystemProps = new HashMap<>();
Expand All @@ -51,8 +65,8 @@ public Map<String, String> start() {
}

public void inject(Object testInstance) {
for (QuarkusTestResourceLifecycleManager testResource : testResources) {
testResource.inject(testInstance);
for (TestResourceEntry entry : testResourceEntries) {
entry.getTestResource().inject(testInstance);
}
}

Expand All @@ -68,11 +82,11 @@ public void close() {
}
}
oldSystemProps = null;
for (QuarkusTestResourceLifecycleManager testResource : testResources) {
for (TestResourceEntry entry : testResourceEntries) {
try {
testResource.stop();
entry.getTestResource().stop();
} catch (Exception e) {
throw new RuntimeException("Unable to stop Quarkus test resource " + testResource, e);
throw new RuntimeException("Unable to stop Quarkus test resource " + entry.getTestResource(), e);
}
}
try {
Expand All @@ -83,10 +97,10 @@ public void close() {
}

@SuppressWarnings("unchecked")
private List<QuarkusTestResourceLifecycleManager> getTestResources(Class<?> testClass) {
private List<TestResourceEntry> getTestResources(Class<?> testClass) {
IndexView index = TestClassIndexer.readIndex(testClass);

Set<Class<? extends QuarkusTestResourceLifecycleManager>> testResourceRunnerClasses = new LinkedHashSet<>();
Map<Class<? extends QuarkusTestResourceLifecycleManager>, String[]> testResourceRunnerClasses = new LinkedHashMap<>();

Set<AnnotationInstance> testResourceAnnotations = new HashSet<>();
testResourceAnnotations.addAll(index.getAnnotations(DotName.createSimple(QuarkusTestResource.class.getName())));
Expand All @@ -96,32 +110,75 @@ private List<QuarkusTestResourceLifecycleManager> getTestResources(Class<?> test
}
for (AnnotationInstance annotation : testResourceAnnotations) {
try {
testResourceRunnerClasses.add((Class<? extends QuarkusTestResourceLifecycleManager>) Class
.forName(annotation.value().asString(), true, Thread.currentThread().getContextClassLoader()));
Class<? extends QuarkusTestResourceLifecycleManager> testResourceClass = (Class<? extends QuarkusTestResourceLifecycleManager>) Class
.forName(annotation.value().asString(), true, Thread.currentThread().getContextClassLoader());

AnnotationValue argsAnnotationValue = annotation.value("initArgs");
String[] args = argsAnnotationValue != null ? argsAnnotationValue.asStringArray() : EMPTY_STRINGS_ARRAY;

if (testResourceRunnerClasses.containsKey(testResourceClass)) {
if (!Arrays.equals(testResourceRunnerClasses.get(testResourceClass), args)) {
throw new RuntimeException(
"The 'initArgs' field of '@QuarkusTestResource' must not be different when using the same value for a class. Offending class is '"
+ testResourceClass + "'");
}
}
testResourceRunnerClasses.put(testResourceClass, args);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to find the class for the test resource " + annotation.value().asString());
}
}

List<QuarkusTestResourceLifecycleManager> testResourceRunners = new ArrayList<>();
List<TestResourceEntry> testResourceRunners = new ArrayList<>();

for (Class<? extends QuarkusTestResourceLifecycleManager> testResourceRunnerClass : testResourceRunnerClasses) {
for (Map.Entry<Class<? extends QuarkusTestResourceLifecycleManager>, String[]> entry : testResourceRunnerClasses
.entrySet()) {
try {
testResourceRunners.add(testResourceRunnerClass.getConstructor().newInstance());
testResourceRunners.add(new TestResourceEntry(entry.getKey().getConstructor().newInstance(), entry.getValue()));
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
throw new RuntimeException("Unable to instantiate the test resource " + testResourceRunnerClass);
throw new RuntimeException("Unable to instantiate the test resource " + entry);
}
}

for (QuarkusTestResourceLifecycleManager quarkusTestResourceLifecycleManager : ServiceLoader
.load(QuarkusTestResourceLifecycleManager.class, Thread.currentThread().getContextClassLoader())) {
testResourceRunners.add(quarkusTestResourceLifecycleManager);
testResourceRunners.add(new TestResourceEntry(quarkusTestResourceLifecycleManager));
}

Collections.sort(testResourceRunners, new QuarkusTestResourceLifecycleManagerComparator());
testResourceRunners.sort(new Comparator<TestResourceEntry>() {

private final QuarkusTestResourceLifecycleManagerComparator lifecycleManagerComparator = new QuarkusTestResourceLifecycleManagerComparator();

@Override
public int compare(TestResourceEntry o1, TestResourceEntry o2) {
return lifecycleManagerComparator.compare(o1.getTestResource(), o2.getTestResource());
}
});

return testResourceRunners;
}

private static class TestResourceEntry {
private final QuarkusTestResourceLifecycleManager testResource;
private final String[] args;

public TestResourceEntry(QuarkusTestResourceLifecycleManager testResource) {
this(testResource, EMPTY_STRINGS_ARRAY);
}

public TestResourceEntry(QuarkusTestResourceLifecycleManager testResource, String[] args) {
this.testResource = testResource;
this.args = args;
}

public QuarkusTestResourceLifecycleManager getTestResource() {
return testResource;
}

public String[] getArgs() {
return args;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public void beforeEach(ExtensionContext extensionContext) throws Exception {
ExtensionContext.Store store = extensionContext.getRoot().getStore(ExtensionContext.Namespace.GLOBAL);
if (store.get(TestResourceManager.class.getName()) == null) {
TestResourceManager manager = new TestResourceManager(extensionContext.getRequiredTestClass());
manager.init();
manager.start();
store.put(TestResourceManager.class.getName(), new ExtensionContext.Store.CloseableResource() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ public void run() {
ExtensionContext.Store store = extensionContext.getRoot().getStore(ExtensionContext.Namespace.GLOBAL);
if (store.get(TestResourceManager.class.getName()) == null) {
TestResourceManager manager = new TestResourceManager(extensionContext.getRequiredTestClass());
manager.init();
manager.start();
store.put(TestResourceManager.class.getName(), new ExtensionContext.Store.CloseableResource() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ public void run() {
ExtensionContext.Store store = extensionContext.getRoot().getStore(ExtensionContext.Namespace.GLOBAL);
if (store.get(TestResourceManager.class.getName()) == null) {
TestResourceManager manager = new TestResourceManager(extensionContext.getRequiredTestClass());
manager.init();
manager.start();
store.put(TestResourceManager.class.getName(), new ExtensionContext.Store.CloseableResource() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public void beforeAll(ExtensionContext extensionContext) throws Exception {
if (state == null) {
TestResourceManager testResourceManager = new TestResourceManager(extensionContext.getRequiredTestClass());
try {
testResourceManager.init();
Map<String, String> systemProps = testResourceManager.start();
NativeImageLauncher launcher = new NativeImageLauncher(extensionContext.getRequiredTestClass());
launcher.addSystemProperties(systemProps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ private ExtensionState doJavaStart(ExtensionContext context) throws Throwable {
testResourceManager = (Closeable) startupAction.getClassLoader().loadClass(TestResourceManager.class.getName())
.getConstructor(Class.class)
.newInstance(requiredTestClass);
testResourceManager.getClass().getMethod("init").invoke(testResourceManager);
testResourceManager.getClass().getMethod("start").invoke(testResourceManager);

populateCallbacks(startupAction.getClassLoader());
Expand Down

0 comments on commit e7c1ecc

Please sign in to comment.