Skip to content

Commit

Permalink
finish quarkus:run and integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
patriot1burke committed Mar 20, 2023
1 parent c15c8a8 commit acb6963
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package io.quarkus.deployment.run;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import io.quarkus.builder.BuildResult;

Expand All @@ -13,25 +14,25 @@ public class RunCommandHandler implements BiConsumer<Object, BuildResult> {
@Override
public void accept(Object o, BuildResult buildResult) {
RunCommandLaunchResultBuildItem result = buildResult.consume(RunCommandLaunchResultBuildItem.class);
Consumer<List> consumer = (Consumer<List>) o;
LinkedList list = new LinkedList();
// Classloaders are different when called so we have to pass back
// instances of class that would be in system classloader
if (result.getCmds() == null || result.getCmds().isEmpty()) {
list.add(new NullPointerException()); // no command found
return;
}
if (result.getCmds().size() > 1) {
list.add(new IndexOutOfBoundsException(
result.getCmds().stream().map(i -> i.getCommand()).collect(Collectors.joining(" "))));

// FYI: AugmentAction.performCustomBuild runs in its own classloader
// so we can only pass back instances of those classes in the system classloader

Consumer<Map<String, List>> consumer = (Consumer<Map<String, List>>) o;
Map<String, List> entries = new HashMap<>();
for (RunCommandLauncherBuildItem item : result.getCmds()) {
LinkedList itemList = new LinkedList();
addLaunchCommand(itemList, item);
entries.put(item.getCommand(), itemList);
}
RunCommandLauncherBuildItem item = result.getCmds().get(0);
consumer.accept(entries);
}

private void addLaunchCommand(List list, RunCommandLauncherBuildItem item) {
list.add(item.getArgs());
list.add(item.getWorkingDirectory());
list.add(item.getStartedExpression());
list.add(item.isNeedsLogfile());
list.add(item.getLogFile());

consumer.accept(list);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package io.quarkus.deployment.run;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import io.quarkus.builder.item.MultiBuildItem;

public final class RunCommandLauncherBuildItem extends MultiBuildItem {
private final String command;
private final List<String> args = new ArrayList<>();
private final List<String> args;
private Path workingDirectory;
private String startedExpression;
private Path logFile;
private boolean needsLogfile;

public RunCommandLauncherBuildItem(String command, Path workingDirectory, String startedExpression, Path logFile,
public RunCommandLauncherBuildItem(String command, List<String> args, Path workingDirectory, String startedExpression,
Path logFile,
boolean needsLogfile) {
this.args = args;
this.command = command;
this.workingDirectory = workingDirectory;
this.startedExpression = startedExpression;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,80 @@
package io.quarkus.deployment.run;

import static io.quarkus.deployment.pkg.steps.JarResultBuildStep.DEFAULT_FAST_JAR_DIRECTORY_NAME;
import static io.quarkus.deployment.pkg.steps.JarResultBuildStep.QUARKUS_RUN_JAR;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.pkg.PackageConfig;
import io.quarkus.deployment.pkg.builditem.LegacyJarRequiredBuildItem;
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
import io.quarkus.deployment.pkg.builditem.UberJarRequiredBuildItem;

public class RunCommandProcessor {
private static final String JAVA_HOME_SYS = "java.home";
private static final String JAVA_HOME_ENV = "JAVA_HOME";

@BuildStep
public RunCommandLaunchResultBuildItem commands(List<RunCommandLauncherBuildItem> cmds) {
return new RunCommandLaunchResultBuildItem(cmds);
}

@BuildStep
public void defaultJavaCommand(PackageConfig packageConfig,
OutputTargetBuildItem jar,
List<UberJarRequiredBuildItem> uberJarRequired,
List<LegacyJarRequiredBuildItem> legacyJarRequired,
BuildProducer<RunCommandLauncherBuildItem> cmds) {

Path jarPath = null;
if (legacyJarRequired.isEmpty() && (!uberJarRequired.isEmpty()
|| packageConfig.type.equalsIgnoreCase(PackageConfig.UBER_JAR))) {
jarPath = jar.getOutputDirectory()
.resolve(jar.getBaseName() + packageConfig.getRunnerSuffix() + ".jar");
} else if (!legacyJarRequired.isEmpty() || packageConfig.isLegacyJar()
|| packageConfig.type.equalsIgnoreCase(PackageConfig.LEGACY)) {
jarPath = jar.getOutputDirectory()
.resolve(jar.getBaseName() + packageConfig.getRunnerSuffix() + ".jar");
} else {
jarPath = jar.getOutputDirectory().resolve(DEFAULT_FAST_JAR_DIRECTORY_NAME).resolve(QUARKUS_RUN_JAR);

}

List<String> args = new ArrayList<>();
args.add(determineJavaPath());

for (Map.Entry e : System.getProperties().entrySet()) {
args.add("-D" + e.getKey().toString() + "=" + e.getValue().toString());
}
args.add("-jar");
args.add(jarPath.toAbsolutePath().toString());
cmds.produce(new RunCommandLauncherBuildItem("java", args, null, null, null, false));
}

private String determineJavaPath() {
// try system property first - it will be the JAVA_HOME used by the current JVM
String home = System.getProperty(JAVA_HOME_SYS);
if (home == null) {
// No luck, somewhat a odd JVM not enforcing this property
// try with the JAVA_HOME environment variable
home = System.getenv(JAVA_HOME_ENV);
}
if (home != null) {
File javaHome = new File(home);
File file = new File(javaHome, "bin/java");
if (file.exists()) {
return file.getAbsolutePath();
}
}

// just assume 'java' is on the system path
return "java";
}

}
53 changes: 35 additions & 18 deletions devtools/maven/src/main/java/io/quarkus/maven/RunMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
Expand Down Expand Up @@ -48,43 +49,59 @@ protected void doExecute() throws MojoExecutionException, MojoFailureException {

try (CuratedApplication curatedApplication = bootstrapApplication()) {
AugmentAction action = curatedApplication.createAugmentor();
AtomicReference<Boolean> exists = new AtomicReference<>(false);
AtomicReference<Boolean> exists = new AtomicReference<>();
AtomicReference<String> tooMany = new AtomicReference<>();
action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer<List>() {
String target = System.getProperty("quarkus.run.target");
action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer<Map<String, List>>() {
@Override
public void accept(List cmd) {
if (cmd.get(0) instanceof NullPointerException) {
exists.set(false);
public void accept(Map<String, List> cmds) {
List cmd = null;
if (target != null) {
cmd = cmds.get(target);
if (cmd == null) {
exists.set(false);
return;
}
} else if (cmds.size() == 1) { // defaults to pure java run
cmd = cmds.values().iterator().next();
} else if (cmds.size() == 2) { // choose not default
for (Map.Entry<String, List> entry : cmds.entrySet()) {
if (entry.getKey().equals("java"))
continue;
cmd = entry.getValue();
break;
}
} else if (cmds.size() > 2) {
tooMany.set(cmds.keySet().stream().collect(Collectors.joining(" ")));
return;
} else {
exists.set(true);
}
if (cmd.get(0) instanceof IndexOutOfBoundsException) {
tooMany.set(((IndexOutOfBoundsException) cmd.get(0)).getMessage());
return;
throw new RuntimeException("Should never reach this!");
}
List<String> args = (List<String>) cmd.get(0);
System.out.println("Executing \"" + String.join(" ", args) + "\"");
Path workingDirectory = (Path) cmd.get(1);
try {
Process process = new ProcessBuilder()
ProcessBuilder builder = new ProcessBuilder()
.command(args)
.inheritIO()
.directory(workingDirectory.toFile())
.start();
.inheritIO();
if (workingDirectory != null) {
builder.directory(workingDirectory.toFile());
}
Process process = builder.start();
int exit = process.waitFor();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
},
RunCommandLaunchResultBuildItem.class.getName());
if (!exists.get()) {
getLog().info(
"You do not need quarkus:run to execute your Quarkus project. Just execute it like a plain Java application with java -jar");
if (target != null && !exists.get()) {
getLog().error("quarkus.run.target " + target + " is not found");
return;
}
if (tooMany.get() != null) {
getLog().error("Run Failed: Too many installed extensions support quarkus:run. Can only have one");
getLog().error(
"Too many installed extensions support quarkus:run. Use -Dquarkus.run.target=<target> to choose");
getLog().error("Extensions: " + tooMany.get());
}
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.OptionalInt;

Expand Down Expand Up @@ -47,11 +48,12 @@ public RunCommandLauncherBuildItem run(List<AzureFunctionBuildItem> functions, O

checkRuntimeExistence(commandHandler);

RunCommandLauncherBuildItem launcher = new RunCommandLauncherBuildItem("azure-functions", stagingDir,
String cmd = getStartFunctionHostCommand(config);
List<String> args = new LinkedList<>();
Arrays.stream(cmd.split(" ")).forEach(s -> args.add(s));
RunCommandLauncherBuildItem launcher = new RunCommandLauncherBuildItem("azure-functions", args, stagingDir,
STARTED_EXPRESSION, null,
true);
String cmd = getStartFunctionHostCommand(config);
Arrays.stream(cmd.split(" ")).forEach(s -> launcher.getArgs().add(s));
return launcher;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,16 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.io.input.TeeInputStream;

Expand All @@ -31,7 +30,6 @@
import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.deployment.run.RunCommandHandler;
import io.quarkus.deployment.run.RunCommandLaunchResultBuildItem;
import io.quarkus.deployment.run.RunCommandLauncherBuildItem;
import io.quarkus.test.common.http.TestHTTPResourceManager;

public class RunCommandLauncher implements ArtifactLauncher<ArtifactLauncher.InitContext> {
Expand All @@ -48,59 +46,49 @@ public class RunCommandLauncher implements ArtifactLauncher<ArtifactLauncher.Ini

private ExecutorService executorService = Executors.newFixedThreadPool(2);

public static RunCommandLauncher tryLauncher(QuarkusBootstrap bootstrap, Duration waitTime) {
AtomicReference<Boolean> exists = new AtomicReference<>(false);
AtomicReference<String> tooMany = new AtomicReference<>();
List<String> args = new ArrayList<>();
AtomicReference<Path> workingDir = new AtomicReference<>();
AtomicReference<String> startedExpression = new AtomicReference<>();
AtomicReference<Boolean> needsLogfile = new AtomicReference<>();
AtomicReference<Path> logFilePath = new AtomicReference<>();
public static RunCommandLauncher tryLauncher(QuarkusBootstrap bootstrap, String target, Duration waitTime) {
Map<String, List> cmds = new HashMap<>();
try (CuratedApplication curatedApplication = bootstrap.bootstrap()) {
AugmentAction action = curatedApplication.createAugmentor();
action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer<List>() {
action.performCustomBuild(RunCommandHandler.class.getName(), new Consumer<Map<String, List>>() {
@Override
public void accept(List cmd) {
if (cmd.get(0) instanceof NullPointerException) {
exists.set(false);
return;
} else {
exists.set(true);
}
if (cmd.get(0) instanceof IndexOutOfBoundsException) {
tooMany.set(((IndexOutOfBoundsException) cmd.get(0)).getMessage());
return;
}
args.addAll((List<String>) cmd.get(0));
workingDir.set((Path) cmd.get(1));
startedExpression.set((String) cmd.get(2));
needsLogfile.set((Boolean) cmd.get(3));
logFilePath.set((Path) cmd.get(4));
public void accept(Map<String, List> accepted) {
cmds.putAll(accepted);
}
},
RunCommandLaunchResultBuildItem.class.getName());
} catch (BootstrapException ex) {
throw new RuntimeException(ex);
} catch (IllegalArgumentException ill) {
if (ill.getMessage().contains(RunCommandLauncherBuildItem.class.getName())) {
return null;
}
throw ill;
}
if (!exists.get()) {
List cmd = null;
if (target != null) {
cmd = cmds.get(target);
if (cmd == null) {
throw new RuntimeException("quarkus.run.target \"" + target + "\" does not exist");
}
} else if (cmds.size() == 1) { // defaults to pure java run
return null;
}
if (tooMany.get() != null) {
} else if (cmds.size() == 2) { // choose not default
for (Map.Entry<String, List> entry : cmds.entrySet()) {
if (entry.getKey().equals("java"))
continue;
cmd = entry.getValue();
break;
}
} else if (cmds.size() > 2) {
String tooMany = cmds.keySet().stream().collect(Collectors.joining(" "));
throw new RuntimeException(
"Too many extensions support quarkus:run. Need to remove one for integration tests to work: "
+ tooMany.get());
"Too many extensions support quarkus:run. Set quarkus.run.target to pick one to run during integration tests: "
+ tooMany);
} else {
throw new RuntimeException("Should never reach this!");
}
RunCommandLauncher launcher = new RunCommandLauncher();
launcher.args = args;
launcher.workingDir = workingDir.get();
launcher.startedExpression = startedExpression.get();
launcher.needsLogFile = needsLogfile.get();
launcher.logFilePath = logFilePath.get();
launcher.args = (List<String>) cmd.get(0);
launcher.workingDir = (Path) cmd.get(1);
launcher.startedExpression = (String) cmd.get(2);
launcher.needsLogFile = (Boolean) cmd.get(3);
launcher.logFilePath = (Path) cmd.get(4);
launcher.waitTimeSeconds = waitTime.getSeconds();
return launcher;
}
Expand Down
Loading

0 comments on commit acb6963

Please sign in to comment.