Skip to content

Commit

Permalink
Use ephemeral ports for tests.
Browse files Browse the repository at this point in the history
This addresses a cause of test errors in which our use of hard-coded
ports sometimes causes failures because those ports are in use.
Instead, always listen on port 0, then check back and see what
port was allocated before sending requests.

Making this work requires some changes in the HTTP adapter so that it
can report the correct address.

For adapters that can't (a servlet adapter, or Apigee Edge) we will
instead return "localhost" and port -1. That way clients that
call 'address' will at least get something they can parse but
can't actually connect to.
  • Loading branch information
gbrail committed Sep 21, 2017
1 parent 239d2ee commit d310b53
Show file tree
Hide file tree
Showing 22 changed files with 119 additions and 52 deletions.
28 changes: 28 additions & 0 deletions core/src/main/java/io/apigee/trireme/core/modules/HTTPWrap.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
import io.apigee.trireme.net.spi.HttpServerStub;
import io.apigee.trireme.net.spi.TLSParams;
import io.apigee.trireme.net.spi.UpgradedSocket;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.util.Random;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.RhinoException;
Expand Down Expand Up @@ -219,6 +222,31 @@ public void close()
runner.unPin();
}

@JSFunction
@SuppressWarnings("unused")
public static Object localAddress(Context cx, Scriptable thisObj, Object[] args, Function func)
{
ServerContainer self = (ServerContainer)thisObj;
Scriptable addr = cx.newObject(thisObj);
if (self.adapter != null) {
InetSocketAddress sa = self.adapter.localAddress();
if (sa == null) {
addr.put("address", addr, "localhost");
addr.put("port", addr, -1);
addr.put("family", addr, "IPv4");
} else {
addr.put("address", addr, sa.getHostString());
addr.put("port", addr, sa.getPort());
if (sa.getAddress() instanceof Inet6Address) {
addr.put("family", addr, "IPv6");
} else {
addr.put("family", addr, "IPv4");
}
}
}
return addr;
}

/**
* This method is called when the whole server has failed or is shutting down prematurely.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/
package io.apigee.trireme.net.spi;

import java.net.InetSocketAddress;
import javax.net.ssl.SSLContext;

/**
Expand All @@ -31,6 +32,16 @@ public interface HttpServerAdapter
/** Start to listen on the specified host and port. */
void listen(String host, int port, int backlog, TLSParams tlsParams);

/**
* Get the address that we're listening on. This should be the real address where
* a client could send a request, not the initial parameters sent to "listen,"
* in case port zero was used to create an anonymous port.
* If there is no meaningful way to return a real address, then return null -- the
* wrapper will use this to generate a random (and meaningless) port number so that clients will
* not break.
*/
InetSocketAddress localAddress();

/** Don't close the socket, but stop accepting new connections */
void suspend();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.timeout.IdleStateHandler;
import java.net.InetSocketAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -88,7 +89,7 @@ public void listen(String host, int port, int backlog, TLSParams tlsParams)
}
try {
server = NettyFactory.get().createServer(port, host, backlog, makePipeline(tlsParams));
log.debug("Listening on port {}", port);
log.debug("Listening on {}", server.getAddress());
} catch (ChannelException ce) {
stub.onError(ce.getMessage());
stub.onClose(null, null);
Expand Down Expand Up @@ -143,6 +144,11 @@ boolean isClosing() {
return closing;
}

@Override
public InetSocketAddress localAddress() {
return server.getAddress();
}

@Override
public void suspend()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ public void close()
}

public InetSocketAddress getAddress() {
if (serverChannel != null) {
return (InetSocketAddress)(serverChannel.localAddress());
}
return address;
}

Expand Down
6 changes: 3 additions & 3 deletions net/src/test/resources/tests/basichttpstest.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ var svr = https.createServer({
});

