Merge branch 'standalone-server' into standalone-server-mvt

This commit is contained in:
Raul Ochoa 2015-09-18 02:31:38 +02:00
commit e9e95eda0a
28 changed files with 649 additions and 291 deletions

4
app.js
View File

@ -89,11 +89,11 @@ var server = cartodbWindshaft(serverOptions);
// 1 is good if you have max 16 filedescriptors
server.maxConnections = global.environment.maxConnections || 128;
server.listen(serverOptions.bind.port, serverOptions.bind.host);
var listener = server.listen(serverOptions.bind.port, serverOptions.bind.host);
var version = require("./package").version;
server.on('listening', function() {
listener.on('listening', function() {
console.log(
"Windshaft tileserver %s started on %s:%s PID=%d (%s)",
version, serverOptions.bind.host, serverOptions.bind.port, process.pid, ENVIRONMENT

View File

@ -17,8 +17,8 @@ module.exports = SurrogateKeysCache;
*/
SurrogateKeysCache.prototype.tag = function(response, cacheObject) {
var newKey = cacheObject.key();
response.header('Surrogate-Key', appendSurrogateKey(
response.header('Surrogate-Key'),
response.set('Surrogate-Key', appendSurrogateKey(
response.get('Surrogate-Key'),
Array.isArray(newKey) ? cacheObject.key().join(' ') : newKey
));

View File

@ -150,23 +150,33 @@ BaseController.prototype.req2params = function(req, callback){
};
// jshint maxcomplexity:6
BaseController.prototype.send = function(req, res, args) {
if (global.environment && global.environment.api_hostname) {
res.header('X-Served-By-Host', global.environment.api_hostname);
}
if (req.params && req.params.dbhost) {
res.header('X-Served-By-DB-Host', req.params.dbhost);
// jshint maxcomplexity:9
BaseController.prototype.send = function(req, res, body, status, headers) {
if (req.params.dbhost) {
res.set('X-Served-By-DB-Host', req.params.dbhost);
}
if (req.profiler) {
res.header('X-Tiler-Profiler', req.profiler.toJSONString());
res.set('X-Tiler-Profiler', req.profiler.toJSONString());
}
res.send.apply(res, args);
if (headers) {
res.set(headers);
}
if (req.profiler ) {
res.status(status);
if (!Buffer.isBuffer(body) && typeof body === 'object') {
if (req.query && req.query.callback) {
res.jsonp(body);
} else {
res.json(body);
}
} else {
res.send(body);
}
if (req.profiler) {
try {
// May throw due to dns, see
// See http://github.com/CartoDB/Windshaft/issues/166
@ -176,6 +186,7 @@ BaseController.prototype.send = function(req, res, args) {
}
}
};
// jshint maxcomplexity:6
BaseController.prototype.sendError = function(req, res, err, label) {
label = label || 'UNKNOWN';
@ -191,7 +202,7 @@ BaseController.prototype.sendError = function(req, res, err, label) {
var errorResponseBody = { errors: [errorMessage(err)] };
this.send(req, res, [errorResponseBody, statusCode]);
this.send(req, res, errorResponseBody, statusCode);
};
function errorMessage(err) {

View File

@ -77,7 +77,7 @@ LayergroupController.prototype.attributes = function(req, res) {
if (err) {
self.sendError(req, res, err, 'GET ATTRIBUTES');
} else {
self.sendResponse(req, res, [tile, 200]);
self.sendResponse(req, res, tile, 200);
}
}
);
@ -159,7 +159,7 @@ LayergroupController.prototype.finalizeGetTileOrGrid = function(err, req, res, t
global.statsClient.increment('windshaft.tiles.error');
global.statsClient.increment('windshaft.tiles.' + formatStat + '.error');
} else {
this.sendResponse(req, res, [tile, headers, 200]);
this.sendResponse(req, res, tile, 200, headers);
global.statsClient.increment('windshaft.tiles.success');
global.statsClient.increment('windshaft.tiles.' + formatStat + '.success');
}
@ -211,17 +211,17 @@ LayergroupController.prototype.staticMap = function(req, res, width, height, zoo
if (err) {
self.sendError(req, res, err, 'STATIC_MAP');
} else {
res.setHeader('Content-Type', headers['Content-Type'] || 'image/' + format);
self.sendResponse(req, res, [image, 200]);
res.set('Content-Type', headers['Content-Type'] || 'image/' + format);
self.sendResponse(req, res, image, 200);
}
}
);
};
LayergroupController.prototype.sendResponse = function(req, res, args) {
LayergroupController.prototype.sendResponse = function(req, res, body, status, headers) {
var self = this;
res.header('Cache-Control', 'public,max-age=31536000');
res.set('Cache-Control', 'public,max-age=31536000');
// Set Last-Modified header
var lastUpdated;
@ -231,7 +231,7 @@ LayergroupController.prototype.sendResponse = function(req, res, args) {
} else {
lastUpdated = new Date();
}
res.header('Last-Modified', lastUpdated.toUTCString());
res.set('Last-Modified', lastUpdated.toUTCString());
var dbName = req.params.dbname;
step(
@ -245,10 +245,10 @@ LayergroupController.prototype.sendResponse = function(req, res, args) {
}
if (!!affectedTables) {
var tablesCacheEntry = new TablesCacheEntry(dbName, affectedTables);
res.header('X-Cache-Channel', tablesCacheEntry.getCacheChannel());
res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel());
self.surrogateKeysCache.tag(res, tablesCacheEntry);
}
self.send(req, res, args);
self.send(req, res, body, status, headers);
}
);

View File

@ -166,8 +166,8 @@ MapController.prototype.create = function(req, res, prepareConfigFn) {
if (err) {
self.sendError(req, res, err, 'ANONYMOUS LAYERGROUP');
} else {
res.header('X-Layergroup-Id', layergroup.layergroupid);
self.send(req, res, [layergroup, 200]);
res.set('X-Layergroup-Id', layergroup.layergroupid);
self.send(req, res, layergroup, 200);
}
}
);
@ -223,10 +223,10 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
res.header('X-Layergroup-Id', layergroup.layergroupid);
res.set('X-Layergroup-Id', layergroup.layergroupid);
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName()));
self.send(req, res, [layergroup, 200]);
self.send(req, res, layergroup, 200);
}
}
);
@ -309,9 +309,9 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la
if (req.method === 'GET') {
var tableCacheEntry = new TablesCacheEntry(dbName, result.affectedTables);
var ttl = global.environment.varnish.layergroupTtl || 86400;
res.header('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
res.header('Last-Modified', (new Date()).toUTCString());
res.header('X-Cache-Channel', tableCacheEntry.getCacheChannel());
res.set('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
res.set('Last-Modified', (new Date()).toUTCString());
res.set('X-Cache-Channel', tableCacheEntry.getCacheChannel());
if (result.affectedTables && result.affectedTables.length > 0) {
self.surrogateKeysCache.tag(res, tableCacheEntry);
}

View File

@ -35,8 +35,8 @@ NamedMapsController.prototype.register = function(app) {
NamedMapsController.prototype.sendResponse = function(req, res, resource, headers, namedMapProvider) {
this.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(req.context.user, namedMapProvider.getTemplateName()));
res.header('Content-Type', headers['content-type'] || headers['Content-Type'] || 'image/png');
res.header('Cache-Control', 'public,max-age=7200,must-revalidate');
res.set('Content-Type', headers['content-type'] || headers['Content-Type'] || 'image/png');
res.set('Cache-Control', 'public,max-age=7200,must-revalidate');
var self = this;
@ -52,7 +52,7 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header
}
if (!result || !!result.affectedTables) {
// we increase cache control as we can invalidate it
res.header('Cache-Control', 'public,max-age=31536000');
res.set('Cache-Control', 'public,max-age=31536000');
var lastModifiedDate;
if (Number.isFinite(result.lastUpdatedTime)) {
@ -60,15 +60,15 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header
} else {
lastModifiedDate = new Date();
}
res.header('Last-Modified', lastModifiedDate.toUTCString());
res.set('Last-Modified', lastModifiedDate.toUTCString());
var tablesCacheEntry = new TablesCacheEntry(dbName, result.affectedTables);
res.header('X-Cache-Channel', tablesCacheEntry.getCacheChannel());
res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel());
if (result.affectedTables.length > 0) {
self.surrogateKeysCache.tag(res, tablesCacheEntry);
}
}
self.send(req, res, [resource, 200]);
self.send(req, res, resource, 200);
}
);
};

View File

@ -29,7 +29,7 @@ NamedMapsAdminController.prototype.register = function(app) {
app.post(app.base_url_templated, cors(), this.create.bind(this));
app.put(app.base_url_templated + '/:template_id', cors(), this.update.bind(this));
app.get(app.base_url_templated + '/:template_id', cors(), this.retrieve.bind(this));
app.del(app.base_url_templated + '/:template_id', cors(), this.destroy.bind(this));
app.delete(app.base_url_templated + '/:template_id', cors(), this.destroy.bind(this));
app.get(app.base_url_templated, cors(), this.list.bind(this));
app.options(app.base_url_templated + '/:template_id', cors('Content-Type'));
};
@ -144,9 +144,9 @@ NamedMapsAdminController.prototype.destroy = function(req, res) {
},
function prepareResponse(err/*, tpl_val*/){
assert.ifError(err);
return { status: 'ok' };
return '';
},
finishFn(self, req, res, 'DELETE TEMPLATE', ['', 204])
finishFn(self, req, res, 'DELETE TEMPLATE', 204)
);
};
@ -176,12 +176,12 @@ NamedMapsAdminController.prototype.list = function(req, res) {
);
};
function finishFn(controller, req, res, description, okResponse) {
function finishFn(controller, req, res, description, status) {
return function finish(err, response){
if (err) {
controller.sendError(req, res, err, description);
} else {
controller.send(req, res, okResponse || [response, 200]);
controller.send(req, res, response, status || 200);
}
};
}

View File

@ -27,11 +27,11 @@ ServerInfoController.prototype.register = function(app) {
};
ServerInfoController.prototype.welcome = function(req, res) {
res.send(WELCOME_MSG, 200);
res.status(200).send(WELCOME_MSG);
};
ServerInfoController.prototype.version = function(req, res) {
res.send(versions, 200);
res.status(200).send(versions);
};
ServerInfoController.prototype.health = function(req, res) {
@ -47,10 +47,10 @@ ServerInfoController.prototype.health = function(req, res) {
if (err) {
response.err = err.message;
}
res.send(response, ok ? 200 : 503);
res.status(ok ? 200 : 503).send(response);
});
} else {
res.send({enabled: false, ok: true}, 200);
res.status(200).send({enabled: false, ok: true});
}
};

