Add some tests (mainly interested in memleak test)

If you wish to check if the API works, launch demo.html,
set the global cors_api_url variable to your local instance,
enter an URL and press "GET" or "POST".
This commit is contained in:
Rob Wu
2013-08-29 12:48:17 +02:00
parent a56fb8843c
commit b76d6457f0
4 changed files with 202 additions and 0 deletions

View File

@@ -23,6 +23,9 @@
"dependencies": {
"http-proxy": "~0.10"
},
"devDependencies": {
"node-webkit-agent": "~0.1.2"
},
"engines": {
"node": ">=0.6.6",
"npm": ">=1.1.0"

126
test/runner.js Normal file
View File

@@ -0,0 +1,126 @@
#!/usr/bin/env node
// Go to the end of the file to see the declarations of the tests
// jshint node:true, sub:true
'use strict';
var http = require('http');
var assert = require('assert');
var fork = require('child_process').fork;
var exec = require('child_process').exec;
var host = '127.0.0.1';
// CORS Anywhere API endpoint
var port = 11400;
var cors_api_url = 'http://' + host + ':' + port + '/';
// Server with redirects
var portServer = 11302;
var no_cors_url = 'http://' + host + ':' + portServer + '/';
// Memleak debugging server
var portLeak = process.env.DEBUG_PORT = 9998;
setupRedirectServer(function() {
setupCORSServer(function(activateDevtoolsAgent) {
runTest(function() {
if (activateDevtoolsAgent) {
activateDevtoolsAgent();
suggestLeakTest();
} else {
console.log('Leak tests not run.');
process.exit();
}
});
});
});
/**
* @param callback {function(activateDevtoolsAgent)} activateDevtoolsAgent is a function
* if the devtools agent is available, omitted otherwise.
*/
function setupCORSServer(callback) {
var child = fork('./sub-server', [host, port]);
child.on('message', function(message) {
if (message.hasDevtoolsAgent) {
callback(function() {
child.kill('SIGUSR2');
child = null;
});
} else if (message.hasDevtoolsAgent === false) {
callback();
} else if (message.action === 'leakTest') {
runLeakTest(message.parallel, message.requestCount);
} else {
console.error('Unexpected message: ', message);
}
});
}
function setupRedirectServer(callback) {
var child = fork('./sub-no-cors-server', [host, portServer]);
child.once('message', function() {
callback();
});
}
//
// Actual tests
//
function runTest(callback) {
var url = cors_api_url + no_cors_url + '2';
console.log('Test, GET: ' + url);
http.get(url, function(res) {
console.log('');
assert.equal(res.statusCode, 200, 'HTTP status must be 200');
console.log('Response headers:', res.headers);
assert.equal(res.headers['access-control-allow-origin'], '*');
assert.equal(res.headers['whatever'], 'header', 'Custom header must be passed through.');
assert.equal(res.headers['x-request-url'], no_cors_url + '2', 'x-request-url should match original URL');
assert.equal(res.headers['x-final-url'], no_cors_url + '0', 'x-final-url should match the last URL');
assert(!res.headers['set-cookie'], 'Cookies must be absent');
assert.equal(res.headers['x-cors-redirect-1'], '302 ' + no_cors_url + '1', 'x-cors-redirect-1 must provide info about redirect');
assert.equal(res.headers['x-cors-redirect-2'], '302 ' + no_cors_url + '0', 'x-cors-redirect-2 must provide info about redirect');
callback();
});
}
function suggestLeakTest() {
console.log('1. Visit http://c4milo.github.io/node-webkit-agent/26.0.1410.65/inspector.html?host=localhost:' + portLeak + '&page=0');
console.log('2. Go to the profiles tab, select "Take Heap Snapshot" and click "Start"');
console.log('3. Go to the JavaScript console, type leakTest() and press Enter');
console.log('4. When you see "leakTest done" in the console, take another heap snapshot and use the Comparison option.');
}
function runLeakTest(/*boolean*/ parallel, requestCount) {
requestCount = +requestCount || 100;
console.log('Sending ' + requestCount + ' requests');
var initCount = 0;
var doneCount = 0;
if (parallel) {
while (initCount < requestCount) doRequest(); // initCount is incremented in doRequest
} else {
doRequest();
}
function onComplete(res) {
if (++doneCount % 10 === 0 || doneCount === requestCount) {
console.log('done #' + doneCount);
}
assert.equal(res.statusCode, 200);
assert.equal(res.headers['access-control-allow-origin'], '*');
assert.equal(res.headers['whatever'], 'header', 'Custom header must be passed through.');
if (!parallel && doneCount < requestCount) {
doRequest();
}
}
function doRequest() {
http.get({
agent: false,
host: host,
port: port,
path: '/' + no_cors_url + '1?' + (++initCount) // resource with one redirect
}, onComplete);
}
}

View File

@@ -0,0 +1,31 @@
// jshint node:true
'use strict';
var host = process.argv[2];
var port = process.argv[3];
console.log('Trying to start redirect server on ' + host + ':' + port + '...');
process.on('disconnect', function() {
console.log('Stopping redirect server at ' + host + ':' + port + '...\n');
process.exit();
});
var regex = /^\/(\d+)(.*)/;
require('http').createServer(function(req, res) {
// Don't use console.log, because the number of newlines would be too much.
process.stdout.write(req.url + ' ');
// Redirect a few times. E.g. /3 -> /2 -> /1 -> /0
// Preserve any suffix (for cache breaking)
var path = regex.exec(req.url);
var count = path && +path[1];
if (count > 0) {
res.writeHead(302, { location: '/' + (count - 1) + path[2] });
res.end();
} else {
res.writeHead(200, { 'whatever':'header', 'Set-Cookie': 'test=1; path=/' });
res.end('Ok');
}
}).listen(port, host, function() {
console.log('Started redirect server at ' + host + ':' + port + '\n');
process.send('ready');
});

42
test/sub-server.js Normal file
View File

@@ -0,0 +1,42 @@
// jshint node:true
'use strict';
var host = process.argv[2];
var port = process.argv[3];
console.log('Trying to start CORS Anywhere on ' + host + ':' + port + '...');
process.on('disconnect', function() {
console.log('Stopping CORS Anywhere server at ' + host + ':' + port + '...\n');
process.exit();
});
require('../lib/cors-anywhere').createServer().listen(port, host, function() {
console.log('Running CORS Anywhere on ' + host + ':' + port + '\n');
var hasDevtoolsAgent = false;
try {
require('webkit-devtools-agent');
hasDevtoolsAgent = true;
} catch (e) {
console.error('Failed to load webkit-devtools-agent. Memory leak testing is not available');
console.error('Install it using npm install webkit-devtools-agent');
}
process.send({
hasDevtoolsAgent: hasDevtoolsAgent
});
});
global.leakTest = function leakTest(parallel, requestCount) {
// parallel {boolean} If true, all requests are sent at once.
// If false, the next request is only sent after completing the previous one (default).
// requestCount {number} Number of requests, defaults to 100
// All parameters are optional
process.send({
action: 'leakTest',
parallel: parallel,
requestCount: requestCount
});
console.log('Switch to the shell and watch the console for the completion message.');
};
global.leakTestParallel = function leakTestParallel(requestCount) {
global.leakTest(true, requestCount);
};