From fba4eb4d67e76fa748d65c88bd57029db391ca97 Mon Sep 17 00:00:00 2001 From: Weimin Yu Date: Thu, 3 Mar 2022 14:43:32 -0500 Subject: [PATCH] Fix hanging test (#1536) * Fix hanging test Tests using the TestServerExtension may hang forever if an underlying component (e.g., testcontainer for psql) fails. This may be the cause of the some kokoro runs that timeed out after three hours. --- .../webdriver/TestServerExtension.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/src/test/java/google/registry/webdriver/TestServerExtension.java b/core/src/test/java/google/registry/webdriver/TestServerExtension.java index f582bf094..3851b2a22 100644 --- a/core/src/test/java/google/registry/webdriver/TestServerExtension.java +++ b/core/src/test/java/google/registry/webdriver/TestServerExtension.java @@ -33,6 +33,7 @@ import google.registry.testing.UserInfo; import java.net.URL; import java.net.UnknownHostException; import java.nio.file.Path; +import java.time.Duration; import java.util.Optional; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; @@ -53,6 +54,8 @@ import org.junit.jupiter.api.extension.ExtensionContext; */ public final class TestServerExtension implements BeforeEachCallback, AfterEachCallback { + private static final Duration SERVER_STATUS_POLLING_INTERVAL = Duration.ofSeconds(5); + private final ImmutableList fixtures; private final AppEngineExtension appEngineExtension; private final BlockingQueue> jobs = new LinkedBlockingDeque<>(); @@ -107,8 +110,11 @@ public final class TestServerExtension implements BeforeEachCallback, AfterEachC serverThread = new Thread(server); synchronized (this) { serverThread.start(); - while (!server.isRunning) { - this.wait(); + while (server.serverStatus.equals(ServerStatus.NOT_STARTED)) { + this.wait(SERVER_STATUS_POLLING_INTERVAL.toMillis()); + } + if (server.serverStatus.equals(ServerStatus.FAILED)) { + throw new RuntimeException("TestServer failed to start. See log for details."); } } } @@ -163,6 +169,12 @@ public final class TestServerExtension implements BeforeEachCallback, AfterEachC return job.get(); } + enum ServerStatus { + NOT_STARTED, + RUNNING, + FAILED + } + private final class Server implements Runnable { private ExtensionContext context; @@ -171,7 +183,7 @@ public final class TestServerExtension implements BeforeEachCallback, AfterEachC this.context = context; } - private volatile boolean isRunning = false; + private volatile ServerStatus serverStatus = ServerStatus.NOT_STARTED; @Override public void run() { @@ -185,6 +197,7 @@ public final class TestServerExtension implements BeforeEachCallback, AfterEachC appEngineExtension.afterEach(context); } } catch (Throwable e) { + serverStatus = ServerStatus.FAILED; throw new RuntimeException(e); } } @@ -196,7 +209,7 @@ public final class TestServerExtension implements BeforeEachCallback, AfterEachC testServer.start(); System.out.printf("TestServerExtension is listening on: %s\n", testServer.getUrl("/")); synchronized (TestServerExtension.this) { - isRunning = true; + serverStatus = ServerStatus.RUNNING; TestServerExtension.this.notify(); } try {