View File

@ -4,8 +4,8 @@ module.exports = function cors(extraHeaders) {
if(extraHeaders) {
baseHeaders += ", " + extraHeaders;
}
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", baseHeaders);
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Headers", baseHeaders);
next();
};
};
};

View File

@ -1,4 +1,5 @@
var express = require('express');
var bodyParser = require('body-parser');
var RedisPool = require('redis-mpool');
var cartodbRedis = require('cartodb-redis');
var _ = require('underscore');
@ -241,10 +242,12 @@ function bootstrap(opts) {
app = express.createServer(opts.https);
} else {
// fall back to http by default
app = express.createServer();
app = express();
}
app.enable('jsonp callback');
app.use(express.bodyParser());
app.disable('x-powered-by');
app.disable('etag');
app.use(bodyParser.json());
app.use(function bootstrap$prepareRequestResponse(req, res, next) {
req.context = req.context || {};
@ -253,7 +256,9 @@ function bootstrap(opts) {
profile: opts.useProfiler
});
res.removeHeader('x-powered-by');
if (global.environment && global.environment.api_hostname) {
res.set('X-Served-By-Host', global.environment.api_hostname);
}
next();
});
@ -262,7 +267,7 @@ function bootstrap(opts) {
app.use(function(err, req, res, next) {
if (err) {
if (err.name === 'SyntaxError') {
res.send({ errors: [err.name + ': ' + err.message] }, 400);
res.status(400).json({ errors: [err.name + ': ' + err.message] });
} else {
next(err);
}
@ -277,7 +282,7 @@ function bootstrap(opts) {
}
function setupLogger(app, opts) {
if (opts.log_format) {
if (global.log4js && opts.log_format) {
var loggerOpts = {
// Allowing for unbuffered logging is mainly
// used to avoid hanging during unit testing.
@ -288,11 +293,7 @@ function setupLogger(app, opts) {
// optional log format
format: opts.log_format
};
if (global.log4js) {
app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level: 'info'})));
} else {
app.use(express.logger(loggerOpts));
}
app.use(global.log4js.connectLogger(global.log4js.getLogger(), _.defaults(loggerOpts, {level: 'info'})));
}
}

334
npm-shrinkwrap.json generated
View File

@ -2,6 +2,103 @@
"name": "windshaft-cartodb",
"version": "2.12.1",
"dependencies": {
"body-parser": {
"version": "1.14.0",
"from": "body-parser@~1.14.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.0.tgz",
"dependencies": {
"bytes": {
"version": "2.1.0",
"from": "bytes@2.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-2.1.0.tgz"
},
"content-type": {
"version": "1.0.1",
"from": "content-type@~1.0.1",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz"
},
"depd": {
"version": "1.1.0",
"from": "depd@~1.1.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz"
},
"http-errors": {
"version": "1.3.1",
"from": "http-errors@~1.3.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
"from": "inherits@~2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
},
"statuses": {
"version": "1.2.1",
"from": "statuses@1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz"
}
}
},
"iconv-lite": {
"version": "0.4.11",
"from": "iconv-lite@0.4.11",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.11.tgz"
},
"on-finished": {
"version": "2.3.0",
"from": "on-finished@~2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"dependencies": {
"ee-first": {
"version": "1.1.1",
"from": "ee-first@1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz"
}
}
},
"qs": {
"version": "5.1.0",
"from": "qs@5.1.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz"
},
"raw-body": {
"version": "2.1.3",
"from": "raw-body@~2.1.3",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.3.tgz",
"dependencies": {
"unpipe": {
"version": "1.0.0",
"from": "unpipe@1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz"
}
}
},
"type-is": {
"version": "1.6.8",
"from": "type-is@~1.6.8",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.8.tgz",
"dependencies": {
"media-typer": {
"version": "0.3.0",
"from": "media-typer@0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
},
"mime-types": {
"version": "2.1.6",
"from": "mime-types@~2.1.6",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz",
"dependencies": {
"mime-db": {
"version": "1.18.0",
"from": "mime-db@~1.18.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.18.0.tgz"
}
}
}
}
}
}
},
"cartodb-psql": {
"version": "0.4.0",
"from": "cartodb-psql@~0.4.0",
@ -84,36 +181,227 @@
"resolved": "https://registry.npmjs.org/dot/-/dot-1.0.3.tgz"
},
"express": {
"version": "2.5.11",
"from": "express@~2.5.11",
"resolved": "https://registry.npmjs.org/express/-/express-2.5.11.tgz",
"version": "4.13.3",
"from": "express@~4.13.3",
"resolved": "https://registry.npmjs.org/express/-/express-4.13.3.tgz",
"dependencies": {
"connect": {
"version": "1.9.2",
"from": "connect@1.x",
"resolved": "https://registry.npmjs.org/connect/-/connect-1.9.2.tgz",
"accepts": {
"version": "1.2.13",
"from": "accepts@~1.2.12",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz",
"dependencies": {
"formidable": {
"version": "1.0.17",
"from": "formidable@1.0.x",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz"
"mime-types": {
"version": "2.1.6",
"from": "mime-types@~2.1.6",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz",
"dependencies": {
"mime-db": {
"version": "1.18.0",
"from": "mime-db@~1.18.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.18.0.tgz"
}
}
},
"negotiator": {
"version": "0.5.3",
"from": "negotiator@0.5.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz"
}
}
},
"mime": {
"version": "1.2.4",
"from": "mime@1.2.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.2.4.tgz"
"array-flatten": {
"version": "1.1.1",
"from": "array-flatten@1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz"
},
"content-disposition": {
"version": "0.5.0",
"from": "content-disposition@0.5.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.0.tgz"
},
"content-type": {
"version": "1.0.1",
"from": "content-type@~1.0.1",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz"
},
"cookie": {
"version": "0.1.3",
"from": "cookie@0.1.3",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz"
},
"cookie-signature": {
"version": "1.0.6",
"from": "cookie-signature@1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz"
},
"depd": {
"version": "1.0.1",
"from": "depd@~1.0.1",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz"
},
"escape-html": {
"version": "1.0.2",
"from": "escape-html@1.0.2",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz"
},
"etag": {
"version": "1.7.0",
"from": "etag@~1.7.0",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz"
},
"finalhandler": {
"version": "0.4.0",
"from": "finalhandler@0.4.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.0.tgz",
"dependencies": {
"unpipe": {
"version": "1.0.0",
"from": "unpipe@~1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz"
}
}
},
"fresh": {
"version": "0.3.0",
"from": "fresh@0.3.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz"
},
"merge-descriptors": {
"version": "1.0.0",
"from": "merge-descriptors@1.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.0.tgz"
},
"methods": {
"version": "1.1.1",
"from": "methods@~1.1.1",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.1.tgz"
},
"on-finished": {
"version": "2.3.0",
"from": "on-finished@~2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"dependencies": {
"ee-first": {
"version": "1.1.1",
"from": "ee-first@1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz"
}
}
},
"parseurl": {
"version": "1.3.0",
"from": "parseurl@~1.3.0",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.0.tgz"
},
"path-to-regexp": {
"version": "0.1.7",
"from": "path-to-regexp@0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz"
},
"proxy-addr": {
"version": "1.0.8",
"from": "proxy-addr@~1.0.8",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.8.tgz",
"dependencies": {
"forwarded": {
"version": "0.1.0",
"from": "forwarded@~0.1.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz"
},
"ipaddr.js": {
"version": "1.0.1",
"from": "ipaddr.js@1.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.1.tgz"
}
}
},
"qs": {
"version": "0.4.2",
"from": "qs@0.4.x",
"resolved": "https://registry.npmjs.org/qs/-/qs-0.4.2.tgz"
"version": "4.0.0",
"from": "qs@4.0.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz"
},
"mkdirp": {
"version": "0.3.0",
"from": "mkdirp@0.3.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz"
"range-parser": {
"version": "1.0.2",
"from": "range-parser@~1.0.2",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.2.tgz"
},
"send": {
"version": "0.13.0",
"from": "send@0.13.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.13.0.tgz",
"dependencies": {
"destroy": {
"version": "1.0.3",
"from": "destroy@1.0.3",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.3.tgz"
},
"http-errors": {
"version": "1.3.1",
"from": "http-errors@~1.3.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz",
"dependencies": {
"inherits": {
"version": "2.0.1",
"from": "inherits@~2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
}
}
},
"mime": {
"version": "1.3.4",
"from": "mime@1.3.4",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz"
},
"ms": {
"version": "0.7.1",
"from": "ms@0.7.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz"
},
"statuses": {
"version": "1.2.1",
"from": "statuses@~1.2.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz"
}
}
},
"serve-static": {
"version": "1.10.0",
"from": "serve-static@~1.10.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.0.tgz"
},
"type-is": {
"version": "1.6.8",
"from": "type-is@~1.6.6",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.8.tgz",
"dependencies": {
"media-typer": {
"version": "0.3.0",
"from": "media-typer@0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
},
"mime-types": {
"version": "2.1.6",
"from": "mime-types@~2.1.6",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz",
"dependencies": {
"mime-db": {
"version": "1.18.0",
"from": "mime-db@~1.18.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.18.0.tgz"
}
}
}
}
},
"utils-merge": {
"version": "1.0.0",
"from": "utils-merge@1.0.0",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz"
},
"vary": {
"version": "1.0.1",
"from": "vary@~1.0.1",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz"
}
}
},
@ -306,7 +594,7 @@
},
"mime-types": {
"version": "2.1.6",
"from": "mime-types@~2.1.2",
"from": "mime-types@~2.1.6",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.6.tgz",
"dependencies": {
"mime-db": {

View File

@ -22,7 +22,8 @@
"Sandro Santilli <strk@vizzuality.com>"
],
"dependencies": {
"express": "~2.5.11",
"express": "~4.13.3",
"body-parser": "~1.14.0",
"debug": "~2.2.0",
"step-profiler": "~0.2.1",
"node-statsd": "~0.0.7",

View File

@ -1,4 +1,4 @@
require(__dirname + '/../../support/test_helper');
require('../../support/test_helper');
var assert = require('../../support/assert');
var redis = require('redis');

View File

@ -22,7 +22,7 @@ describe('tests from old api translated to multilayer', function() {
// 'map_style|null|publicuser|my_table',
redisClient.keys("map_style|*", function(err, matches) {
redisClient.del(matches, function() {
done();
testHelper.deleteRedisKeys({ 'user:cartodb250user:mapviews:global': 5 }, done);
});
});
});

View File

@ -235,7 +235,10 @@ describe('attributes', function() {
assert.ifError(err);
// jsonp errors should be returned with HTTP status 200
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
assert.equal(res.body, 'test({"errors":["Layer 0 has no exposed attributes"]});');
assert.equal(
res.body,
'/**/ typeof test === \'function\' && test({"errors":["Layer 0 has no exposed attributes"]});'
);
return null;
},
function do_get_attr_1(err)

View File

@ -1,4 +1,4 @@
require('../../support/test_helper');
var testHelper = require('../../support/test_helper');
var assert = require('../../support/assert');
@ -7,6 +7,8 @@ var PortedServerOptions = require('./support/ported_server_options');
var http = require('http');
var testClient = require('./support/test_client');
var nock = require('nock');
var BaseController = require('../../../lib/cartodb/controllers/base');
function rmdir_recursive_sync(dirname) {
@ -33,6 +35,8 @@ describe('external resources', function() {
var req2paramsFn;
before(function(done) {
nock.enableNetConnect('127.0.0.1');
req2paramsFn = BaseController.prototype.req2params;
BaseController.prototype.req2params = PortedServerOptions.req2params;
// Start a server to test external resources
@ -58,8 +62,13 @@ describe('external resources', function() {
rmdir_recursive_sync(global.environment.millstone.cache_basedir);
// Close the resources server
res_serv.close(done);
testHelper.deleteRedisKeys({
'user:localhost:mapviews:global': 5
}, function() {
// Close the resources server
res_serv.close(done);
});
});
function imageCompareFn(fixture, done) {
@ -73,7 +82,7 @@ describe('external resources', function() {
it("basic external resource", function(done) {
var circleStyle = "#test_table_3 { marker-file: url('http://localhost:" + res_serv_port +
var circleStyle = "#test_table_3 { marker-file: url('http://127.0.0.1:" + res_serv_port +
"/circle.svg'); marker-transform:'scale(0.2)'; }";
testClient.getTile(testClient.defaultTableMapConfig('test_table_3', circleStyle), 13, 4011, 3088,
@ -82,7 +91,7 @@ describe('external resources', function() {
it("different external resource", function(done) {
var squareStyle = "#test_table_3 { marker-file: url('http://localhost:" + res_serv_port +
var squareStyle = "#test_table_3 { marker-file: url('http://127.0.0.1:" + res_serv_port +
"/square.svg'); marker-transform:'scale(0.2)'; }";
testClient.getTile(testClient.defaultTableMapConfig('test_table_3', squareStyle), 13, 4011, 3088,
@ -96,7 +105,7 @@ describe('external resources', function() {
serverOptions: PortedServerOptions
};
var externalResourceStyle = "#test_table_3{marker-file: url('http://localhost:" + res_serv_port +
var externalResourceStyle = "#test_table_3{marker-file: url('http://127.0.0.1:" + res_serv_port +
"/square.svg'); marker-transform:'scale(0.2)'; }";
var externalResourceMapConfig = testClient.defaultTableMapConfig('test_table_3', externalResourceStyle);
@ -122,7 +131,7 @@ describe('external resources', function() {
});
it("referencing unexistant external resources returns an error", function(done) {
var url = "http://localhost:" + res_serv_port + "/notfound.png";
var url = "http://127.0.0.1:" + res_serv_port + "/notfound.png";
var style = "#test_table_3{marker-file: url('" + url + "'); marker-transform:'scale(0.2)'; }";
var mapConfig = testClient.defaultTableMapConfig('test_table_3', style);

View File

@ -56,7 +56,10 @@ describe('multilayer error cases', function() {
headers: {'Content-Type': 'application/json' }
}, {}, function(res) {
assert.equal(res.statusCode, 200);
assert.equal(res.body, 'test({"errors":["Missing layers array from layergroup config"]});');
assert.equal(
res.body,
'/**/ typeof test === \'function\' && test({"errors":["Missing layers array from layergroup config"]});'
);
done();
});
});
@ -340,7 +343,10 @@ describe('multilayer error cases', function() {
}
};
testClient.createLayergroup(bogusSqlMapConfig, options, function(err, res) {
assert.ok(/^test\(/.test(res.body), "Body start expected callback name: " + res.body);
assert.ok(
/^\/\*\*\/ typeof test === 'function' && test\(/.test(res.body),
"Body start expected callback name: " + res.body
);
assert.ok(/syntax error/.test(res.body), "Unexpected error: " + res.body);
done();
});
@ -356,7 +362,10 @@ describe('multilayer error cases', function() {
}
};
testClient.createLayergroup(noGeomMapConfig, options, function(err, res) {
assert.ok(/^test\(/.test(res.body), "Body start expected callback name: " + res.body);
assert.ok(
/^\/\*\*\/ typeof test === 'function' && test\(/.test(res.body),
"Body start expected callback name: " + res.body
);
assert.ok(/column.*does not exist/.test(res.body), "Unexpected error: " + res.body);
done();
});

View File

@ -1,10 +1,8 @@
require('../../support/test_helper');
var assert = require('../../support/assert');
var _ = require('underscore');
var fs = require('fs');
var http = require('http');
var cartodbServer = require('../../../lib/cartodb/server');
var ServerOptions = require('./support/ported_server_options');
var testClient = require('./support/test_client');
@ -102,37 +100,4 @@ describe('regressions', function() {
done();
});
});
// See https://github.com/CartoDB/Windshaft/issues/167
it("#167 does not die on unexistent statsd host", function(done) {
var CustomOptions = _.clone(ServerOptions);
CustomOptions.statsd = _.clone(CustomOptions.statsd);
CustomOptions.statsd.host = 'whoami.vizzuality.com';
CustomOptions.statsd.cacheDns = false;
var server = cartodbServer(CustomOptions);
server.req2params = CustomOptions.req2params;
server.setMaxListeners(0);
var errors = [];
// We need multiple requests to make sure
// statsd_client eventually tries to send
// stats _and_ DNS lookup is given enough
// time (an interval is used later for that)
var numreq = 10;
var pending = numreq;
var completed = function(err) {
if ( err ) {
errors.push(err);
}
if ( ! --pending ) {
setTimeout(function() {
done(errors.length ? new Error(errors.join(',')) : null);
}, 10);
}
};
var mapConfig = testClient.defaultTableMapConfig('test_table');
for (var i=0; i<numreq; ++i) {
testClient.createLayergroup(mapConfig, { server: server }, completed);
}
});
});

View File

@ -111,13 +111,20 @@ describe('server', function() {
it("grid jsonp", function(done){
var mapConfig = testClient.singleLayerMapConfig('select * from test_table', null, null, 'name');
testClient.getGridJsonp(mapConfig, 0, 13, 4011, 3088, 'test', function(err, res) {
testClient.getGridJsonp(mapConfig, 0, 13, 4011, 3088, 'jsonp_test', function(err, res) {
assert.equal(res.statusCode, 200, res.body);
assert.deepEqual(res.headers['content-type'], 'application/json; charset=utf-8');
var regexp = '^test\\((.*)\\);$';
var matches = res.body.match(regexp);
assert.equal(matches.length, 2, 'Unexpected JSONP response:' + res.body);
assert.utfgridEqualsFile(matches[1], './test/fixtures/test_table_13_4011_3088.grid.json', 2, done);
assert.deepEqual(res.headers['content-type'], 'text/javascript; charset=utf-8');
var didRunJsonCallback = false;
var response = {};
// jshint ignore:start
function jsonp_test(body) {
response = body;
didRunJsonCallback = true;
}
eval(res.body);
// jshint ignore:end
assert.ok(didRunJsonCallback);
assert.utfgridEqualsFile(response, './test/fixtures/test_table_13_4011_3088.grid.json', 2, done);
});
});
@ -145,7 +152,7 @@ describe('server', function() {
}
};
testClient.getGrid(mapConfig, 0, 13, 4011, 3088, expectedResponse, function(err, res) {
console.log(res.body);
assert.deepEqual(JSON.parse(res.body), {"errors":["Tileset has no interactivity"]});
done();
});
});

View File

@ -44,6 +44,7 @@ server.setMaxListeners(0);
var redisClient = redis.createClient(global.environment.redis.port);
var jsonContentType = 'application/json; charset=utf-8';
var jsContentType = 'text/javascript; charset=utf-8';
var pngContentType = 'image/png';
function createLayergroup(layergroupConfig, options, callback) {
@ -75,9 +76,20 @@ function createLayergroup(layergroupConfig, options, callback) {
var parsedBody;
var layergroupid;
if (!options.callbackName) {
if (options.callbackName) {
global[options.callbackName] = function(layergroup) {
layergroupid = layergroup.layergroupid;
};
// jshint ignore:start
eval(res.body);
// jshint ignore:end
delete global[options.callbackName];
} else {
parsedBody = JSON.parse(res.body);
layergroupid = parsedBody.layergroupid;
if (layergroupid) {
layergroupid = layergroupid.split(':')[0];
}
}
if (layergroupid) {
@ -218,7 +230,7 @@ function getGrid(layergroupConfig, layer, z, x, y, expectedResponse, callback) {
function getGridJsonp(layergroupConfig, layer, z, x, y, jsonpCallbackName, expectedResponse, callback) {
if (!callback) {
callback = expectedResponse;
expectedResponse = jsonContentType;
expectedResponse = jsContentType;
}
var options = {
@ -369,7 +381,7 @@ function getGeneric(layergroupConfig, url, expectedResponse, callback) {
},
function validateTile(err, res) {
assert.ok(!err, 'Failed to get tile');
var redisKey = 'map_cfg|' + layergroupid;
var redisKey = 'map_cfg|' + layergroupid.split(':')[0];
var img;
if (contentType === pngContentType) {
@ -454,7 +466,7 @@ function withLayergroup(layergroupConfig, options, callback) {
}
function finish(done) {
var redisKey = 'map_cfg|' + layergroupid;
var redisKey = 'map_cfg|' + layergroupid.split(':')[0];
redisClient.del(redisKey, function (delErr) {
return done(delErr);
});

View File

@ -1,4 +1,4 @@
require('../support/test_helper');
var testHelper = require('../support/test_helper');
var assert = require('../support/assert');
var qs = require('querystring');
@ -106,6 +106,13 @@ describe('get requests x-cache-channel', function() {
describe('header should be present', function() {
after(function(done) {
testHelper.deleteRedisKeys({
'map_cfg|a181ac96fac6d2b315dda88bc0bfa6cd': 0,
'user:localhost:mapviews:global': 5
}, done);
});
it('/api/v1/map Map instantiation', function(done) {
assert.response(
server,

View File

@ -0,0 +1,46 @@
require('../support/test_helper');
var assert = require('assert');
var StatsClient = require('../../lib/cartodb/stats/client');
var ProfilerProxy = require('../../lib/cartodb/stats/profiler_proxy');
describe('profiler + statsd', function() {
var statsInstance;
before(function() {
statsInstance = StatsClient.instance;
StatsClient.instance = null;
});
after(function() {
StatsClient.instance = statsInstance;
});
var statsdConfig = {
host: 'whoami.vizzuality.com',
port: 8125,
prefix: 'test.',
cacheDns: false
// support all allowed node-statsd options
};
// See https://github.com/CartoDB/Windshaft/issues/167
it('profiler does not throw uncaught exception on invalid host/port', function(done) {
var statsClient = StatsClient.getInstance(statsdConfig);
var profiler = new ProfilerProxy({profile: true, statsd_client: statsClient});
profiler.start('test');
profiler.done('wadus');
profiler.end();
profiler.sendStats();
// force a call to validate sendStats does not throw and uncaught exception
statsClient.timing('forced', 50, 1, function(err) {
assert.ok(err);
assert.equal(err.code, 'ENOTFOUND');
done();
});
});
});

View File

@ -1,11 +1,12 @@
// Cribbed from the ever prolific Konstantin Kaefer
// https://github.com/mapbox/tilelive-mapnik/blob/master/test/support/assert.js
var exec = require('child_process').exec,
fs = require('fs'),
http = require('http'),
path = require('path'),
util = require('util');
var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var util = require('util');
var request = require('request');
var assert = module.exports = exports = require('assert');
@ -82,140 +83,70 @@ function imageFilesAreEqual(testImageFilePath, referenceImageFilePath, tolerance
});
}
/**
* Assert response from `server` with
* the given `req` object and `res` assertions object.
*
* @param {Server|Object} server
* @param {Object} req
* @param {Object|Function} res
* @param {String|Function} msg
*/
// jshint maxcomplexity:12
assert.response = function(server, req, res, msg){
var port = 5555;
function check(){
try {
server.__port = server.address().port;
server.__listening = true;
} catch (err) {
process.nextTick(check);
return;
// jshint maxcomplexity:9
assert.response = function(server, req, res, callback) {
if (!callback) {
callback = res;
res = {};
}
var port = 5555,
host = '127.0.0.1';
var listeningAttempts = 0;
var listener;
function listen() {
if (listeningAttempts > 25) {
return callback(null, new Error('Tried too many ports'));
}
if (server.__deferred) {
server.__deferred.forEach(function(args){
assert.response.apply(assert, args);
});
server.__deferred = null;
}
}
// Check that the server is ready or defer
if (!server.fd) {
server.__deferred = server.__deferred || [];
server.listen(server.__port = port++, '127.0.0.1', check);
} else if (!server.__port) {
server.__deferred = server.__deferred || [];
process.nextTick(check);
}
// The socket was created but is not yet listening, so keep deferring
if (!server.__listening) {
server.__deferred.push(arguments);
return;
}
// Callback as third or fourth arg
var callback = typeof res === 'function' ? res : (typeof msg === 'function' ? msg : function(){});
// Default messate to test title
if (typeof msg === 'function') {
msg = null;
}
msg = msg || assert.testTitle;
msg += '. ';
// Pending responses
server.__pending = server.__pending || 0;
server.__pending++;
// Create client
if (!server.fd) {
server.listen(server.__port = port++, '127.0.0.1', issue);
} else {
issue();
}
// jshint maxcomplexity:8
function issue(){
// Issue request
var timer,
method = req.method || 'GET',
status = res.status || res.statusCode,
data = req.data || req.body,
requestTimeout = req.timeout || 0,
encoding = req.encoding || 'utf8';
var request = http.request({
host: '127.0.0.1',
port: server.__port,
path: req.url,
method: method,
headers: req.headers
listener = server.listen(port, host);
listener.on('error', function() {
port++;
listeningAttempts++;
listen();
});
listener.on('listening', onServerListening);
}
var check = function() {
if (--server.__pending === 0) {
server.close();
server.__listening = false;
}
listen();
// jshint maxcomplexity:9
function onServerListening() {
var status = res.status || res.statusCode;
var requestParams = {
url: 'http://' + host + ':' + port + req.url,
method: req.method || 'GET',
headers: req.headers || {},
timeout: req.timeout || 0,
encoding: req.encoding || 'utf8'
};
// Timeout
if (requestTimeout) {
timer = setTimeout(function(){
check();
delete req.timeout;
assert.fail(msg + 'Request timed out after ' + requestTimeout + 'ms.');
}, requestTimeout);
if (req.body || req.data) {
requestParams.body = req.body || req.data;
}
if (data) {
request.write(data);
}
request.on('response', function(response){
response.body = '';
response.setEncoding(encoding);
response.on('data', function(chunk){ response.body += chunk; });
response.on('end', function(){
if (timer) {
clearTimeout(timer);
}
check();
request(requestParams, function assert$response$requestHandler(error, response, body) {
listener.close(function() {
response.body = response.body || body;
// Assert response body
if (res.body !== undefined) {
if (res.body) {
var eql = res.body instanceof RegExp ? res.body.test(response.body) : res.body === response.body;
assert.ok(
eql,
msg + colorize('[red]{Invalid response body.}\n' +
' Expected: [green]{' + res.body + '}\n' +
' Got: [red]{' + response.body + '}')
colorize('[red]{Invalid response body.}\n' +
' Expected: [green]{' + res.body + '}\n' +
' Got: [red]{' + response.body + '}')
);
}
// Assert response status
if (typeof status === 'number') {
assert.equal(
response.statusCode,
status,
msg + colorize('[red]{Invalid response status code.}\n' +
' Expected: [green]{' + status + '}\n' +
' Got: [red]{' + response.statusCode + '}\n' +
' Body: ' + response.body)
assert.equal(response.statusCode, status,
colorize('[red]{Invalid response status code.}\n' +
' Expected: [green]{' + status + '}\n' +
' Got: [red]{' + response.statusCode + '}\n' +
' Body: ' + response.body)
);
}
@ -227,11 +158,10 @@ assert.response = function(server, req, res, msg){
actual = response.headers[name.toLowerCase()],
expected = res.headers[name],
headerEql = expected instanceof RegExp ? expected.test(actual) : expected === actual;
assert.ok(
headerEql,
msg + colorize('Invalid response header [bold]{' + name + '}.\n' +
' Expected: [green]{' + expected + '}\n' +
' Got: [red]{' + actual + '}')
assert.ok(headerEql,
colorize('Invalid response header [bold]{' + name + '}.\n' +
' Expected: [green]{' + expected + '}\n' +
' Got: [red]{' + actual + '}')
);
}
}
@ -241,12 +171,12 @@ assert.response = function(server, req, res, msg){
});
});
request.end();
}
};
// jshint maxcomplexity:6
// @param tolerance number of tolerated grid cell differences
// jshint maxcomplexity:8
// jshint maxcomplexity:9
assert.utfgridEqualsFile = function(buffer, file_b, tolerance, callback) {
fs.writeFileSync('/tmp/grid.json', buffer, 'binary'); // <-- to debug/update
var expected_json = JSON.parse(fs.readFileSync(file_b, 'utf8'));
@ -265,7 +195,7 @@ assert.utfgridEqualsFile = function(buffer, file_b, tolerance, callback) {
};
try {
var obtained_json = JSON.parse(buffer);
var obtained_json = Object.prototype.toString() === buffer.toString() ? buffer : JSON.parse(buffer);
// compare grid
var obtained_grid = obtained_json.grid;

View File

@ -10,6 +10,9 @@ var LZMA = require('lzma').LZMA;
var lzmaWorker = new LZMA();
var redis = require('redis');
var nock = require('nock');
// set environment specific variables
global.environment = require(__dirname + '/../../config/environments/test');
global.environment.name = 'test';
@ -56,23 +59,74 @@ function checkSurrogateKey(res, expectedKey) {
assert.equal(res.headers['surrogate-key'], expectedKey);
}
//var _ = require('underscore');
//var redis = require('redis');
// global afterEach to capture tests that leave keys in redis
//afterEach(function(done) {
// var redisClient = redis.createClient(global.environment.redis.port);
// // Check that we start with an empty redis db
// redisClient.keys("*", function(err, keys) {
// if ( err ) {
// return done(err);
// }
// assert.equal(keys.length, 0, "test left objects in redis:\n" + keys.join("\n"));
// redisClient.flushall(done);
// });
//});
//global after to capture test suites that leave keys in redis
after(function(done) {
// restoring nock globally after each suite
nock.cleanAll();
nock.enableNetConnect();
var expectedKeys = {
'rails:test_windshaft_cartodb_user_1_db:test_table_private_1': true,
'rails:test_windshaft_cartodb_user_1_db:my_table': true,
'rails:users:localhost:map_key': true,
'rails:users:cartodb250user': true,
'rails:users:localhost': true
};
var databasesTasks = { 0: 'users', 5: 'meta'};
var keysFound = [];
function taskDone(err, db, keys) {
if (err) {
return done(err);
}
delete databasesTasks[db];
keys.forEach(function(k) {
if (!expectedKeys[k]) {
keysFound.push(k);
}
});
if (Object.keys(databasesTasks).length === 0) {
//assert.equal(keysFound.length, 0, 'Unexpected keys found in redis: ' + keysFound.join(', '));
done();
}
}
Object.keys(databasesTasks).forEach(function(db) {
var redisClient = redis.createClient(global.environment.redis.port);
redisClient.select(db, function() {
// Check that we start with an empty redis db
redisClient.keys("*", function(err, keys) {
return taskDone(err, db, keys);
});
});
});
});
function deleteRedisKeys(keysToDelete, callback) {
function taskDone(k) {
delete keysToDelete[k];
if (Object.keys(keysToDelete).length === 0) {
callback();
}
}
Object.keys(keysToDelete).forEach(function(k) {
var redisClient = redis.createClient(global.environment.redis.port);
redisClient.select(keysToDelete[k], function() {
redisClient.del(k, function() {
taskDone(k);
});
});
});
}
module.exports = {
deleteRedisKeys: deleteRedisKeys,
lzma_compress_to_base64: lzma_compress_to_base64,
checkNoCache: checkNoCache,
checkSurrogateKey: checkSurrogateKey,

View File

@ -1,3 +1,5 @@
require('../../../../support/test_helper');
var assert = require('assert');
var _ = require('underscore');
var NamedMapsCacheEntry = require('../../../../../lib/cartodb/cache/model/named_maps_entry');

View File

@ -36,6 +36,9 @@ describe('tile stats', function() {
}
};
var resMock = {
status: function() { return this; },
json: function() {},
jsonp: function() {},
send: function() {}
};
layergroupController.finalizeGetTileOrGrid('Unsupported format png2', reqMock, resMock, null, null);
@ -61,6 +64,9 @@ describe('tile stats', function() {
}
};
var resMock = {
status: function() { return this; },
json: function() {},
jsonp: function() {},
send: function() {}
};

View File

@ -19,9 +19,9 @@ describe('windshaft', function() {
it('can spawn a new server on the global listen port', function(done){
var ws = cartodbServer(serverOptions);
ws.listen(global.environment.windshaft_port, function() {
var server = ws.listen(global.environment.windshaft_port, function() {
assert.ok(ws);
ws.close(done); /* allow proper tear down */
server.close(done); /* allow proper tear down */
});
});

View File

@ -1,4 +1,4 @@
require('../../support/test_helper');
var testHelper = require('../../support/test_helper');
var assert = require('assert');
var RedisPool = require('redis-mpool');
@ -11,6 +11,13 @@ describe('template_maps', function() {
// configure redis pool instance to use in tests
var redis_pool = new RedisPool(global.environment.redis);
after(function(done) {
testHelper.deleteRedisKeys({
'map_tpl|me': 0,
'map_tpl|you': 0
}, done);
});
var wadusLayer = {
options: {
sql: 'select 1 cartodb_id, null::geometry the_geom_webmercator',