diff options
5 files changed, 74 insertions, 74 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java index 52e5431b552..fb7a3fc4ba5 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java @@ -13,11 +13,6 @@ import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.zone.RoutingMethod; import com.yahoo.config.provision.zone.ZoneId; import com.yahoo.log.LogLevel; -import com.yahoo.security.KeyAlgorithm; -import com.yahoo.security.KeyUtils; -import com.yahoo.security.SignatureAlgorithm; -import com.yahoo.security.X509CertificateBuilder; -import com.yahoo.security.X509CertificateUtils; import com.yahoo.vespa.hosted.controller.Application; import com.yahoo.vespa.hosted.controller.Controller; import com.yahoo.vespa.hosted.controller.Instance; @@ -48,12 +43,9 @@ import com.yahoo.vespa.hosted.controller.routing.RoutingPolicy; import com.yahoo.vespa.hosted.controller.routing.context.DeploymentRoutingContext; import com.yahoo.yolean.Exceptions; -import javax.security.auth.x500.X500Principal; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.UncheckedIOException; -import java.math.BigInteger; -import java.security.KeyPair; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; @@ -65,7 +57,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.UUID; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.logging.Level; @@ -95,7 +86,6 @@ import static com.yahoo.vespa.hosted.controller.deployment.Step.deployReal; import static com.yahoo.vespa.hosted.controller.deployment.Step.deployTester; import static com.yahoo.vespa.hosted.controller.deployment.Step.installTester; import static com.yahoo.vespa.hosted.controller.deployment.Step.report; -import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.FINE; import static java.util.logging.Level.INFO; @@ -671,6 +661,7 @@ public class InternalStepRunner implements StepRunner { logger.log(INFO, "The test package should either contain basic HTTP tests under 'tests/<suite-name>/', " + "or a Java test bundle under 'components/' with at least one test with the annotation " + "for this suite. See docs.vespa.ai/en/testing.html for details."); + controller.jobController().updateTestReport(id); return Optional.of(noTests); } case SUCCESS: diff --git a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/AggregateTestRunner.java b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/AggregateTestRunner.java index 6e3393b2761..15aeef18013 100644 --- a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/AggregateTestRunner.java +++ b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/AggregateTestRunner.java @@ -4,9 +4,7 @@ package com.yahoo.vespa.testrunner; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.LogRecord; /** @@ -15,7 +13,8 @@ import java.util.logging.LogRecord; public class AggregateTestRunner implements TestRunner { private final List<TestRunner> wrapped; - private final AtomicInteger current = new AtomicInteger(-1); + private int current = -1; + private final Object monitor = new Object(); private AggregateTestRunner(List<TestRunner> testRunners) { this.wrapped = testRunners; @@ -28,65 +27,77 @@ public class AggregateTestRunner implements TestRunner { @Override public Collection<LogRecord> getLog(long after) { ArrayList<LogRecord> records = new ArrayList<>(); - for (int i = 0; i <= current.get() && i < wrapped.size(); i++) - records.addAll(wrapped.get(i).getLog(after)); - + synchronized (monitor) { + for (int i = 0; i <= current && i < wrapped.size(); i++) + records.addAll(wrapped.get(i).getLog(after)); + } return records; } @Override public Status getStatus() { - if (current.get() == -1) - return Status.NOT_STARTED; - - Status status = Status.NO_TESTS; - for (int i = 0; i <= current.get(); i++) { - if (i == wrapped.size()) - return status; - - Status next = wrapped.get(i).getStatus(); - status = status.ordinal() < next.ordinal() ? status : next; + synchronized (monitor) { + if (current == -1) + return Status.NOT_STARTED; + + Status status = Status.NO_TESTS; + for (int i = 0; i <= current; i++) { + if (i == wrapped.size()) + return status; + + Status next = wrapped.get(i).getStatus(); + status = status.ordinal() < next.ordinal() ? status : next; + } + return Status.RUNNING; } - return Status.RUNNING; } @Override public CompletableFuture<?> test(Suite suite, byte[] config) { - if (0 <= current.get() && current.get() < wrapped.size()) - throw new IllegalStateException("Tests already running, should not attempt to start now"); - - current.set(-1); - CompletableFuture<?> aggregate = new CompletableFuture<>(); - CompletableFuture<?> vessel = CompletableFuture.completedFuture(null); - runNext(suite, config, vessel, aggregate); - return aggregate; + synchronized (monitor) { + if (0 <= current && current < wrapped.size()) + throw new IllegalStateException("Tests already running, should not attempt to start now"); + + current = -1; + CompletableFuture<?> aggregate = new CompletableFuture<>(); + CompletableFuture<?> vessel = CompletableFuture.completedFuture(null); + runNext(suite, config, vessel, aggregate); + return aggregate; + } } private void runNext(Suite suite, byte[] config, CompletableFuture<?> vessel, CompletableFuture<?> aggregate) { vessel.whenComplete((__, ___) -> { - int next = current.incrementAndGet(); - if (next == wrapped.size()) - aggregate.complete(null); - else - runNext(suite, config, wrapped.get(next).test(suite, config), aggregate); + synchronized (monitor) { + if (++current < wrapped.size()) + runNext(suite, config, wrapped.get(current).test(suite, config), aggregate); + else + aggregate.complete(null); + } }); } @Override public TestReport getReport() { - return wrapped.stream().map(TestRunner::getReport).filter(Objects::nonNull) - .reduce(AggregateTestRunner::merge).orElse(null); + TestReport report = null; + synchronized (monitor) { + for (int i = 0; i < current && i < wrapped.size(); i++) + report = merge(report, wrapped.get(i).getReport()); + } + return report; } static TestReport merge(TestReport first, TestReport second) { - return TestReport.builder() - .withAbortedCount(first.abortedCount + second.abortedCount) - .withFailedCount(first.failedCount + second.failedCount) - .withIgnoredCount(first.ignoredCount + second.ignoredCount) - .withSuccessCount(first.successCount + second.successCount) - .withFailures(merged(first.failures, second.failures)) - .withLogs(merged(first.logLines, second.logLines)) - .build(); + return first == null ? second + : second == null ? first + : TestReport.builder() + .withAbortedCount(first.abortedCount + second.abortedCount) + .withFailedCount(first.failedCount + second.failedCount) + .withIgnoredCount(first.ignoredCount + second.ignoredCount) + .withSuccessCount(first.successCount + second.successCount) + .withFailures(merged(first.failures, second.failures)) + .withLogs(merged(first.logLines, second.logLines)) + .build(); } static <T> List<T> merged(List<T> first, List<T> second) { diff --git a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java index 90b3f972a3a..9bbba2d6c2a 100644 --- a/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java +++ b/vespa-osgi-testrunner/src/main/java/com/yahoo/vespa/testrunner/JunitRunner.java @@ -7,16 +7,14 @@ import ai.vespa.cloud.Zone; import ai.vespa.hosted.api.TestDescriptor; import ai.vespa.hosted.cd.InconclusiveTestException; import ai.vespa.hosted.cd.internal.TestRuntimeProvider; -import com.yahoo.component.annotation.Inject; import com.yahoo.component.AbstractComponent; +import com.yahoo.component.annotation.Inject; import com.yahoo.io.IOUtils; import com.yahoo.jdisc.application.OsgiFramework; import com.yahoo.vespa.defaults.Defaults; import org.junit.jupiter.engine.JupiterTestEngine; -import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.Launcher; -import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.core.LauncherConfig; import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherFactory; @@ -37,9 +35,10 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; -import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.stream.Collectors.toList; + /** * @author mortent */ @@ -163,7 +162,7 @@ public class JunitRunner extends AbstractComponent implements TestRunner { private List<Class<?>> loadClasses(Bundle bundle, TestDescriptor testDescriptor, TestDescriptor.TestCategory testCategory) { List<Class<?>> testClasses = testDescriptor.getConfiguredTests(testCategory).stream() .map(className -> loadClass(bundle, className)) - .collect(Collectors.toList()); + .collect(toList()); StringBuffer buffer = new StringBuffer(); testClasses.forEach(cl -> buffer.append("\t").append(cl.toString()).append(" / ").append(cl.getClassLoader().toString()).append("\n")); @@ -180,24 +179,18 @@ public class JunitRunner extends AbstractComponent implements TestRunner { } private TestReport launchJunit(List<Class<?>> testClasses, boolean isProductionTest) { - LauncherDiscoveryRequest discoveryRequest = LauncherDiscoveryRequestBuilder.request() - .selectors(testClasses.stream().map(DiscoverySelectors::selectClass).collect(Collectors.toList())) - .build(); - - var launcherConfig = LauncherConfig.builder() - .addTestEngines(new JupiterTestEngine()) - - .build(); - Launcher launcher = LauncherFactory.create(launcherConfig); - - // Create log listener: var logListener = new VespaJunitLogListener(record -> logRecords.put(record.getSequenceNumber(), record)); - // Create a summary listener: var summaryListener = new SummaryGeneratingListener(); + + Launcher launcher = LauncherFactory.create(LauncherConfig.builder().addTestEngines(new JupiterTestEngine()).build()); launcher.registerTestExecutionListeners(logListener, summaryListener); - // Execute request - launcher.execute(discoveryRequest); + launcher.execute(LauncherDiscoveryRequestBuilder.request() + .selectors(testClasses.stream() + .map(DiscoverySelectors::selectClass) + .collect(toList())) + .build()); + var report = summaryListener.getSummary(); var failures = report.getFailures().stream() .map(failure -> { @@ -205,11 +198,12 @@ public class JunitRunner extends AbstractComponent implements TestRunner { return new TestReport.Failure(VespaJunitLogListener.toString(failure.getTestIdentifier().getUniqueIdObject()), failure.getException()); }) - .collect(Collectors.toList()); + .collect(toList()); long inconclusive = isProductionTest ? failures.stream() .filter(failure -> failure.exception() instanceof InconclusiveTestException) .count() : 0; + return TestReport.builder() .withSuccessCount(report.getTestsSucceededCount()) .withAbortedCount(report.getTestsAbortedCount()) diff --git a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java index 14e139b3fbf..8bd72d35737 100644 --- a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java +++ b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/AggregateTestRunnerTest.java @@ -136,8 +136,10 @@ class AggregateTestRunnerTest { .build(); first.report = report; assertSame(report, runner.getReport()); - second.report = report; + assertSame(report, runner.getReport()); + + second.future.complete(null); TestReport merged = runner.getReport(); assertEquals(List.of(record1, record1), merged.logLines); assertEquals(List.of(failure, failure), merged.failures); @@ -145,6 +147,7 @@ class AggregateTestRunnerTest { assertEquals(8, merged.ignoredCount); assertEquals(4, merged.failedCount); assertEquals(2, merged.abortedCount); + } @Test @@ -171,9 +174,9 @@ class AggregateTestRunnerTest { catch (Exception e) { TestReport.trimStackTraces(e, "org.junit.platform.launcher.core.SessionPerRequestLauncher"); assertEquals("java.lang.RuntimeException: java.lang.RuntimeException: inner\n" + - "\tat com.yahoo.vespa.testrunner.AggregateTestRunnerTest.testStackTrimming(AggregateTestRunnerTest.java:168)\n" + + "\tat com.yahoo.vespa.testrunner.AggregateTestRunnerTest.testStackTrimming(AggregateTestRunnerTest.java:171)\n" + "Caused by: java.lang.RuntimeException: inner\n" + - "\tat com.yahoo.vespa.testrunner.AggregateTestRunnerTest.testStackTrimming(AggregateTestRunnerTest.java:165)\n", + "\tat com.yahoo.vespa.testrunner.AggregateTestRunnerTest.testStackTrimming(AggregateTestRunnerTest.java:168)\n", ExceptionUtils.getStackTraceAsString(e)); } } diff --git a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/TestRunnerHandlerTest.java b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/TestRunnerHandlerTest.java index 49dd2b20797..7b75f1cd4bd 100644 --- a/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/TestRunnerHandlerTest.java +++ b/vespa-osgi-testrunner/src/test/java/com/yahoo/vespa/testrunner/TestRunnerHandlerTest.java @@ -6,6 +6,7 @@ import com.yahoo.component.provider.ComponentRegistry; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; import com.yahoo.test.json.JsonTestHelper; +import com.yahoo.vespa.testrunner.TestRunner.Suite; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -23,7 +24,6 @@ import java.util.stream.Collectors; import static com.yahoo.jdisc.http.HttpRequest.Method.GET; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -57,6 +57,7 @@ class TestRunnerHandlerTest { @Test public void createsCorrectTestReport() throws IOException { + aggregateRunner.test(Suite.SYSTEM_TEST, new byte[0]); HttpResponse response = testRunnerHandler.handle(HttpRequest.createTestRequest("http://localhost:1234/tester/v1/report", GET)); ByteArrayOutputStream out = new ByteArrayOutputStream(); response.render(out); |