Skip to content

Commit 9a36306

Browse files
committed
build: always run test in random port(0)
1 parent 493a953 commit 9a36306

File tree

8 files changed

+62
-34
lines changed

8 files changed

+62
-34
lines changed

.github/workflows/full-build.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ jobs:
2626
- name: Build
2727
run: mvn -B package -P gradlePlugin
2828
env:
29-
BUILD_PORT: 0
30-
BUILD_SECURE_PORT: 0
3129
BUILD_LOG_LEVEL: 'ERROR'
3230
- name: Tests
3331
uses: mikepenz/action-junit-report@v5

.github/workflows/quick-build.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ jobs:
2727
- name: Install
2828
run: mvn install -DskipTests -q -B
2929
env:
30-
BUILD_PORT: 0
31-
BUILD_SECURE_PORT: 0
3230
BUILD_LOG_LEVEL: 'ERROR'
3331
- name: Build
3432
run: mvn package

jooby/src/main/java/io/jooby/ServerOptions.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import static java.util.Spliterators.spliteratorUnknownSize;
99
import static java.util.stream.StreamSupport.stream;
1010

11-
import java.io.IOException;
12-
import java.net.ServerSocket;
1311
import java.security.Security;
1412
import java.util.ArrayList;
1513
import java.util.Arrays;
@@ -271,7 +269,7 @@ public int getPort() {
271269
* @return This options.
272270
*/
273271
public @NonNull ServerOptions setPort(int port) {
274-
this.port = port == 0 ? randomPort() : port;
272+
this.port = Math.max(0, port);
275273
return this;
276274
}
277275

@@ -303,7 +301,7 @@ public boolean isSSLEnabled() {
303301
if (securePort == null) {
304302
this.securePort = null;
305303
} else {
306-
this.securePort = securePort == 0 ? randomPort() : securePort;
304+
this.securePort = Math.max(0, securePort);
307305
}
308306
return this;
309307
}
@@ -657,13 +655,4 @@ public ServerOptions setExpectContinue(@Nullable Boolean expectContinue) {
657655
}
658656
return null;
659657
}
660-
661-
private static int randomPort() {
662-
try (ServerSocket socket = new ServerSocket(0)) {
663-
socket.setReuseAddress(true);
664-
return socket.getLocalPort();
665-
} catch (IOException x) {
666-
throw SneakyThrows.propagate(x);
667-
}
668-
}
669658
}

modules/jooby-jetty/src/main/java/io/jooby/jetty/JettyServer.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,19 +163,21 @@ public io.jooby.Server start(@NonNull Jooby... application) {
163163
connectionFactories.addAll(http2.configure(httpConf));
164164
}
165165

166+
ServerConnector httpConector = null;
166167
if (!options.isHttpsOnly()) {
167-
var http =
168+
httpConector =
168169
new ServerConnector(
169170
server,
170171
acceptors,
171172
selectors,
172173
connectionFactories.toArray(new ConnectionFactory[0]));
173-
http.setPort(options.getPort());
174-
http.setHost(options.getHost());
174+
httpConector.setPort(options.getPort());
175+
httpConector.setHost(options.getHost());
175176

176-
server.addConnector(http);
177+
server.addConnector(httpConector);
177178
}
178179