console.log('Server starting to listen');
svr.listen(33333, function() {
console.log('Server listening');
https.get({host: 'localhost', port: 33333,
svr.listen(0, function() {
console.log('Server listening on %j', svr.address());
https.get({host: 'localhost', port: svr.address().port,
path: '/', rejectUnauthorized: false}, function(resp) {
var received = '';
console.log('Got a response with status code ' + resp.statusCode);
Expand Down
10 changes: 5 additions & 5 deletions net/src/test/resources/tests/basichttptest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var socketsMatch = false;
Expand Down Expand Up @@ -52,8 +52,10 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33333, function() {
http.get('http://localhost:33333/', function(resp) {
svr.listen(0, function() {
console.log('Server listening on %j', svr.address());
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
var received = '';
resp.setEncoding('utf8');
if (resp.statusCode != 200) {
Expand All @@ -75,9 +77,7 @@ svr.listen(33333, function() {
var msg = JSON.parse(received);
console.log('Received: %j', msg);

assert.equal(localAddress, msg.remoteAddress);
assert.equal(localPort, msg.remotePort);
assert.equal(remoteAddress, msg.localAddress);
assert.equal(remotePort, msg.localPort);
socketsMatch = true;
});
Expand Down
8 changes: 5 additions & 3 deletions net/src/test/resources/tests/blackholeresponsetest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var TIMEOUT = 1000;

Expand All @@ -15,8 +16,9 @@ var svr = http.createServer(function(req, resp) {
}
});

svr.listen(33342, function() {
http.get('http://localhost:33342', function(resp) {
svr.listen(0, function() {
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
var received = '';
resp.setEncoding('utf8');
assert.equal(resp.statusCode, 500);
Expand Down
8 changes: 5 additions & 3 deletions net/src/test/resources/tests/blackholeresponsetest2.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var TIMEOUT = 1000;

Expand All @@ -19,8 +20,9 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33341, function() {
http.get('http://localhost:33341', function(resp) {
svr.listen(0, function() {
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
var received = '';
resp.setEncoding('utf8');
assert.equal(resp.statusCode, 500);
Expand Down
10 changes: 7 additions & 3 deletions net/src/test/resources/tests/catchexception.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var urlparse = require('url');
var util = require('util');

var svr = http.createServer(function(req, resp) {
console.log('Got %s', req.url);
Expand Down Expand Up @@ -40,7 +41,10 @@ var svr = http.createServer(function(req, resp) {
}
});

svr.listen(33333, function() {
var baseUrl;

svr.listen(0, function() {
baseUrl = util.format('http://localhost:%d/', svr.address().port);
doTest('GET', 'ok', false, 200, function() {
doTest('GET', 'throw', false, 500, function() {
doTest('POST', 'throwOnData', false, 500, function() {
Expand All @@ -58,7 +62,7 @@ svr.listen(33333, function() {
});

function doTest(verb, url, shouldClose, code, next) {
opts = urlparse.parse('http://localhost:33333/' + url);
opts = urlparse.parse(baseUrl + url);
opts.method = verb;
req = http.request(opts, function(resp) {
var respData = '';
Expand Down
7 changes: 4 additions & 3 deletions net/src/test/resources/tests/clientclose.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var TIMEOUT = 100;
var ITERATIONS = 10;
Expand Down Expand Up @@ -63,8 +64,8 @@ function getClose(url, cb) {
});
}

svr.listen(33344, function() {
var url = 'http://localhost:33344';
svr.listen(0, function() {
var url = util.format('http://localhost:%d', svr.address().port);
getGood(url, function() {
getClose(url, function() {
console.log('Done');
Expand Down
8 changes: 5 additions & 3 deletions net/src/test/resources/tests/cpulooptest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var svr = http.createServer(function(req, resp) {
console.log('Starting to loop the CPU');
Expand All @@ -12,8 +13,9 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33333, function() {
http.get('http://localhost:33333/', function(resp) {
svr.listen(0, function() {
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
svr.close();
assert.equal(500, resp.statusCode, 'Expected status code 500');

Expand Down
8 changes: 5 additions & 3 deletions net/src/test/resources/tests/newhttptest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var svr = http.createServer(function(req, resp) {
console.log('Got an HTTP request');
Expand All @@ -14,9 +15,10 @@ var svr = http.createServer(function(req, resp) {
});

console.log('Server starting to listen');
svr.listen(33333, function() {
svr.listen(0, function() {
console.log('Server listening');
http.get('http://localhost:33333/', function(resp) {
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
var received = '';
console.log('Got a response with status code ' + resp.statusCode);
resp.setEncoding('utf8');
Expand Down
4 changes: 2 additions & 2 deletions net/src/test/resources/tests/postmanychunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33333, function() {
var req = http.request({host: 'localhost', port: 33333,
svr.listen(0, function() {
var req = http.request({host: 'localhost', port: svr.address().port,
path: '/', method: 'POST',
headers: { 'Content-Type': 'text/plain' }},
function(resp) {
Expand Down
4 changes: 2 additions & 2 deletions net/src/test/resources/tests/postmanychunkshttps.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ var svr = https.createServer({
});
});

svr.listen(33333, function() {
var req = https.request({host: 'localhost', port: 33333,
svr.listen(0, function() {
var req = https.request({host: 'localhost', port: svr.address().port,
path: '/', method: 'POST',
headers: { 'Content-Type': 'text/plain' },
rejectUnauthorized: false},
Expand Down
4 changes: 2 additions & 2 deletions net/src/test/resources/tests/postonechunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33333, function() {
var req = http.request({host: 'localhost', port: 33333,
svr.listen(0, function() {
var req = http.request({host: 'localhost', port: svr.address().port,
path: '/', method: 'POST',
headers: { 'Content-Type': 'text/plain' }},
function(resp) {
Expand Down
4 changes: 2 additions & 2 deletions net/src/test/resources/tests/postonechunkhttps.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ var svr = https.createServer({ keystore: keystore, passphrase: 'secure' },
});
});

svr.listen(33333, function() {
var req = https.request({host: 'localhost', port: 33333,
svr.listen(0, function() {
var req = https.request({host: 'localhost', port: svr.address().port,
path: '/', method: 'POST',
headers: { 'Content-Type': 'text/plain' },
rejectUnauthorized: false},
Expand Down
8 changes: 5 additions & 3 deletions net/src/test/resources/tests/responsecodetest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var svr = http.createServer(function(req, resp) {
console.log('Server: got request');
Expand All @@ -8,8 +9,9 @@ var svr = http.createServer(function(req, resp) {
resp.end();
});

svr.listen(33333, function() {
http.get('http://localhost:33333/', function(resp) {
svr.listen(0, function() {
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
resp.on('readable', function() {
resp.read();
});
Expand Down
4 changes: 2 additions & 2 deletions net/src/test/resources/tests/slowrequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33342, function() {
svr.listen(0, function() {
var req = http.request({
hostname: 'localhost',
port: 33342,
port: svr.address().port,
path: '/',
method: 'POST'
}, function(resp) {
Expand Down
8 changes: 5 additions & 3 deletions net/src/test/resources/tests/slowresponse.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var http = require('http');
var assert = require('assert');
var http = require('http');
var util = require('util');

var TIMEOUT = 1000;

Expand Down Expand Up @@ -27,8 +28,9 @@ var svr = http.createServer(function(req, resp) {
});
});

svr.listen(33343, function() {
http.get('http://localhost:33343', function(resp) {
svr.listen(0, function() {
var url = util.format('http://localhost:%d', svr.address().port);
http.get(url, function(resp) {
var received = '';
resp.setEncoding('utf8');
assert.equal(resp.statusCode, 200);
Expand Down
4 changes: 2 additions & 2 deletions net/src/test/resources/tests/upgradetest.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ srv.on('upgrade', function(req, socket, head) {
});

// now that server is running
srv.listen(33334, function() {
srv.listen(0, function() {

// make a request
var options = {
port: 33334,
port: srv.address().port,
hostname: 'localhost',
headers: {
'Connection': 'Upgrade',
Expand Down
Loading

0 comments on commit d310b53

Please sign in to comment.