Skip to content

Commit d307d97

Browse files
committed
Support getting bound local port from Application and avoid using fixed port in unit tests
1 parent 5761c67 commit d307d97

File tree

4 files changed

+90
-7
lines changed

4 files changed

+90
-7
lines changed

core/src/main/java/io/confluent/rest/Application.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import com.fasterxml.jackson.jaxrs.base.JsonParseExceptionMapper;
2020

2121
import io.confluent.common.config.ConfigException;
22+
23+
import org.eclipse.jetty.server.Connector;
2224
import org.eclipse.jetty.server.Handler;
2325
import org.eclipse.jetty.server.NetworkTrafficServerConnector;
2426
import org.eclipse.jetty.server.Server;
@@ -121,6 +123,12 @@ public Server createServer() throws RestConfigException {
121123
ServletContainer servletContainer = new ServletContainer(resourceConfig);
122124
ServletHolder servletHolder = new ServletHolder(servletContainer);
123125
server = new Server() {
126+
@Override
127+
protected void doStart() throws Exception {
128+
super.doStart();
129+
Application.this.onStarted();
130+
}
131+
124132
@Override
125133
protected void doStop() throws Exception {
126134
super.doStop();
@@ -239,6 +247,26 @@ protected void doStop() throws Exception {
239247
return server;
240248
}
241249

250+
/**
251+
* Get the local ports that were bound for the listeners.
252+
* @return an List containing the local ports
253+
*/
254+
public List<Integer> localPorts() {
255+
List<Integer> ports = new ArrayList<>();
256+
for(Connector connector : server.getConnectors()) {
257+
if (!(connector instanceof NetworkTrafficServerConnector)) {
258+
throw new RuntimeException(
259+
String.format(
260+
"Expected NetworkTrafficServerConnector for listener but found %s",
261+
connector.getClass()
262+
)
263+
);
264+
}
265+
ports.add(((NetworkTrafficServerConnector) connector).getLocalPort());
266+
}
267+
return ports;
268+
}
269+
242270
// TODO: delete deprecatedPort parameter when `PORT_CONFIG` is deprecated. It's only used to support the deprecated
243271
// configuration.
244272
public static List<URI> parseListeners(List<String> listenersConfig, int deprecatedPort,
@@ -352,6 +380,10 @@ public void stop() throws Exception {
352380
server.stop();
353381
}
354382

383+
public void onStarted() {
384+
385+
}
386+
355387
/**
356388
* Shutdown hook that is invoked after the Jetty server has processed the shutdown request,
357389
* stopped accepting new connections, and tried to gracefully finish existing requests. At this

core/src/test/java/io/confluent/rest/ApplicationTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,21 @@
1616

1717
package io.confluent.rest;
1818

19+
import io.confluent.common.config.ConfigDef;
1920
import io.confluent.common.config.ConfigException;
2021
import org.junit.Test;
2122

2223
import java.net.URI;
2324
import java.util.ArrayList;
2425
import java.util.Arrays;
26+
import java.util.Collections;
2527
import java.util.List;
28+
import java.util.Map;
29+
30+
import javax.ws.rs.core.Configurable;
2631

2732
import static org.junit.Assert.assertEquals;
33+
import static org.junit.Assert.assertTrue;
2834

2935
public class ApplicationTest {
3036
@Test
@@ -79,6 +85,48 @@ public void testParseListenersNoPort() {
7985
List<URI> listeners = Application.parseListeners(listenersConfig, -1, Arrays.asList("http", "https"), "http");
8086
}
8187

88+
@Test
89+
public void zeroForPortShouldHaveNonZeroLocalPort() throws Exception {
90+
TestRestConfig config = new TestRestConfig(
91+
Collections.singletonMap(RestConfig.PORT_CONFIG, "0")
92+
);
93+
TestApplication testApp = new TestApplication(config);
94+
testApp.start();
95+
List<Integer> localPorts = testApp.localPorts();
96+
assertEquals(1, localPorts.size());
97+
// Validate not only that it isn't zero, but also a valid value
98+
assertTrue("Should have a valid local port value", localPorts.get(0) > 0);
99+
testApp.stop();
100+
testApp.join();
101+
}
102+
103+
private class TestApplication extends Application<TestRestConfig> {
104+
TestApplication(TestRestConfig config) {
105+
super(config);
106+
}
107+
108+
@Override
109+
public void setupResources(Configurable<?> config, TestRestConfig appConfig) {
110+
// intentionally left blank
111+
}
112+
}
113+
114+
private static class TestRestConfig extends RestConfig {
115+
private static ConfigDef config;
116+
117+
static {
118+
config = baseConfigDef();
119+
}
120+
121+
public TestRestConfig() {
122+
super(config);
123+
}
124+
125+
public TestRestConfig(Map<?, ?> props) {
126+
super(config, props);
127+
}
128+
}
129+
82130
private void assertExpectedUri(URI uri, String scheme, String host, int port) {
83131
assertEquals("Scheme should be " + scheme, scheme, uri.getScheme());
84132
assertEquals("Host should be " + host, host, uri.getHost());

core/src/test/java/io/confluent/rest/ExceptionHandlingTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class ExceptionHandlingTest {
5151
public void setUp() throws Exception {
5252
Properties props = new Properties();
5353
props.setProperty("debug", "false");
54+
props.setProperty(RestConfig.PORT_CONFIG, "0");
5455
config = new TestRestConfig(props);
5556
app = new ExceptionApplication(config);
5657
app.start();
@@ -65,7 +66,7 @@ public void tearDown() throws Exception {
6566
private void testGetException(String path, int expectedStatus, int expectedErrorCode,
6667
String expectedMessage) {
6768
Response response = ClientBuilder.newClient(app.resourceConfig.getConfiguration())
68-
.target("http://localhost:" + config.getInt(RestConfig.PORT_CONFIG))
69+
.target("http://localhost:" + app.localPorts().get(0))
6970
.path(path)
7071
.request()
7172
.get();
@@ -79,7 +80,7 @@ private void testGetException(String path, int expectedStatus, int expectedError
7980
private void testPostException(String path, Entity entity, int expectedStatus, int expectedErrorCode,
8081
String expectedMessage) {
8182
Response response = ClientBuilder.newClient(app.resourceConfig.getConfiguration())
82-
.target("http://localhost:" + config.getInt(RestConfig.PORT_CONFIG))
83+
.target("http://localhost:" + app.localPorts().get(0))
8384
.path(path)
8485
.request()
8586
.post(entity);

core/src/test/java/io/confluent/rest/ShutdownTest.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class ShutdownTest {
3535
public void testShutdownHook() throws Exception {
3636
Properties props = new Properties();
3737
props.put("shutdown.graceful.ms", "50");
38+
props.put(RestConfig.PORT_CONFIG, "0");
3839
ShutdownApplication app = new ShutdownApplication(new TestRestConfig(props));
3940
app.start();
4041

@@ -49,11 +50,12 @@ public void testShutdownHook() throws Exception {
4950
public void testGracefulShutdown() throws Exception {
5051
Properties props = new Properties();
5152
props.put("shutdown.graceful.ms", "50");
53+
props.put(RestConfig.PORT_CONFIG, "0");
5254
final TestRestConfig config = new TestRestConfig(props);
5355
ShutdownApplication app = new ShutdownApplication(config);
5456
app.start();
5557

56-
RequestThread req = new RequestThread(config);
58+
RequestThread req = new RequestThread(app.localPorts().get(0));
5759
req.start();
5860
app.resource.requestProcessingStarted.await();
5961

@@ -115,12 +117,12 @@ public void run() {
115117
};
116118

117119
private static class RequestThread extends Thread {
118-
RestConfig config;
120+
int port;
119121
boolean finished = false;
120122
String response = null;
121123

122-
RequestThread(RestConfig config) {
123-
this.config = config;
124+
RequestThread(int port) {
125+
this.port = port;
124126
}
125127
@Override
126128
public void run() {
@@ -131,7 +133,7 @@ public void run() {
131133
try {
132134
Client client = ClientBuilder.newClient();
133135
response = client
134-
.target("http://localhost:" + config.getInt(RestConfig.PORT_CONFIG))
136+
.target("http://localhost:" + port)
135137
.path("/")
136138
.request()
137139
.get(String.class);

0 commit comments

Comments
 (0)