[refactor test] Finish removing old test code.

This commit is contained in:
indexzero 2012-07-21 20:46:30 -04:00
parent 4ae7a5b840
commit e2dc7f9693
8 changed files with 292 additions and 131 deletions

View File

@ -103,14 +103,29 @@ exports.createProxyServer = function (options, callback) {
});
};
//
// ### function assignPortsToRoutes (routes)
// #### @routes {Object} Routing table to assign ports to
//
// Assigns dynamic ports to the `routes` for runtime testing.
//
exports.assignPortsToRoutes = function (routes) {
Object.keys(routes).forEach(function (source) {
routes[source] = routes[source].replace('{PORT}', helpers.nextPort);
});
return routes;
}
};
//
// ### function parseRoutes (options)
// #### @options {Object} Options to use when parsing routes
// #### @protocol {string} Protocol to use in the routes
// #### @routes {Object} Routes to parse.
//
// Returns an Array of fully-parsed URLs for the source and
// target of `options.routes`.
//
exports.parseRoutes = function (options) {
var protocol = options.protocol || 'http',
routes = options.routes;

View File

@ -9,11 +9,14 @@
var assert = require('assert'),
async = require('async'),
io = require('socket.io'),
ws = require('ws'),
http = require('./http');
//
// ### function createServerPair (options, callback)
// #### @options {Object} Options to create target and proxy server.
// #### @target {Object} Options for the target server.
// #### @proxy {Object} Options for the proxy server.
// #### @callback {function} Continuation to respond to when complete.
//
// Creates http target and proxy servers
@ -35,7 +38,30 @@ exports.createServerPair = function (options, callback) {
], callback);
};
//
// ### function createServer (options, callback)
// #### @options {Object} Options for creating the socket.io or ws server.
// #### @raw {boolean} Enables ws.Websocket server.
//
// Creates a socket.io or ws server using the specified `options`.
//
exports.createServer = function (options, callback) {
return options.raw
? exports.createWsServer(options, callback)
: exports.createSocketIoServer(options, callback);
};
//
// ### function createSocketIoServer (options, callback)
// #### @options {Object} Options for creating the socket.io server
// #### @port {number} Port to listen on
// #### @input {string} Input to expect from the only socket
// #### @output {string} Output to send the only socket
//
// Creates a socket.io server on the specified `options.port` which
// will expect `options.input` and then send `options.output`.
//
exports.createSocketIoServer = function (options, callback) {
var server = io.listen(options.port, callback);
server.sockets.on('connection', function (socket) {
@ -46,3 +72,23 @@ exports.createServer = function (options, callback) {
});
};
//
// ### function createWsServer (options, callback)
// #### @options {Object} Options for creating the ws.Server instance
// #### @port {number} Port to listen on
// #### @input {string} Input to expect from the only socket
// #### @output {string} Output to send the only socket
//
// Creates a ws.Server instance on the specified `options.port` which
// will expect `options.input` and then send `options.output`.
//
exports.createWsServer = function (options, callback) {
var server = new ws.Server({ port: options.port }, callback);
server.on('connection', function (socket) {
socket.on('message', function (data) {
assert.equal(data, options.input);
socket.send(options.output);
});
});
};

View File

@ -72,7 +72,7 @@ vows.describe('node-http-proxy/http/routing-table').addBatch({
)
], function () {
request({
uri: 'http://localhost:' + that.port,
uri: 'http://127.0.0.1:' + that.port,
headers: {
host: 'dynamic.com'
}

View File

@ -59,7 +59,7 @@ exports.assertProxied = function (options) {
output = options.output || 'hello world from ' + ports.target,
req = options.request || {};
req.uri = req.uri || 'http://localhost:' + ports.proxy;
req.uri = req.uri || 'http://127.0.0.1:' + ports.proxy;
return {
topic: function () {
@ -79,7 +79,7 @@ exports.assertProxied = function (options) {
proxy: {
forward: options.forward,
target: {
host: 'localhost',
host: '127.0.0.1',
port: ports.target
}
}
@ -110,7 +110,7 @@ exports.assertInvalidProxy = function (options) {
var ports = options.ports || helpers.nextPortPair,
req = options.request || {};
req.uri = req.uri || 'http://localhost:' + ports.proxy;
req.uri = req.uri || 'http://127.0.0.1:' + ports.proxy;
return {
topic: function () {
@ -123,7 +123,7 @@ exports.assertInvalidProxy = function (options) {
port: ports.proxy,
proxy: {
target: {
host: 'localhost',
host: '127.0.0.1',
port: ports.target
}
}
@ -158,13 +158,13 @@ exports.assertForwardProxied = function (options) {
"and a valid forward target": exports.assertProxied({
forward: {
port: forwardPort,
host: 'localhost'
host: '127.0.0.1'
}
}),
"and an invalid forward target": exports.assertProxied({
forward: {
port: 9898,
host: 'localhost'
host: '127.0.0.1'
}
})
};
@ -271,7 +271,7 @@ exports.assertProxiedToRoutes = function (options, nested) {
"a request to unknown.com": exports.assertRequest({
assert: { statusCode: 404 },
request: {
uri: 'http://localhost:' + port,
uri: 'http://127.0.0.1:' + port,
headers: {
host: 'unknown.com'
}
@ -285,7 +285,7 @@ exports.assertProxiedToRoutes = function (options, nested) {
locations.forEach(function (location) {
context[location.source.href] = exports.assertRequest({
request: {
uri: 'http://localhost:' + port + location.source.path,
uri: 'http://127.0.0.1:' + port + location.source.path,
headers: {
host: location.source.hostname
}

View File

@ -8,8 +8,49 @@
var assert = require('assert'),
io = require('socket.io-client'),
WebSocket = require('ws'),
helpers = require('../helpers/index');
//
// ### function assertSendRecieve (options)
// #### @options {Object} Options for creating this assertion.
// #### @raw {boolean} Enables raw `ws.WebSocket`.
// #### @uri {string} URI of the proxy server.
// #### @input {string} Input to assert sent to the target ws server.
// #### @output {string} Output to assert from the taget ws server.
//
// Creates a `socket.io` or raw `WebSocket` connection and asserts that
// `options.input` is sent to and `options.output` is received from the
// connection.
//
exports.assertSendReceive = function (options) {
if (!options.raw) {
return {
topic: function () {
var socket = io.connect(options.uri);
socket.on('outgoing', this.callback.bind(this, null));
socket.emit('incoming', options.input);
},
"should send input and receive output": function (_, data) {
assert.equal(data, options.output);
}
}
}
return {
topic: function () {
var socket = new WebSocket(options.uri);
socket.on('message', this.callback.bind(this, null));
socket.on('open', function () {
socket.send(options.input);
});
},
"should send input and recieve output": function (_, data, flags) {
assert.equal(data, options.output);
}
}
}
//
// ### function assertProxied (options)
// #### @options {Object} Options for this test
@ -17,6 +58,7 @@ var assert = require('assert'),
// #### @ports {Object} Ports for the request (target, proxy).
// #### @input {string} Input to assert sent to the target ws server.
// #### @output {string} Output to assert from the taget ws server.
// #### @raw {boolean} Enables raw `ws.Server` usage.
//
// Creates a complete end-to-end test for requesting against an
// http proxy.
@ -26,7 +68,12 @@ exports.assertProxied = function (options) {
var ports = options.ports || helpers.nextPortPair,
input = options.input || 'hello world to ' + ports.target,
output = options.output || 'hello world from ' + ports.target;
output = options.output || 'hello world from ' + ports.target,
protocol = options.protocol || 'http';
if (options.raw && !options.protocol) {
protocol = 'ws';
}
return {
topic: function () {
@ -34,29 +81,145 @@ exports.assertProxied = function (options) {
target: {
input: input,
output: output,
port: ports.target
port: ports.target,
raw: options.raw
},
proxy: {
latency: options.latency,
port: ports.proxy,
proxy: {
target: {
host: 'localhost',
host: '127.0.0.1',
port: ports.target
}
}
}
}, this.callback);
},
"the proxy WebSocket": {
topic: function () {
var socket = io.connect('http://localhost:' + ports.proxy);
socket.on('outgoing', this.callback.bind(this, null));
socket.emit('incoming', input);
},
"should send input and receive output": function (_, data) {
assert.equal(data, output);
}
}
"the proxy Websocket connection": exports.assertSendReceive({
uri: protocol + '://127.0.0.1:' + ports.proxy,
input: input,
output: output,
raw: options.raw
})
};
};
//
// ### function assertProxiedtoRoutes (options, nested)
// #### @options {Object} Options for this ProxyTable-based test
// #### @raw {boolean} Enables ws.Server usage.
// #### @routes {Object|string} Routes to use for the proxy.
// #### @hostnameOnly {boolean} Enables hostnameOnly routing.
// #### @nested {Object} Nested vows to add to the returned context.
//
// Creates a complete end-to-end test for requesting against an
// http proxy using `options.routes`:
//
// 1. Creates target servers for all routes in `options.routes.`
// 2. Creates a proxy server.
// 3. Ensure Websocket connections to the proxy server for all route targets
// can send input and recieve output.
//
exports.assertProxiedToRoutes = function (options, nested) {
//
// Assign dynamic ports to the routes to use.
//
options.routes = helpers.http.assignPortsToRoutes(options.routes);
//
// Parse locations from routes for making assertion requests.
//
var locations = helpers.http.parseRoutes(options),
protocol = options.protocol || 'http',
port = helpers.nextPort,
context,
proxy;
if (options.raw && !options.protocol) {
protocol = 'ws';
}
if (options.filename) {
//
// If we've been passed a filename write the routes to it
// and setup the proxy options to use that file.
//
fs.writeFileSync(options.filename, JSON.stringify({ router: options.routes }));
proxy = { router: options.filename };
}
else {
//
// Otherwise just use the routes themselves.
//
proxy = {
hostnameOnly: options.hostnameOnly,
router: options.routes
};
}
//
// Create the test context which creates all target
// servers for all routes and a proxy server.
//
context = {
topic: function () {
var that = this;
async.waterfall([
//
// 1. Create all the target servers
//
async.apply(
async.forEach,
locations,
function createRouteTarget(location, next) {
helpers.ws.createServer({
raw: options.raw,
port: location.target.port,
output: 'hello from ' + location.source.href,
input: 'hello to ' + location.source.href
}, next);
}
),
//
// 2. Create the proxy server
//
async.apply(
helpers.http.createProxyServer,
{
port: port,
latency: options.latency,
routing: true,
proxy: proxy
}
)
], function (_, server) {
//
// 3. Set the proxy server for later use
//
that.proxyServer = server;
that.callback();
});
//
// 4. Assign the port to the context for later use
//
this.port = port;
}
};
//
// Add test assertions for each of the route locations.
//
locations.forEach(function (location) {
context[location.source.href] = exports.assertSendRecieve({
uri: protocol + '://127.0.0.1:' + port + location.source.path,
output: 'hello from ' + location.source.href,
input: 'hello to ' + location.source.href,
raw: options.raw
});
});
return context;
};

View File

@ -1,104 +1,25 @@
/*
node-http-proxy-test.js: http proxy for node.js
* routing-tabletest.js: Test for proxying `socket.io` and raw `WebSocket` requests using a ProxyTable.
*
* (C) 2010 Nodejitsu Inc.
* MIT LICENCE
*
*/
Copyright (c) 2010 Charlie Robbins, Marak Squires and Fedor Indutny
var vows = require('vows'),
macros = require('../macros'),
helpers = require('../helpers/index');
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var util = require('util'),
assert = require('assert'),
argv = require('optimist').argv,
colors = require('colors'),
request = require('request'),
vows = require('vows'),
websocket = require('../../vendor/websocket'),
helpers = require('../helpers');
try {
var utils = require('socket.io/lib/socket.io/utils'),
io = require('socket.io');
}
catch (ex) {
console.error('Socket.io is required for this example:');
console.error('npm ' + 'install'.green + ' socket.io@0.6.18'.magenta);
process.exit(1);
}
var options = helpers.parseProtocol(),
testName = [options.source.protocols.ws, options.target.protocols.ws].join('-to-'),
runner = new helpers.TestRunner(options);
vows.describe('node-http-proxy/routing-proxy/' + testName).addBatch({
"When using server created by httpProxy.createServer()": {
"using proxy table with no latency": {
"when an inbound message is sent from a WebSocket client": {
topic: function () {
var that = this
headers = {};
runner.webSocketTestWithTable({
io: io,
host: 'localhost',
wsprotocol: options.source.protocols.ws,
protocol: options.source.protocols.http,
router: { 'localhost' : 'localhost:8230' },
ports: {
target: 8230,
proxy: 8231
vows.describe('node-http-proxy/ws').addBatch({
"With a valid target server": {
"and no latency": {
"using ws": macros.ws.assertProxied(),
"using socket.io": macros.ws.assertProxied({
raw: true
}),
},
onListen: function (socket) {
socket.on('connection', function (client) {
client.on('message', function (msg) {
that.callback(null, msg, headers);
});
});
},
onWsupgrade: function (req, res) {
headers.request = req;
headers.response = res.headers;
},
onOpen: function (ws) {
ws.send(utils.encode('from client'));
}
});
},
"the target server should receive the message": function (err, msg, headers) {
assert.equal(msg, 'from client');
},
"the origin and sec-websocket-origin headers should match": function (err, msg, headers) {
assert.isString(headers.response['sec-websocket-location']);
assert.isTrue(headers.response['sec-websocket-location'].indexOf(options.source.protocols.ws) !== -1);
assert.equal(headers.request.Origin, headers.response['sec-websocket-origin']);
}
}
}
}
}).addBatch({
"When the tests are over": {
topic: function () {
return runner.closeServers();
},
"the servers should clean up": function () {
assert.isTrue(true);
}
// "and latency": macros.websocket.assertProxied({
// latency: 2000
// })
}
}).export(module);

View File

@ -10,10 +10,10 @@ var vows = require('vows'),
macros = require('../macros'),
helpers = require('../helpers/index');
vows.describe('node-http-proxy/ws').addBatch({
vows.describe('node-http-proxy/ws/socket.io').addBatch({
"With a valid target server": {
"and no latency": macros.ws.assertProxied(),
// "and latency": macros.websocket.assertProxied({
// "and latency": macros.ws.assertProxied({
// latency: 2000
// })
}

View File

@ -5,3 +5,19 @@
* MIT LICENCE
*
*/
var vows = require('vows'),
macros = require('../macros'),
helpers = require('../helpers/index');
vows.describe('node-http-proxy/ws/WebSocket').addBatch({
"With a valid target server": {
"and no latency": macros.ws.assertProxied({
raw: true
}),
// "and latency": macros.ws.assertProxied({
// raw: true,
// latency: 2000
// })
}
}).export(module);