Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to control which classes are cloned #17306

Merged
merged 1 commit into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ public class TestConfig {
@ConfigItem(defaultValue = "all")
TestType type;

/**
* If a class matches this pattern then it will be cloned into the Quarkus ClassLoader even if it
* is in a parent first artifact.
*
* This is important for collections which can contain objects from the Quarkus ClassLoader, but for
* most parent first classes it will just cause problems.
*/
@ConfigItem(defaultValue = "java\\..*")
String classClonePattern;

@ConfigGroup
public static class Profile {

Expand Down
11 changes: 11 additions & 0 deletions core/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,17 @@
<parentFirstArtifact>org.opentest4j:opentest4j</parentFirstArtifact>
<parentFirstArtifact>org.junit.platform:junit-platform-commons</parentFirstArtifact>

<!-- Pact support. It would be great if there was somewhere better to put this-->
<parentFirstArtifact>au.com.dius:pact-jvm-provider-junit5</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-provider</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-core-support</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-core-pact-broker</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-core-model</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-core-matchers</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-junit5</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-consumer-java8</parentFirstArtifact>
<parentFirstArtifact>au.com.dius:pact-jvm-consumer</parentFirstArtifact>

</parentFirstArtifacts>
<runnerParentFirstArtifacts>
<runnerParentFirstArtifact>org.graalvm.sdk:graal-sdk</runnerParentFirstArtifact>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.enterprise.inject.Alternative;
Expand Down Expand Up @@ -127,6 +129,7 @@ public class QuarkusTestExtension
private static Object actualTestInstance;
private static ClassLoader originalCl;
private static RunningQuarkusApplication runningQuarkusApplication;
private static Pattern clonePattern;
private static Throwable firstException; //if this is set then it will be thrown from the very first test that is run, the rest are aborted

private static List<Object> beforeClassCallbacks;
Expand Down Expand Up @@ -343,6 +346,9 @@ private ExtensionState doJavaStart(ExtensionContext context, Class<? extends Qua
populateCallbacks(startupAction.getClassLoader());

runningQuarkusApplication = startupAction.run();
String patternString = runningQuarkusApplication.getConfigValue("quarkus.test.class-clone-pattern", String.class)
.orElse("java\\..*");
clonePattern = Pattern.compile(patternString);
TracingHandler.quarkusStarted();

//now we have full config reset the hang timer
Expand Down Expand Up @@ -951,7 +957,36 @@ private Object runExtensionMethod(ReflectiveInvocationContext<Method> invocation
List<Object> originalArguments = invocationContext.getArguments();
List<Object> argumentsFromTccl = new ArrayList<>();
for (Object arg : originalArguments) {
argumentsFromTccl.add(deepClone.clone(arg));
boolean cloneRequired = false;
if (arg != null) {
Class theclass = arg.getClass();
while (theclass.isArray()) {
theclass = theclass.getComponentType();
}
String className = theclass.getName();
if (theclass.isPrimitive()) {
cloneRequired = false;
} else if (clonePattern.matcher(className).matches()) {
cloneRequired = true;
} else {
try {
cloneRequired = runningQuarkusApplication.getClassLoader()
.loadClass(theclass.getName()) != theclass;
} catch (ClassNotFoundException e) {
if (arg instanceof Supplier) {
cloneRequired = true;
} else {
throw e;
}
}
}
}

if (cloneRequired) {
argumentsFromTccl.add(deepClone.clone(arg));
} else {
argumentsFromTccl.add(arg);
}
}

return newMethod.invoke(actualTestInstance, argumentsFromTccl.toArray(new Object[0]));
Expand Down Expand Up @@ -1087,6 +1122,7 @@ public void close() {
log.error("Failed to shutdown Quarkus", e);
} finally {
runningQuarkusApplication = null;
clonePattern = null;
try {
if (QuarkusTestExtension.this.originalCl != null) {
setCCL(QuarkusTestExtension.this.originalCl);
Expand Down