Merge pull request #768 from CartoDB/test-support-fixes

Test support fixes
This commit is contained in:
David M 2017-10-06 15:57:25 +02:00 committed by GitHub
commit 44eb323764
4 changed files with 93 additions and 117 deletions

View File

@ -1,4 +1,3 @@
test/results/
test/monkey/
test/benchmark.js
test/support/

View File

@ -77,7 +77,6 @@ function randomImagePath() {
return path.resolve('test/results/png/image-test-' + Date.now() + '.png');
}
// jshint maxcomplexity:9
assert.response = function(server, req, res, callback) {
if (!callback) {
callback = res;
@ -106,7 +105,6 @@ assert.response = function(server, req, res, callback) {
// jshint maxcomplexity:9
function onServerListening() {
var status = res.status || res.statusCode;
var requestParams = {
url: 'http://' + host + ':' + port + req.url,
method: req.method || 'GET',
@ -122,61 +120,74 @@ assert.response = function(server, req, res, callback) {
request(requestParams, function assert$response$requestHandler(error, response, body) {
listener.close(function() {
response.body = response.body || body;
// Assert response body
if (res.body) {
var eql = res.body instanceof RegExp ? res.body.test(response.body) : res.body === response.body;
if (!eql) {
return callback(response, new Error(colorize(
'[red]{Invalid response body.}\n' +
' Expected: [green]{' + res.body + '}\n' +
' Got: [red]{' + response.body + '}'))
);
}
}
// Assert response status
if (typeof status === 'number') {
if (response.statusCode != status) {
return callback(response, new Error(colorize(
'[red]{Invalid response status code.}\n' +
' Expected: [green]{' + status + '}\n' +
' Got: [red]{' + response.statusCode + '}\n' +
' Body: ' + response.body))
);
}
}
// Assert response headers
if (res.headers) {
var keys = Object.keys(res.headers);
for (var i = 0, len = keys.length; i < len; ++i) {
var name = keys[i],
actual = response.headers[name.toLowerCase()],
expected = res.headers[name],
headerEql = expected instanceof RegExp ? expected.test(actual) : expected === actual;
if (!headerEql) {
return callback(response, new Error(colorize(
'Invalid response header [bold]{' + name + '}.\n' +
' Expected: [green]{' + expected + '}\n' +
' Got: [red]{' + actual + '}'))
);
}
}
}
// Callback
callback(response);
var err = validateResponse(response, res);
return callback(response, err);
});
});
}
};
// jshint maxcomplexity:6
function validateResponseBody(response, expected) {
if (expected.body) {
var eql = expected.body instanceof RegExp ?
expected.body.test(response.body) :
expected.body === response.body;
if (!eql) {
return new Error(colorize(
'[red]{Invalid response body.}\n' +
' Expected: [green]{' + expected.body + '}\n' +
' Got: [red]{' + response.body + '}')
);
}
}
}
function validateResponseStatus(response, expected) {
var status = expected.status || expected.statusCode;
// Assert response status
if (typeof status === 'number') {
if (response.statusCode !== status) {
return new Error(colorize(
'[red]{Invalid response status code.}\n' +
' Expected: [green]{' + status + '}\n' +
' Got: [red]{' + response.statusCode + '}\n' +
' Body: ' + response.body)
);
}
}
}
function validateResponseHeaders(response, expected) {
// Assert response headers
if (expected.headers) {
var keys = Object.keys(expected.headers);
for (var i = 0, len = keys.length; i < len; ++i) {
var name = keys[i],
actual = response.headers[name.toLowerCase()],
expectedHeader = expected.headers[name],
headerEql = expectedHeader instanceof RegExp ? expectedHeader.test(actual) : expectedHeader === actual;
if (!headerEql) {
return new Error(colorize(
'Invalid response header [bold]{' + name + '}.\n' +
' Expected: [green]{' + expectedHeader + '}\n' +
' Got: [red]{' + actual + '}')
);
}
}
}
}
function validateResponse(response, expected) {
// Assert response body
return validateResponseBody(response, expected) ||
validateResponseStatus(response, expected) ||
validateResponseHeaders(response, expected);
}
// @param tolerance number of tolerated grid cell differences
// jshint maxcomplexity:9
assert.utfgridEqualsFile = function(buffer, file_b, tolerance, callback) {
// jshint maxcomplexity:9
fs.writeFileSync('/tmp/grid.json', buffer, 'binary'); // <-- to debug/update
var expected_json = JSON.parse(fs.readFileSync(file_b, 'utf8'));

View File

@ -1,21 +0,0 @@
var _ = require('underscore');
require(__dirname + '/test_helper');
module.exports = function(opts) {
var config = {
redis_pool: {
max: 10,
idleTimeoutMillis: 1,
reapIntervalMillis: 1,
port: global.environment.redis.port
}
}
_.extend(config, opts || {});
return config;
}();

View File

@ -22,7 +22,7 @@ const MAPNIK_SUPPORTED_FORMATS = {
'grid.json': true,
'geojson': true,
'mvt': true
}
};
function TestClient(config, apiKey) {
this.mapConfig = isMapConfig(config) ? config : null;
@ -115,7 +115,7 @@ module.exports.CARTOCSS = {
module.exports.SQL = {
EMPTY: 'select 1 as cartodb_id, null::geometry as the_geom_webmercator',
ONE_POINT: 'select 1 as cartodb_id, \'SRID=3857;POINT(0 0)\'::geometry the_geom_webmercator'
}
};
TestClient.prototype.getWidget = function(widgetName, params, callback) {
var self = this;
@ -130,7 +130,6 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
url += '?' + qs.stringify({ filters: JSON.stringify(params.filters) });
}
var layergroupId;
step(
function createLayergroup() {
var next = this;
@ -176,11 +175,12 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
}
);
},
function getWidgetResult(err, _layergroupId) {
function getWidgetResult(err, layergroupId) {
assert.ifError(err);
var next = this;
layergroupId = _layergroupId;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
var urlParams = {
own_filter: params.hasOwnProperty('own_filter') ? params.own_filter : 1
@ -217,8 +217,6 @@ TestClient.prototype.getWidget = function(widgetName, params, callback) {
);
},
function finish(err, res) {
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
var widget;
if (!err && res.body) {
widget = JSON.parse(res.body);
@ -241,7 +239,6 @@ TestClient.prototype.widgetSearch = function(widgetName, userQuery, params, call
url += '?' + qs.stringify({ filters: JSON.stringify(params.filters) });
}
var layergroupId;
step(
function createLayergroup() {
var next = this;
@ -287,11 +284,12 @@ TestClient.prototype.widgetSearch = function(widgetName, userQuery, params, call
}
);
},
function getWidgetSearchResult(err, _layergroupId) {
function getWidgetSearchResult(err, layergroupId) {
assert.ifError(err);
var next = this;
layergroupId = _layergroupId;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
var urlParams = {
q: userQuery,
@ -326,8 +324,6 @@ TestClient.prototype.widgetSearch = function(widgetName, userQuery, params, call
);
},
function finish(err, res) {
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
var searchResult;
if (!err && res.body) {
searchResult = JSON.parse(res.body);
@ -365,7 +361,6 @@ TestClient.prototype.getDataview = function(dataviewName, params, callback) {
}
};
var layergroupId;
step(
function createLayergroup() {
var next = this;
@ -401,11 +396,10 @@ TestClient.prototype.getDataview = function(dataviewName, params, callback) {
}
);
},
function getDataviewResult(err, _layergroupId) {
function getDataviewResult(err, layergroupId) {
assert.ifError(err);
var next = this;
layergroupId = _layergroupId;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
@ -479,7 +473,6 @@ TestClient.prototype.getFeatureAttributes = function(featureId, layerId, params,
}
};
var layergroupId;
step(
function createLayergroup() {
var next = this;
@ -568,7 +561,7 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) {
var layergroupId;
if (params.layergroupid) {
layergroupId = params.layergroupid
layergroupId = params.layergroupid;
}
step(
@ -583,7 +576,7 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) {
return next(new Error('apiKey param is mandatory to create a new template'));
}
params.placeholders = params.placeholders || {};
params.placeholders = params.placeholders || {};
assert.response(self.server,
{
@ -616,7 +609,7 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) {
return next(null, layergroupId);
}
var data = templateId ? params.placeholders : self.mapConfig
var data = templateId ? params.placeholders : self.mapConfig;
var path = templateId ?
urlNamed + '/' + templateId + '?' + qs.stringify({api_key: self.apiKey}) :
url;
@ -645,10 +638,10 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) {
}
);
},
function getTileResult(err, _layergroupId) {
function getTileResult(err, layergroupId) {
// jshint maxcomplexity:12
assert.ifError(err);
layergroupId = _layergroupId;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
@ -744,7 +737,7 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) {
body = JSON.parse(res.body);
break;
default:
body = res.body
body = res.body;
break;
}
@ -784,10 +777,11 @@ TestClient.prototype.getLayergroup = function(expectedResponse, callback) {
},
expectedResponse,
function(res, err) {
var parsedBody;
// If there is a response, we are still interested in catching the created keys
// to be able to delete them on the .drain() method.
if (res) {
var parsedBody = JSON.parse(res.body);
parsedBody = JSON.parse(res.body);
if (parsedBody.layergroupid) {
self.keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
@ -805,7 +799,7 @@ TestClient.prototype.getLayergroup = function(expectedResponse, callback) {
TestClient.prototype.getStaticCenter = function (params, callback) {
var self = this;
let { layergroupid, z, lat, lng, width, height, format } = params
let { layergroupid, z, lat, lng, width, height, format } = params;
var url = `/api/v1/map/`;
@ -821,7 +815,7 @@ TestClient.prototype.getStaticCenter = function (params, callback) {
return next(null, layergroupid);
}
var data = self.mapConfig
var data = self.mapConfig;
var path = url;
assert.response(self.server,
@ -848,16 +842,13 @@ TestClient.prototype.getStaticCenter = function (params, callback) {
}
);
},
function getStaticResult(err, _layergroupid) {
function getStaticResult(err, layergroupId) {
assert.ifError(err);
var next = this;
layergroupid = _layergroupid;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupid).token] = 0;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
url = `/api/v1/map/static/center/${layergroupid}/${z}/${lat}/${lng}/${width}/${height}.${format}`
url = `/api/v1/map/static/center/${layergroupId}/${z}/${lat}/${lng}/${width}/${height}.${format}`;
if (self.apiKey) {
url += '?' + qs.stringify({api_key: self.apiKey});
@ -895,7 +886,7 @@ TestClient.prototype.getStaticCenter = function (params, callback) {
body = JSON.parse(res.body);
break;
default:
body = res.body
body = res.body;
break;
}
@ -913,7 +904,6 @@ TestClient.prototype.getNodeStatus = function(nodeName, callback) {
url += '?' + qs.stringify({api_key: this.apiKey});
}
var layergroupId;
var nodes = {};
step(
function createLayergroup() {
@ -952,10 +942,9 @@ TestClient.prototype.getNodeStatus = function(nodeName, callback) {
}
);
},
function getNodeStatusResult(err, _layergroupId) {
function getNodeStatusResult(err, layergroupId) {
assert.ifError(err);
layergroupId = _layergroupId;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
@ -995,11 +984,11 @@ TestClient.prototype.getAttributes = function(params, callback) {
var self = this;
if (!Number.isFinite(params.featureId)) {
throw new Error('featureId param must be a number')
throw new Error('featureId param must be a number');
}
if (!Number.isFinite(params.layer)) {
throw new Error('layer param must be a number')
throw new Error('layer param must be a number');
}
var url = '/api/v1/map';
@ -1011,7 +1000,7 @@ TestClient.prototype.getAttributes = function(params, callback) {
var layergroupid;
if (params.layergroupid) {
layergroupid = params.layergroupid
layergroupid = params.layergroupid;
}
step(
@ -1048,14 +1037,13 @@ TestClient.prototype.getAttributes = function(params, callback) {
}
);
},
function getAttributes(err, _layergroupid) {
function getAttributes(err, layergroupId) {
assert.ifError(err);
layergroupid = _layergroupid;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupid).token] = 0;
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
self.keysToDelete['user:localhost:mapviews:global'] = 5;
url = `/api/v1/map/${layergroupid}/${params.layer}/attributes/${params.featureId}`;
url = `/api/v1/map/${layergroupId}/${params.layer}/attributes/${params.featureId}`;
if (self.apiKey) {
url += '?' + qs.stringify({api_key: self.apiKey});
@ -1127,7 +1115,7 @@ module.exports.getStaticMap = function getStaticMap(templateName, params, callba
// this could be removed once named maps are invalidated, otherwise you hits the cache
var server = new CartodbWindshaft(serverOptions);
assert.response(self.server, requestOptions, expectedResponse, function (res, err) {
assert.response(server, requestOptions, expectedResponse, function (res, err) {
helper.deleteRedisKeys({'user:localhost:mapviews:global': 5}, function() {
return callback(err, mapnik.Image.fromBytes(new Buffer(res.body, 'binary')));
});
@ -1149,12 +1137,11 @@ TestClient.prototype.setUserRenderTimeoutLimit = function (user, userTimeoutLimi
TestClient.prototype.setUserDatabaseTimeoutLimit = function (timeoutLimit, callback) {
const dbname = _.template(global.environment.postgres_auth_user, { user_id: 1 }) + '_db';
const dbuser = _.template(global.environment.postgres_auth_user, { user_id: 1 })
const pass = _.template(global.environment.postgres_auth_pass, { user_id: 1 })
const dbuser = _.template(global.environment.postgres_auth_user, { user_id: 1 });
const publicuser = global.environment.postgres.user;
// we need to guarantee all new connections have the new settings
helper.cleanPGPoolConnections()
helper.cleanPGPoolConnections();
const psql = new PSQL({
user: 'postgres',