diff options
Diffstat (limited to 'vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestRunnerHandler.java')
-rw-r--r-- | vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestRunnerHandler.java | 165 |
1 files changed, 53 insertions, 112 deletions
diff --git a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestRunnerHandler.java b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestRunnerHandler.java index 4c359071fc9..62601e4dfa0 100644 --- a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestRunnerHandler.java +++ b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/TestRunnerHandler.java @@ -1,34 +1,27 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.testrunner; -import ai.vespa.hosted.api.TestDescriptor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.inject.Inject; +import com.yahoo.component.provider.ComponentRegistry; import com.yahoo.container.jdisc.EmptyResponse; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.container.jdisc.LoggingRequestHandler; +import com.yahoo.exception.ExceptionUtils; +import com.yahoo.restapi.MessageResponse; +import com.yahoo.restapi.SlimeJsonResponse; import com.yahoo.slime.Cursor; -import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; -import com.yahoo.slime.SlimeUtils; -import com.yahoo.vespa.testrunner.legacy.LegacyTestRunner; -import com.yahoo.vespa.testrunner.legacy.TestProfile; import com.yahoo.yolean.Exceptions; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.io.PrintStream; import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.Optional; import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.LogRecord; -import java.util.stream.Collectors; import static com.yahoo.jdisc.Response.Status; @@ -39,18 +32,16 @@ import static com.yahoo.jdisc.Response.Status; */ public class TestRunnerHandler extends LoggingRequestHandler { - private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json"; - - private final TestRunner junitRunner; - private final LegacyTestRunner testRunner; - private final boolean useOsgiMode; + private final TestRunner testRunner; @Inject - public TestRunnerHandler(Executor executor, TestRunner junitRunner, LegacyTestRunner testRunner) { + public TestRunnerHandler(Executor executor, ComponentRegistry<TestRunner> testRunners) { + this(executor, AggregateTestRunner.of(testRunners.allComponents())); + } + + TestRunnerHandler(Executor executor, TestRunner testRunner) { super(executor); - this.junitRunner = junitRunner; this.testRunner = testRunner; - this.useOsgiMode = junitRunner.isSupported(); } @Override @@ -60,81 +51,48 @@ public class TestRunnerHandler extends LoggingRequestHandler { case GET: return handleGET(request); case POST: return handlePOST(request); - default: return new Response(Status.METHOD_NOT_ALLOWED, "Method '" + request.getMethod() + "' is not supported"); + default: return new MessageResponse(Status.METHOD_NOT_ALLOWED, "Method '" + request.getMethod() + "' is not supported"); } } catch (IllegalArgumentException e) { - return new Response(Status.BAD_REQUEST, Exceptions.toMessageString(e)); + return new MessageResponse(Status.BAD_REQUEST, Exceptions.toMessageString(e)); } catch (Exception e) { log.log(Level.WARNING, "Unexpected error handling '" + request.getUri() + "'", e); - return new Response(Status.INTERNAL_SERVER_ERROR, Exceptions.toMessageString(e)); + return new MessageResponse(Status.INTERNAL_SERVER_ERROR, Exceptions.toMessageString(e)); } } private HttpResponse handleGET(HttpRequest request) { String path = request.getUri().getPath(); - if (path.equals("/tester/v1/log")) { - if (useOsgiMode) { + switch (path) { + case "/tester/v1/log": long fetchRecordsAfter = Optional.ofNullable(request.getProperty("after")) - .map(Long::parseLong) - .orElse(-1L); - - List<LogRecord> logRecords = Optional.ofNullable(junitRunner.getReport()) - .map(TestReport::logLines) - .orElse(Collections.emptyList()).stream() - .filter(record -> record.getSequenceNumber()>fetchRecordsAfter) - .collect(Collectors.toList()); - return new SlimeJsonResponse(logToSlime(logRecords)); - } else { - return new SlimeJsonResponse(logToSlime(testRunner.getLog(request.hasProperty("after") - ? Long.parseLong(request.getProperty("after")) - : -1))); - } - } else if (path.equals("/tester/v1/status")) { - if (useOsgiMode) { - log.info("Responding with status " + junitRunner.getStatus()); - return new Response(junitRunner.getStatus().name()); - } else { + .map(Long::parseLong) + .orElse(-1L); + return new SlimeJsonResponse(logToSlime(testRunner.getLog(fetchRecordsAfter))); + case "/tester/v1/status": log.info("Responding with status " + testRunner.getStatus()); - return new Response(testRunner.getStatus().name()); - } - } else if (path.equals("/tester/v1/report")) { - if (useOsgiMode) { - String report = junitRunner.getReportAsJson(); - return new SlimeJsonResponse(SlimeUtils.jsonToSlime(report)); - } else { - return new EmptyResponse(200); - } + return new MessageResponse(testRunner.getStatus().name()); + case "/tester/v1/report": + TestReport report = testRunner.getReport(); + if (report == null) + return new EmptyResponse(200); + + return new SlimeJsonResponse(toSlime(report)); } - return new Response(Status.NOT_FOUND, "Not found: " + request.getUri().getPath()); + return new MessageResponse(Status.NOT_FOUND, "Not found: " + request.getUri().getPath()); } private HttpResponse handlePOST(HttpRequest request) throws IOException { final String path = request.getUri().getPath(); if (path.startsWith("/tester/v1/run/")) { String type = lastElement(path); - TestProfile testProfile = TestProfile.valueOf(type.toUpperCase() + "_TEST"); + TestRunner.Suite testSuite = TestRunner.Suite.valueOf(type.toUpperCase() + "_TEST"); byte[] config = request.getData().readAllBytes(); - if (useOsgiMode) { - junitRunner.executeTests(categoryFromProfile(testProfile), config); - log.info("Started tests of type " + type + " and status is " + junitRunner.getStatus()); - return new Response("Successfully started " + type + " tests"); - } else { - testRunner.test(testProfile, config); - log.info("Started tests of type " + type + " and status is " + testRunner.getStatus()); - return new Response("Successfully started " + type + " tests"); - } - } - return new Response(Status.NOT_FOUND, "Not found: " + request.getUri().getPath()); - } - - TestDescriptor.TestCategory categoryFromProfile(TestProfile testProfile) { - switch(testProfile) { - case SYSTEM_TEST: return TestDescriptor.TestCategory.systemtest; - case STAGING_SETUP_TEST: return TestDescriptor.TestCategory.stagingsetuptest; - case STAGING_TEST: return TestDescriptor.TestCategory.stagingtest; - case PRODUCTION_TEST: return TestDescriptor.TestCategory.productiontest; - default: throw new RuntimeException("Unknown test profile: " + testProfile.name()); + testRunner.test(testSuite, config); + log.info("Started tests of type " + type + " and status is " + testRunner.getStatus()); + return new MessageResponse("Successfully started " + type + " tests"); } + return new MessageResponse(Status.NOT_FOUND, "Not found: " + request.getUri().getPath()); } private static String lastElement(String path) { @@ -177,48 +135,31 @@ public class TestRunnerHandler extends LoggingRequestHandler { : "error"; } - private static class SlimeJsonResponse extends HttpResponse { - private final Slime slime; + private static Slime toSlime(TestReport testReport) { + var slime = new Slime(); + var root = slime.setObject(); + if (testReport == null) + return slime; - private SlimeJsonResponse(Slime slime) { - super(200); - this.slime = slime; - } + var summary = root.setObject("summary"); + summary.setLong("total", testReport.totalCount); + summary.setLong("success", testReport.successCount); + summary.setLong("failed", testReport.failedCount); + summary.setLong("ignored", testReport.ignoredCount); + summary.setLong("aborted", testReport.abortedCount); + var failureRoot = summary.setArray("failures"); + testReport.failures.forEach(failure -> serializeFailure(failure, failureRoot.addObject())); - @Override - public void render(OutputStream outputStream) throws IOException { - new JsonFormat(true).encode(outputStream, slime); - } + var output = root.setArray("output"); + testReport.logLines.forEach(lr -> output.addString(lr.getMessage())); - @Override - public String getContentType() { - return CONTENT_TYPE_APPLICATION_JSON; - } + return slime; } - private static class Response extends HttpResponse { - private static final ObjectMapper objectMapper = new ObjectMapper(); - private final String message; - - private Response(String response) { - this(200, response); - } - - private Response(int statusCode, String message) { - super(statusCode); - this.message = message; - } - - @Override - public void render(OutputStream outputStream) throws IOException { - ObjectNode objectNode = objectMapper.createObjectNode(); - objectNode.put("message", message); - objectMapper.writeValue(outputStream, objectNode); - } - - @Override - public String getContentType() { - return CONTENT_TYPE_APPLICATION_JSON; - } + private static void serializeFailure(TestReport.Failure failure, Cursor slime) { + slime.setString("testName", failure.testId()); + slime.setString("testError",failure.exception().getMessage()); + slime.setString("exception", ExceptionUtils.getStackTraceAsString(failure.exception())); } + } |