180+
ServerConnector secureConnector = null;
179181
if (options.isSSLEnabled()) {
180182
var classLoader = applications.get(0).getClassLoader();
181183
var sslContextFactory = new SslContextFactory.Server();
@@ -208,7 +210,7 @@ public io.jooby.Server start(@NonNull Jooby... application) {
208210
}
209211
secureConnectionFactories.add(new HttpConnectionFactory(httpsConf));
210212

211-
var secureConnector =
213+
secureConnector =
212214
new ServerConnector(
213215
server,
214216
acceptors,
@@ -272,6 +274,15 @@ public io.jooby.Server start(@NonNull Jooby... application) {
272274
server.setHandler(context);
273275
server.start();
274276

277+
// --- EXTRACT OS-ASSIGNED PORTS ---
278+
if (httpConector != null) {
279+
options.setPort(httpConector.getLocalPort());
280+
}
281+
if (secureConnector != null) {
282+
options.setSecurePort(secureConnector.getLocalPort());
283+
}
284+
// ---------------------------------
285+
275286
fireReady(applications);
276287
} catch (Exception x) {
277288
if (io.jooby.Server.isAddressInUse(x.getCause())) {

modules/jooby-netty/src/main/java/io/jooby/netty/NettyServer.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,15 @@ public Server start(@NonNull Jooby... application) {
166166
var http =
167167
newBootstrap(
168168
allocator, transport, newPipeline(options, null, http2, grpcProcessor), eventLoop);
169-
http.bind(options.getHost(), options.getPort()).get();
169+
170+
var httpFuture = http.bind(options.getHost(), options.getPort());
171+
if (options.getPort() == 0) {
172+
httpFuture.get(); // Wait for bind to complete
173+
java.net.SocketAddress address = httpFuture.channel().localAddress();
174+
if (address instanceof java.net.InetSocketAddress) {
175+
options.setPort(((java.net.InetSocketAddress) address).getPort());
176+
}
177+
}
170178
}
171179

172180
if (options.isSSLEnabled()) {
@@ -184,7 +192,14 @@ public Server start(@NonNull Jooby... application) {
184192
newPipeline(options, sslContext, http2, grpcProcessor),
185193
eventLoop);
186194
portInUse = options.getSecurePort();
187-
https.bind(options.getHost(), portInUse).get();
195+
var httpsFuture = https.bind(options.getHost(), portInUse);
196+
if (portInUse == 0) {
197+
httpsFuture.get();
198+
var address = httpsFuture.channel().localAddress();
199+
if (address instanceof java.net.InetSocketAddress inetSocketAddress) {
200+
options.setSecurePort(inetSocketAddress.getPort());
201+
}
202+
}
188203
} else if (options.isHttpsOnly()) {
189204
throw new StartupException("Server configured for httpsOnly, but ssl options not set");
190205
}

modules/jooby-undertow/src/main/java/io/jooby/undertow/UndertowServer.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,18 +178,35 @@ public Server start(@NonNull Jooby... application) {
178178
.ifPresent(
179179
clientAuth -> builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE, clientAuth));
180180
} else if (options.isHttpsOnly()) {
181-
throw new StartupException("Server configured for httpsOnly, but ssl options not set");
181+
throw new StartupException("Server configured for httpsOnly, but ssl options are not set");
182182
}
183183
fireStart(applications, worker);
184184
server = builder.build();
185185
server.start();
186186

187+
// --- EXTRACT OS-ASSIGNED PORTS ---
188+
for (var info : server.getListenerInfo()) {
189+
var address = info.getAddress();
190+
if (address instanceof java.net.InetSocketAddress inetSocketAddress) {
191+
int actualPort = inetSocketAddress.getPort();
192+
193+
if ("https".equalsIgnoreCase(info.getProtcol())) {
194+
options.setSecurePort(actualPort);
195+
} else {
196+
options.setPort(actualPort);
197+
}
198+
}
199+
}
200+
// ---------------------------------
201+
187202
fireReady(applications);
188203

189204
return this;
190205
} catch (Exception x) {
191206
Throwable sourceException = x;
192207
Throwable cause = Optional.ofNullable(x.getCause()).orElse(x);
208+
cause.printStackTrace();
209+
System.out.println(options.toString());
193210
if (Server.isAddressInUse(cause)) {
194211
sourceException = new BindException("Address already in use: " + portInUse);
195212
}

tests/src/test/java/io/jooby/i3783/Issue3783.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import okhttp3.FormBody;
1414

1515
public class Issue3783 {
16-
1716
@ServerTest
1817
public void shouldAllowToSetMaxFormFields(ServerTestRunner runner) {
1918
runner

tests/src/test/java/io/jooby/junit/ServerTestRunner.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,19 @@ public void ready(SneakyThrows.Consumer2<WebClient, WebClient> onReady) {
103103
// HTTP/2 is off while testing unless explicit set
104104
ServerOptions options = server.getOptions();
105105
options.setHttp2(Optional.ofNullable(options.isHttp2()).orElse(Boolean.FALSE));
106-
options.setPort(Integer.parseInt(System.getenv().getOrDefault("BUILD_PORT", "9999")));
107-
this.allocatedPort = options.getPort();
108-
WebClient https;
106+
options.setPort(0);
109107
if (options.isSSLEnabled()) {
110-
options.setSecurePort(
111-
Integer.parseInt(System.getenv().getOrDefault("BUILD_SECURE_PORT", "9443")));
112-
https = new WebClient("https", options.getSecurePort(), followRedirects);
113-
} else {
114-
https = null;
108+
options.setSecurePort(0);
115109
}
110+
WebClient https = null;
116111
try {
117112
MutedServer.mute(server).start(app);
113+
this.allocatedPort = options.getPort();
114+
if (options.isSSLEnabled()) {
115+
https = new WebClient("https", options.getSecurePort(), followRedirects);
116+
} else {
117+
https = null;
118+
}
118119
if (options.isHttpsOnly()) {
119120
onReady.accept(null, https);
120121
} else {

0 commit comments

Comments
 (0)