diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java b/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java index 5a60cd98..657cbd64 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Connection.java @@ -36,6 +36,7 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import static com.microsoft.playwright.impl.LoggingSupport.logWithTimestamp; import static com.microsoft.playwright.impl.Serialization.gson; class Message { @@ -67,7 +68,11 @@ public class Connection { private int lastId = 0; private final Path srcDir; private final Map> callbacks = new HashMap<>(); - private final boolean isLogging = "pw:channel".equals(System.getenv("DEBUG")); + private static final boolean isLogging; + static { + String debug = System.getenv("DEBUG"); + isLogging = (debug != null) && debug.contains("pw:channel"); + } class Root extends ChannelOwner { Root(Connection connection) { @@ -156,7 +161,7 @@ public class Connection { } String messageString = gson().toJson(message); if (isLogging) { - System.err.println("SEND ► " + messageString); + logWithTimestamp("SEND ► " + messageString); } transport.send(messageString); return result; @@ -190,7 +195,7 @@ public class Connection { return; } if (isLogging) { - System.err.println("◀ RECV " + messageString); + logWithTimestamp("◀ RECV " + messageString); } Gson gson = gson(); Message message = gson.fromJson(messageString, Message.class); diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/LoggingSupport.java b/playwright/src/main/java/com/microsoft/playwright/impl/LoggingSupport.java index 5b3387c7..768d168f 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/LoggingSupport.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/LoggingSupport.java @@ -54,9 +54,14 @@ class LoggingSupport { } } - private void logApi(String message) { + static void logWithTimestamp(String message) { // This matches log format produced by the server. String timestamp = ZonedDateTime.now().format(timestampFormat); - System.err.println(timestamp + " pw:api " + message); + System.err.println(timestamp + " " + message); + } + + private void logApi(String message) { + // This matches log format produced by the server. + System.err.println("pw:api " + message); } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestChromium.java b/playwright/src/test/java/com/microsoft/playwright/TestChromium.java index 9afdb343..052fb71d 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestChromium.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestChromium.java @@ -41,6 +41,8 @@ public class TestChromium extends TestBase { // Do not create anything. } + private static int nextPort = 9339; + private static String wsEndpointFromUrl(String urlString) throws IOException { URL url = new URL(urlString); URLConnection request = url.openConnection(); @@ -52,7 +54,7 @@ public class TestChromium extends TestBase { @Test void shouldConnectToAnExistingCdpSession() throws IOException { - int port = 9339; + int port = nextPort++; try (Browser browserServer = browserType.launch(createLaunchOptions() .setArgs(asList("--remote-debugging-port=" + port)))) { Browser cdpBrowser = browserType.connectOverCDP("http://localhost:" + port); @@ -64,7 +66,7 @@ public class TestChromium extends TestBase { @Test void shouldConnectToAnExistingCdpSessionTwice() throws IOException { - int port = 9339; + int port = nextPort++; try (Browser browserServer = browserType.launch(createLaunchOptions() .setArgs(asList("--remote-debugging-port=" + port)))) { String endpointUrl = "http://localhost:" + port; @@ -90,7 +92,7 @@ public class TestChromium extends TestBase { @Test void shouldConnectOverAWsEndpoint() throws IOException { - int port = 9339; + int port = nextPort++; try (Browser browserServer = browserType.launch(createLaunchOptions() .setArgs(asList("--remote-debugging-port=" + port)))) { String wsEndpoint = wsEndpointFromUrl("http://localhost:" + port + "/json/version/"); diff --git a/playwright/src/test/java/com/microsoft/playwright/WebSocketServerImpl.java b/playwright/src/test/java/com/microsoft/playwright/WebSocketServerImpl.java index cd864ab9..a274b56b 100644 --- a/playwright/src/test/java/com/microsoft/playwright/WebSocketServerImpl.java +++ b/playwright/src/test/java/com/microsoft/playwright/WebSocketServerImpl.java @@ -22,15 +22,19 @@ import org.java_websocket.server.WebSocketServer; import java.net.InetSocketAddress; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; class WebSocketServerImpl extends WebSocketServer implements AutoCloseable { volatile ClientHandshake lastClientHandshake; private final Semaphore startSemaphore = new Semaphore(0); - static final int WS_SERVER_PORT = 8910; + private static final AtomicInteger nextWsServerPort = new AtomicInteger(8910); static WebSocketServerImpl create() throws InterruptedException { - WebSocketServerImpl result = new WebSocketServerImpl(new InetSocketAddress("localhost", WebSocketServerImpl.WS_SERVER_PORT)); + // FIXME: WebSocketServer.stop() doesn't release socket immediately and starting another server + // fails with "Address already in use", so we just allocate new port. + int port = nextWsServerPort.getAndIncrement(); + WebSocketServerImpl result = new WebSocketServerImpl(new InetSocketAddress("localhost", port)); result.start(); result.startSemaphore.acquire(); return result; @@ -61,6 +65,8 @@ class WebSocketServerImpl extends WebSocketServer implements AutoCloseable { @Override public void onError(WebSocket webSocket, Exception e) { + e.printStackTrace(); + startSemaphore.release(); } @Override