
io.quarkus.vertx.http.deployment.devmode.tests.TestsProcessor Maven / Gradle / Ivy
package io.quarkus.vertx.http.deployment.devmode.tests;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.dev.RuntimeUpdatesProcessor;
import io.quarkus.deployment.dev.testing.TestClassResult;
import io.quarkus.deployment.dev.testing.TestListenerBuildItem;
import io.quarkus.deployment.dev.testing.TestRunResults;
import io.quarkus.deployment.dev.testing.TestSupport;
import io.quarkus.dev.spi.DevModeType;
import io.quarkus.devconsole.spi.DevConsoleRouteBuildItem;
import io.quarkus.devconsole.spi.DevConsoleTemplateInfoBuildItem;
import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem;
import io.quarkus.vertx.http.deployment.RouteBuildItem;
import io.quarkus.vertx.http.runtime.devmode.DevConsoleRecorder;
import io.quarkus.vertx.http.runtime.devmode.Json;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
public class TestsProcessor {
@BuildStep(onlyIf = IsDevelopment.class)
public DevConsoleTemplateInfoBuildItem results(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleTemplateInfoBuildItem("tests", ts.get());
}
@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep(onlyIf = IsDevelopment.class)
public void setupTestRoutes(
DevConsoleRecorder recorder,
NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem,
LaunchModeBuildItem launchModeBuildItem,
ShutdownContextBuildItem shutdownContextBuildItem,
BuildProducer routeBuildItemBuildProducer,
BuildProducer testListenerBuildItemBuildProducer) throws IOException {
DevModeType devModeType = launchModeBuildItem.getDevModeType().orElse(null);
if (devModeType == null || !devModeType.isContinuousTestingSupported()) {
return;
}
if (TestSupport.instance().isPresent()) {
// Add continuous testing
routeBuildItemBuildProducer.produce(nonApplicationRootPathBuildItem.routeBuilder()
.route("dev-v1/test")
.handler(recorder.continuousTestHandler(shutdownContextBuildItem))
.build());
}
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem handleTestStatus(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
//GET tests/status
//DISABLED, RUNNING (run id), RUN (run id, start time, nextRunQueued)
//GET tests/results
return new DevConsoleRouteBuildItem("tests/status", "GET", new Handler<>() {
@Override
public void handle(RoutingContext event) {
jsonResponse(event);
TestSupport testSupport = ts.get();
TestSupport.RunStatus status = testSupport.getStatus();
TestStatus testStatus = new TestStatus();
long lastRun = status.getLastRun();
testStatus.setLastRun(lastRun);
if (lastRun > 0) {
TestRunResults result = testSupport.getResults();
testStatus.setTestsFailed(result.getCurrentFailedCount());
testStatus.setTestsPassed(result.getCurrentPassedCount());
testStatus.setTestsSkipped(result.getCurrentSkippedCount());
testStatus.setTestsRun(result.getFailedCount() + result.getPassedCount());
testStatus.setTotalTestsFailed(result.getFailedCount());
testStatus.setTotalTestsPassed(result.getPassedCount());
testStatus.setTotalTestsSkipped(result.getSkippedCount());
}
//get running last, as otherwise if the test completes in the meantime you could see
//both running and last run being the same number
testStatus.setRunning(status.getRunning());
event.response().end(JsonObject.mapFrom(testStatus).encode());
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
void toggleTestRunner(LaunchModeBuildItem launchModeBuildItem, BuildProducer routeProducer) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return;
}
routeProducer.produce(new DevConsoleRouteBuildItem("tests/toggle", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
if (ts.get().isStarted()) {
ts.get().stop();
} else {
ts.get().start();
}
Json.JsonObjectBuilder object = Json.object();
object.put("running", ts.get().isRunning());
event.response().putHeader("Content-Type", "application/json; charset=utf-8").end(object.build());
}
}));
routeProducer.produce(new DevConsoleRouteBuildItem("tests/toggle-broken-only", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
boolean brokenOnlyMode = ts.get().toggleBrokenOnlyMode();
Json.JsonObjectBuilder object = Json.object();
object.put("brokenOnlyMode", brokenOnlyMode);
event.response().putHeader("Content-Type", "application/json; charset=utf-8").end(object.build());
}
}));
}
private boolean testsDisabled(LaunchModeBuildItem launchModeBuildItem, Optional ts) {
return ts.isEmpty() || launchModeBuildItem.getDevModeType().orElse(null) != DevModeType.LOCAL;
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem runAllTests(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleRouteBuildItem("tests/runall", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
ts.get().runAllTests();
event.response().setStatusCode(204).end();
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem toggleTestOutput(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleRouteBuildItem("tests/toggle-test-output", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
boolean isTestOutput = ts.get().toggleTestOutput();
Json.JsonObjectBuilder object = Json.object();
object.put("isTestOutput", isTestOutput);
event.response().putHeader("Content-Type", "application/json; charset=utf-8").end(object.build());
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem runFailedTests(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleRouteBuildItem("tests/runfailed", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
ts.get().runFailedTests();
event.response().setStatusCode(204).end();
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem printfailures(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleRouteBuildItem("tests/printfailures", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
ts.get().printFullResults();
event.response().setStatusCode(204).end();
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem toggleInstrumentation(LaunchModeBuildItem launchModeBuildItem) {
return new DevConsoleRouteBuildItem("tests/toggle-instrumentation", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
boolean instrumentationEnabled = RuntimeUpdatesProcessor.INSTANCE.toggleInstrumentation();
Json.JsonObjectBuilder object = Json.object();
object.put("instrumentationEnabled", instrumentationEnabled);
event.response().putHeader("Content-Type", "application/json; charset=utf-8").end(object.build());
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem toggleLiveReloadEnabled(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleRouteBuildItem("tests/toggle-live-reload", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
boolean liveReloadEnabled = ts.get().toggleLiveReloadEnabled();
Json.JsonObjectBuilder object = Json.object();
object.put("liveReloadEnabled", liveReloadEnabled);
event.response().putHeader("Content-Type", "application/json; charset=utf-8").end(object.build());
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem forceRestart(LaunchModeBuildItem launchModeBuildItem) {
if (testsDisabled(launchModeBuildItem, TestSupport.instance())) {
return null;
}
return new DevConsoleRouteBuildItem("tests/force-restart", "POST", new Handler<>() {
@Override
public void handle(RoutingContext event) {
RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
event.response().setStatusCode(204).end();
}
});
}
@BuildStep(onlyIf = IsDevelopment.class)
DevConsoleRouteBuildItem handleTestResult(LaunchModeBuildItem launchModeBuildItem) {
Optional ts = TestSupport.instance();
if (testsDisabled(launchModeBuildItem, ts)) {
return null;
}
return new DevConsoleRouteBuildItem("tests/result", "GET", new Handler<>() {
@Override
public void handle(RoutingContext event) {
TestRunResults testRunResults = ts.get().getResults();
if (testRunResults == null) {
event.response().setStatusCode(204).end();
} else {
jsonResponse(event);
Map results = new HashMap<>();
for (Map.Entry entry : testRunResults.getResults().entrySet()) {
results.put(entry.getKey(), new ClassResult(entry.getValue()));
}
SuiteResult result = new SuiteResult(results);
event.response().end(JsonObject.mapFrom(result).encode());
}
}
});
}
public MultiMap jsonResponse(RoutingContext event) {
return event.response().headers().add(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy