Skip to content

Commit

Permalink
Add support (maybe?) for profiles in dev mode
Browse files Browse the repository at this point in the history
  • Loading branch information
holly-cummins committed Jul 24, 2024
1 parent 79c76b4 commit 730f557
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ private QuarkusClassLoader makeClassLoader(String key, Class requiredTestClass,
// .unwrap(SmallRyeConfig.class)
// .getProfiles());

System.out.println("HOLLY interceipt original" + originalClassLoader);
System.out.println("HOLLY facade original" + originalClassLoader);
AppMakerHelper appMakerHelper = new AppMakerHelper();

CuratedApplication curatedApplication = curatedApplications.get(key);
Expand Down Expand Up @@ -333,6 +333,7 @@ public String getName() {

@Override
public void close() throws IOException {
// TODO clearly, an implementation is needed!

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ public Runnable prepare() {
try {
long start = System.currentTimeMillis();
ClassLoader old = Thread.currentThread().getContextClassLoader();
System.out.println("HOLLU junit prepare, old is " + old);

QuarkusClassLoader tcl = testApplication.createDeploymentClassLoader();
LogCapturingOutputFilter logHandler = new LogCapturingOutputFilter(testApplication, true, true,
TestSupport.instance().get()::isDisplayTestOutput);
Expand Down Expand Up @@ -584,6 +586,7 @@ private DiscoveryResult discoverTestClasses() {
Set<String> quarkusTestClasses = new HashSet<>();
for (var a : Arrays.asList(QUARKUS_TEST, QUARKUS_MAIN_TEST)) {
for (AnnotationInstance i : index.getAnnotations(a)) {

DotName name = i.target().asClass().name();
quarkusTestClasses.add(name.toString());
for (ClassInfo clazz : index.getAllKnownSubclasses(name)) {
Expand All @@ -597,6 +600,8 @@ private DiscoveryResult discoverTestClasses() {
Set<DotName> allTestAnnotations = collectTestAnnotations(index);
Set<DotName> allTestClasses = new HashSet<>();
Map<DotName, DotName> enclosingClasses = new HashMap<>();
Map<String, String> profiles = new HashMap<>();
Map<String, ClassLoader> rcls = new HashMap<>();
for (DotName annotation : allTestAnnotations) {
for (AnnotationInstance instance : index.getAnnotations(annotation)) {
if (instance.target().kind() == AnnotationTarget.Kind.METHOD) {
Expand Down Expand Up @@ -646,6 +651,17 @@ private DiscoveryResult discoverTestClasses() {
if (Modifier.isAbstract(clazz.flags())) {
continue;
}
AnnotationInstance testProfile = clazz.declaredAnnotation(TEST_PROFILE);
// TODO is there a cleaner way to do this? probably!
if (testProfile == null) {
profiles.put(name, "no-profile");
} else {
System.out.println(
"HOLLY profile is " + testProfile + testProfile.value().asString() + testProfile.value().asClass()
+ testProfile.value().name());
profiles.put(name,
testProfile.value().asString());
}
unitTestClasses.add(name);
}

Expand All @@ -658,28 +674,45 @@ private DiscoveryResult discoverTestClasses() {

System.out.println(
"HOLLY after the re-add or whatever? quarkus test classes is " + Arrays.toString(quarkusTestClasses.toArray()));
ClassLoader rcl = null;
System.out.println("classload thread is " + Thread.currentThread());

for (String i : quarkusTestClasses) {
ClassLoader old = Thread.currentThread().getContextClassLoader();
String profileName = profiles.get(i);
if (profileName == null) {
profileName = "no-profile";
}
System.out.println("HOLLY profile name is " + profileName);
ClassLoader rcl = rcls.get(profileName);
System.out.println("HOLLY rcl is " + rcl);
// rcl = null; // TODO diagnostics
try {
if (rcl == null) {
System.out.println("HOLLY Making a java start with " + testApplication);
// Although it looks like we need to start once per class, the class is just indicative of where classes for this module live

Class profile = null;
// TODO diagnostics
if (!"no-profile".equals(profileName)) {
//TODO is this the right classloader to use?
profile = Class.forName(profileName);
System.out.println("HOLLY setting profile to " + profile);
}
// CuratedApplications cannot (right now) be re-used between restarts. So even though the builder gave us a
// curated application, don't use it.
// TODO can we make the app re-usable, or otherwise leverage the app that we got passed in?
// TODO sort out profiles!
System.out.println("HOLLY will make an app using profile " + profile);
rcl = new AppMakerHelper()
.getStartupAction(Thread.currentThread().getContextClassLoader().loadClass(i), null,
true, null);
true, profile);
rcls.put(profileName, rcl);
}
// TODO do we need to set a TCCL? Behaviour seems the same either way
Thread.currentThread().setContextClassLoader(rcl);

System.out.println("639 HOLLY loading quarkus test with " + Thread.currentThread().getContextClassLoader());
itClasses.add(Thread.currentThread().getContextClassLoader().loadClass(i));

itClasses.add(rcl.loadClass(i));
} catch (Exception e) {
System.out.println("HOLLY BAD BAD" + e);
log.warnf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public DevUIJsonRPCTest(String namespace) {
public DevUIJsonRPCTest(String namespace, String testUrl) {
this.namespace = namespace;
this.testUrl = testUrl;
System.out.println("HOLLY config loading TCCL " + Thread.currentThread().getContextClassLoader());
System.out.println("HOLLY config loading config ptovider class " + ConfigProvider.class.getClassLoader());
System.out.println("HOLLY config loading this class " + this.getClass().getClassLoader());
String nonApplicationRoot = ConfigProvider.getConfig()
.getOptionalValue("quarkus.http.non-application-root-path", String.class).orElse("q");
if (!nonApplicationRoot.startsWith("/")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public Thread newThread(Runnable r) {

testHttpEndpointProviders = TestHttpEndpointProvider.load();
System.out.println("HOLLY during execution, TCCL is " + Thread.currentThread().getContextClassLoader());
System.out.println("HOLLY the test was loaded with " + requiredTestClass);
System.out.println("HOLLY the test was loaded with " + requiredTestClass + requiredTestClass.getClassLoader());

// StartupAction startupAction = augmentAction.createInitialRuntimeApplication();
// clear the test.url system property as the value leaks into the run when using different profiles
Expand Down Expand Up @@ -281,8 +281,10 @@ public Thread newThread(Runnable r) {

TracingHandler.quarkusStarted();

// TODO infinite loops? also causes all paramstests to fail + 37 failures??
// ... and doesn't even fix the config problem
// ConfigProviderResolver.setInstance(new RunningAppConfigResolver(runningQuarkusApplication));
//now we have full config reset the hang timer

if (hangTaskKey != null) {
hangTaskKey.cancel(false);
hangTimeout = runningQuarkusApplication.getConfigValue(QUARKUS_TEST_HANG_DETECTION_TIMEOUT, Duration.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,21 @@

public class CustomLauncherInterceptor implements LauncherInterceptor {

private final ClassLoader customClassLoader;
private static int count = 0;
private static int constructCount = 0;
FacadeClassLoader facadeLoader = null;

public CustomLauncherInterceptor() throws Exception {
System.out.println(constructCount++ + "HOLLY interceipt construct" + getClass().getClassLoader());
System.out.println(constructCount++ + "HOLLY interceipt constructor" + getClass().getClassLoader());
ClassLoader parent = Thread.currentThread()
.getContextClassLoader();
System.out.println("HOLLY CCL is " + parent);
System.out.println("HOLLY at interceptor construction, CCL is " + parent);

customClassLoader = parent;
System.out.println("HOLLY stored variable loader" + customClassLoader);
}

@Override
public <T> T intercept(Invocation<T> invocation) {
System.out.println("HOLLY intercept");
System.out.println("HOLLY intercept top level" + invocation);
if (System.getProperty("prod.mode.tests") != null) {
return invocation.proceed();

Expand All @@ -39,21 +37,33 @@ public <T> T intercept(Invocation<T> invocation) {

private <T> T nintercept(Invocation<T> invocation) {
ClassLoader old = Thread.currentThread().getContextClassLoader();
System.out.println("Interceipt, TCCL is " + old);
System.out.println("Interceipt, TCCL is " + old + Thread.currentThread());
// Don't make a facade loader if the JUnitRunner got there ahead of us
// they set a runtime classloader so handle that too
if (!(old instanceof FacadeClassLoader) || old instanceof QuarkusClassLoader && old.getName().contains("Runtime")) {
System.out.println("HOLLY INTERCEPT RESTART ------------------------------");
System.out.println(
"HOLLY intercept constructing a classloader ------------------------------" + Thread.currentThread());
try {
// TODO we should be able to do better than this here
//TODO We want to tidy up classloaders we created, but not ones created upstream
facadeLoader = null; // TODO diagnostics
// TODO should this be a static variable, so we don't make zillions and cause too many files exceptions?
// Although in principle we only go through a few times
FacadeClassLoader facadeLoader = new FacadeClassLoader(old);
if (facadeLoader == null) {
facadeLoader = new FacadeClassLoader(old);
}
Thread.currentThread()
.setContextClassLoader(facadeLoader);
System.out.println("HOLLY did set TCCL " + Thread.currentThread());
return invocation.proceed();
} finally {
Thread.currentThread()
.setContextClassLoader(old);
System.out.println("HOLLY doing finally, setting back to " + old);

// TODO It would clearly be nice to tidy up, but I think the gradle
// devtools tests may be asynchronous, because if we reset the TCCL
// at this point, the test loads with the wrong classloader
// Thread.currentThread()
// .setContextClassLoader(old);
}
} else {
return invocation.proceed();
Expand All @@ -63,11 +73,10 @@ private <T> T nintercept(Invocation<T> invocation) {
@Override
public void close() {

// // try {
// // // TODO customClassLoader.close();
// // } catch (Exception e) {
// // throw new UncheckedIOException("Failed to close custom class
// loader", e);
// // }
try {
facadeLoader.close();
} catch (Exception e) {
throw new RuntimeException("Failed to close custom classloader", e);
}
}
}

0 comments on commit 730f557

Please sign in to comment.