112 lines
3.6 KiB
JavaScript
112 lines
3.6 KiB
JavaScript
/* eslint-env mocha */
|
|
// Run this specific test using:
|
|
// npm test -- -f memory
|
|
var http = require('http');
|
|
var path = require('path');
|
|
var url = require('url');
|
|
var fork = require('child_process').fork;
|
|
|
|
describe('memory usage', function() {
|
|
var cors_api_url;
|
|
|
|
var server;
|
|
var cors_anywhere_child;
|
|
before(function(done) {
|
|
server = http.createServer(function(req, res) {
|
|
res.writeHead(200);
|
|
res.end();
|
|
}).listen(0, function() {
|
|
done();
|
|
});
|
|
});
|
|
|
|
after(function(done) {
|
|
server.close(function() {
|
|
done();
|
|
});
|
|
});
|
|
|
|
beforeEach(function(done) {
|
|
var cors_module_path = path.join(__dirname, 'child');
|
|
var args = [];
|
|
// Uncomment this if you want to compare the performance of CORS Anywhere
|
|
// with the standard no-op http module.
|
|
// args.push('use-http-instead-of-cors-anywhere');
|
|
cors_anywhere_child = fork(cors_module_path, args, {
|
|
execArgv: ['--expose-gc'],
|
|
});
|
|
cors_anywhere_child.once('message', function(cors_url) {
|
|
cors_api_url = cors_url;
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function() {
|
|
cors_anywhere_child.kill();
|
|
});
|
|
|
|
/**
|
|
* Perform N CORS Anywhere proxy requests to a simple test server.
|
|
*
|
|
* @param {number} n - number of repetitions.
|
|
* @param {number} requestSize - Approximate size of request in kilobytes.
|
|
* @param {number} memMax - Expected maximum memory usage in kilobytes.
|
|
* @param {function} done - Upon success, called without arguments.
|
|
* Upon failure, called with the error as parameter.
|
|
*/
|
|
function performNRequests(n, requestSize, memMax, done) {
|
|
var remaining = n;
|
|
var request = url.parse(
|
|
cors_api_url + 'http://127.0.0.1:' + server.address().port);
|
|
request.agent = false; // Force Connection: Close
|
|
request.headers = {
|
|
'Long-header': new Array(requestSize * 1e3).join('x'),
|
|
};
|
|
(function requestAgain() {
|
|
if (remaining-- === 0) {
|
|
cors_anywhere_child.once('message', function(memory_usage_delta) {
|
|
console.log('Memory usage delta: ' + memory_usage_delta +
|
|
' (' + n + ' requests of ' + requestSize + ' kb each)');
|
|
if (memory_usage_delta > memMax * 1e3) {
|
|
// Note: Even if this error is reached, always profile (e.g. using
|
|
// node-inspector) whether it is a true leak, and not e.g. noise
|
|
// caused by the implementation of V8/Node.js.
|
|
// Uncomment args.push('use-http-instead-of-cors-anywhere') at the
|
|
// fork() call to get a sense of what's normal.
|
|
throw new Error('Possible memory leak: ' + memory_usage_delta +
|
|
' bytes was not released, which exceeds the ' + memMax +
|
|
' kb limit by ' +
|
|
Math.round(memory_usage_delta / memMax / 10 - 100) + '%.');
|
|
}
|
|
done();
|
|
});
|
|
cors_anywhere_child.send(null);
|
|
return;
|
|
}
|
|
http.request(request, function() {
|
|
requestAgain();
|
|
}).on('error', function(error) {
|
|
done(error);
|
|
}).end();
|
|
})();
|
|
}
|
|
|
|
it('100 GET requests 50k', function(done) {
|
|
// This test is just for comparison with the following tests.
|
|
performNRequests(100, 50, 1200, done);
|
|
});
|
|
|
|
// 100x 1k and 100x 50k for comparison.
|
|
// Both should use about the same amount of memory if there is no leak.
|
|
it('1000 GET requests 1k', function(done) {
|
|
// Every request should complete within 10ms.
|
|
this.timeout(1000 * 10);
|
|
performNRequests(1000, 1, 2000, done);
|
|
});
|
|
it('1000 GET requests 50k', function(done) {
|
|
// Every request should complete within 10ms.
|
|
this.timeout(1000 * 10);
|
|
performNRequests(1000, 50, 2000, done);
|
|
});
|
|
});
|