2013-02-25 22:08:28 +08:00
|
|
|
var assert = require('../support/assert');
|
|
|
|
var tests = module.exports = {};
|
|
|
|
var _ = require('underscore');
|
|
|
|
var redis = require('redis');
|
|
|
|
var querystring = require('querystring');
|
|
|
|
var semver = require('semver');
|
|
|
|
var Step = require('step');
|
2013-06-04 19:29:36 +08:00
|
|
|
var strftime = require('strftime');
|
2013-03-14 01:41:37 +08:00
|
|
|
var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js');
|
2013-06-04 19:29:36 +08:00
|
|
|
var redis_stats_db = 5;
|
2013-02-25 22:08:28 +08:00
|
|
|
|
2014-03-04 17:46:15 +08:00
|
|
|
var helper = require(__dirname + '/../support/test_helper');
|
2013-02-25 22:08:28 +08:00
|
|
|
|
|
|
|
var windshaft_fixtures = __dirname + '/../../node_modules/windshaft/test/fixtures';
|
|
|
|
|
2014-08-04 07:30:24 +08:00
|
|
|
var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20;
|
|
|
|
var IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL = 25;
|
|
|
|
|
2013-02-25 22:08:28 +08:00
|
|
|
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft');
|
2014-02-19 13:45:29 +08:00
|
|
|
var ServerOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
|
|
|
serverOptions = ServerOptions();
|
2013-02-25 22:08:28 +08:00
|
|
|
var server = new CartodbWindshaft(serverOptions);
|
|
|
|
server.setMaxListeners(0);
|
|
|
|
|
2015-03-19 01:15:26 +08:00
|
|
|
['/tiles/layergroup', '/u/rambo/tiles/layergroup'].forEach(function(layergroup_url) {
|
2014-08-07 03:48:08 +08:00
|
|
|
[true, false].forEach(function(cdbQueryTablesFromPostgresEnabledValue) {
|
|
|
|
|
2015-03-19 01:15:26 +08:00
|
|
|
suite('multilayer:postgres=' + cdbQueryTablesFromPostgresEnabledValue + "layergroup_url=" + layergroup_url, function() {
|
2013-02-25 22:08:28 +08:00
|
|
|
|
|
|
|
var redis_client = redis.createClient(global.environment.redis.port);
|
2013-03-13 18:55:57 +08:00
|
|
|
var sqlapi_server;
|
2013-04-04 19:15:50 +08:00
|
|
|
var expected_last_updated_epoch = 1234567890123; // this is hard-coded into SQLAPIEmu
|
|
|
|
var expected_last_updated = new Date(expected_last_updated_epoch).toISOString();
|
2013-02-25 22:08:28 +08:00
|
|
|
|
2014-02-21 01:03:43 +08:00
|
|
|
var test_user = _.template(global.environment.postgres_auth_user, {user_id:1});
|
|
|
|
var test_pubuser = global.environment.postgres.user;
|
|
|
|
var test_database = test_user + '_db';
|
|
|
|
|
2013-03-13 18:55:57 +08:00
|
|
|
suiteSetup(function(done){
|
2015-02-09 21:33:17 +08:00
|
|
|
global.environment.enabledFeatures = { cdbQueryTablesFromPostgres: cdbQueryTablesFromPostgresEnabledValue };
|
2013-03-14 01:41:37 +08:00
|
|
|
sqlapi_server = new SQLAPIEmu(global.environment.sqlapi.port, done);
|
2013-02-25 22:08:28 +08:00
|
|
|
});
|
|
|
|
|
2013-04-02 18:24:03 +08:00
|
|
|
test("layergroup with 2 layers, each with its style", function(done) {
|
2013-02-25 22:08:28 +08:00
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
2013-04-04 19:15:50 +08:00
|
|
|
cartocss_version: '2.0.1',
|
|
|
|
interactivity: 'cartodb_id'
|
2013-02-25 22:08:28 +08:00
|
|
|
} },
|
|
|
|
{ options: {
|
|
|
|
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, -5e6, 0) as the_geom_webmercator from test_table limit 2 offset 2',
|
|
|
|
cartocss: '#layer { marker-fill:blue; marker-allow-overlap:true; }',
|
2013-04-04 19:15:50 +08:00
|
|
|
cartocss_version: '2.0.2',
|
|
|
|
interactivity: 'cartodb_id'
|
2013-02-25 22:08:28 +08:00
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
2014-02-04 20:30:59 +08:00
|
|
|
var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7";
|
2013-02-25 22:08:28 +08:00
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2013-02-25 22:08:28 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
var expectedBody = { layergroupid: expected_token };
|
2013-03-14 01:41:37 +08:00
|
|
|
// check last modified
|
|
|
|
var qTables = JSON.stringify({
|
|
|
|
'q': 'SELECT CDB_QueryTables($windshaft$'
|
|
|
|
+ layergroup.layers[0].options.sql + ';'
|
|
|
|
+ layergroup.layers[1].options.sql
|
|
|
|
+ '$windshaft$)'
|
|
|
|
});
|
2013-04-04 19:15:50 +08:00
|
|
|
assert.equal(parsedBody.last_updated, expected_last_updated);
|
2013-03-14 01:41:37 +08:00
|
|
|
if ( expected_token ) {
|
2013-04-04 19:15:50 +08:00
|
|
|
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
2013-03-14 01:41:37 +08:00
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
else expected_token = parsedBody.layergroupid.split(':')[0];
|
2013-02-25 22:08:28 +08:00
|
|
|
next(null, res);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_tile(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png',
|
2013-02-25 22:08:28 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
2013-03-13 18:55:57 +08:00
|
|
|
|
2013-07-08 18:13:45 +08:00
|
|
|
// Check Cache-Control
|
|
|
|
var cc = res.headers['cache-control'];
|
|
|
|
assert.equal(cc, 'public,max-age=31536000'); // 1 year
|
|
|
|
|
2013-03-13 18:55:57 +08:00
|
|
|
// Check X-Cache-Channel
|
2013-07-08 18:13:45 +08:00
|
|
|
cc = res.headers['x-cache-channel'];
|
2013-03-13 23:45:15 +08:00
|
|
|
assert.ok(cc);
|
2014-02-21 01:03:43 +08:00
|
|
|
var dbname = test_database;
|
2013-03-13 18:55:57 +08:00
|
|
|
assert.equal(cc.substring(0, dbname.length), dbname);
|
2015-02-09 21:38:29 +08:00
|
|
|
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
|
|
|
var jsonquery = cc.substring(dbname.length + 1);
|
|
|
|
var sentquery = JSON.parse(jsonquery);
|
|
|
|
var expectedQuery = [layergroup.layers[0].options.sql, ';', layergroup.layers[1].options.sql].join('');
|
|
|
|
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$'
|
|
|
|
+ expectedQuery
|
|
|
|
+ '$windshaft$) as tablenames )'
|
|
|
|
+ ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max'
|
|
|
|
+ ' FROM CDB_TableMetadata m'
|
|
|
|
+ ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
|
|
|
}
|
2013-03-13 18:55:57 +08:00
|
|
|
|
2014-08-04 07:30:24 +08:00
|
|
|
assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png', IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL,
|
2013-02-25 22:08:28 +08:00
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
2014-03-04 01:06:39 +08:00
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/170
|
|
|
|
function do_get_tile_nosignature(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '/localhost@' + expected_token + ':cb0/0/0/0.png',
|
2014-03-04 01:06:39 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
2014-03-04 00:18:06 +08:00
|
|
|
assert.equal(res.statusCode, 403, res.statusCode + ':' + res.body);
|
2014-03-04 01:06:39 +08:00
|
|
|
var parsed = JSON.parse(res.body);
|
|
|
|
var msg = parsed.error; // TODO: should it be "errors" ?
|
2014-03-04 01:13:06 +08:00
|
|
|
assert.ok(msg.match(/permission denied/i), msg);
|
2014-03-04 01:06:39 +08:00
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
2013-02-25 22:08:28 +08:00
|
|
|
function do_get_grid_layer0(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-04-04 19:15:50 +08:00
|
|
|
+ '/0/0/0/0.grid.json',
|
2013-02-25 22:08:28 +08:00
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
2014-09-24 21:54:13 +08:00
|
|
|
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
2013-02-25 22:08:28 +08:00
|
|
|
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.layer0.grid.json', 2,
|
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid_layer1(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-04-04 19:15:50 +08:00
|
|
|
+ '/1/0/0/0.grid.json',
|
2013-02-25 22:08:28 +08:00
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
2014-09-24 21:54:13 +08:00
|
|
|
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
2013-02-25 22:08:28 +08:00
|
|
|
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.layer1.grid.json', 2,
|
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
var errors = [];
|
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2013-02-25 22:08:28 +08:00
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( errors.length ) done(new Error(errors));
|
|
|
|
else done(null);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2014-03-06 22:19:12 +08:00
|
|
|
|
|
|
|
test("should include serverMedata in the response", function(done) {
|
|
|
|
global.environment.serverMetadata = { cdn_url : { http:'test', https: 'tests' } }
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
var expected_token;
|
|
|
|
Step(
|
|
|
|
function do_create_get()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
2014-03-06 22:19:12 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost'}
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function do_check_create(err, res) {
|
|
|
|
var parsed = JSON.parse(res.body);
|
|
|
|
assert.ok(_.isEqual(parsed.cdn_url, global.environment.serverMetadata.cdn_url));
|
|
|
|
done();
|
|
|
|
}
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2014-06-24 19:13:00 +08:00
|
|
|
test("get creation requests has cache", function(done) {
|
2014-03-04 17:46:15 +08:00
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
var expected_token;
|
|
|
|
Step(
|
|
|
|
function do_create_get()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
2014-03-04 17:46:15 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost'}
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function do_check_create(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
expected_token = parsedBody.layergroupid.split(':')[0];
|
2014-06-24 19:13:00 +08:00
|
|
|
helper.checkCache(res);
|
2014-03-04 17:46:15 +08:00
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
var errors = [];
|
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( errors.length ) done(new Error(errors));
|
|
|
|
else done(null);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2014-06-24 19:13:00 +08:00
|
|
|
test("get creation has no cache if sql is bogus", function(done) {
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select bogus(0,0) as the_geom_webmercator',
|
|
|
|
cartocss: '#layer { polygon-fill: red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
2014-06-24 19:13:00 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost'}
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.notEqual(res.statusCode, 200);
|
|
|
|
helper.checkNoCache(res);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
test("get creation has no cache if cartocss is not valid", function(done) {
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
|
|
|
cartocss: '#layer { invalid-rule:red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify(layergroup)),
|
2014-06-24 19:13:00 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost'}
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.notEqual(res.statusCode, 200);
|
|
|
|
helper.checkNoCache(res);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
2013-04-02 18:24:03 +08:00
|
|
|
|
2013-03-28 19:48:00 +08:00
|
|
|
test("layergroup can hold substitution tokens", function(done) {
|
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select 1 as cartodb_id, '
|
2015-02-09 21:38:29 +08:00
|
|
|
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator from test_table limit 1',
|
2013-03-28 19:48:00 +08:00
|
|
|
cartocss: '#layer { polygon-fill:red; }',
|
2013-04-04 19:15:50 +08:00
|
|
|
cartocss_version: '2.0.1',
|
|
|
|
interactivity: 'cartodb_id'
|
2013-03-28 19:48:00 +08:00
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
2014-02-04 20:30:59 +08:00
|
|
|
var expected_token; // = "6d8e4ad5458e2d25cf0eef38e38717a6";
|
2013-03-28 19:48:00 +08:00
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2013-03-28 19:48:00 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
var expectedBody = { layergroupid: expected_token };
|
|
|
|
// check last modified
|
|
|
|
var qTables = JSON.stringify({
|
|
|
|
'q': 'SELECT CDB_QueryTables($windshaft$'
|
|
|
|
+ layergroup.layers[0].options.sql
|
|
|
|
+ '$windshaft$)'
|
|
|
|
});
|
2013-04-04 19:15:50 +08:00
|
|
|
assert.equal(parsedBody.last_updated, expected_last_updated);
|
2013-03-28 19:48:00 +08:00
|
|
|
if ( expected_token ) {
|
2013-04-04 19:15:50 +08:00
|
|
|
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
2013-03-28 19:48:00 +08:00
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
else expected_token = parsedBody.layergroupid.split(':')[0];
|
2013-03-28 19:48:00 +08:00
|
|
|
next(null, res);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_tile1(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb10/1/0/0.png',
|
2013-03-28 19:48:00 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
|
|
|
|
|
|
|
// Check X-Cache-Channel
|
|
|
|
var cc = res.headers['x-cache-channel'];
|
2015-02-09 21:38:29 +08:00
|
|
|
assert.ok(cc);
|
2014-02-21 01:03:43 +08:00
|
|
|
var dbname = test_database;
|
2013-03-28 19:48:00 +08:00
|
|
|
assert.equal(cc.substring(0, dbname.length), dbname);
|
2015-02-09 21:38:29 +08:00
|
|
|
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
|
|
|
var jsonquery = cc.substring(dbname.length + 1);
|
|
|
|
var sentquery = JSON.parse(jsonquery);
|
|
|
|
var expectedQuery = layergroup.layers[0].options.sql
|
|
|
|
.replace(/!bbox!/g, 'ST_MakeEnvelope(0,0,0,0)')
|
|
|
|
.replace(/!pixel_width!/g, '1')
|
|
|
|
.replace(/!pixel_height!/g, '1');
|
|
|
|
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$'
|
|
|
|
+ expectedQuery
|
|
|
|
+ '$windshaft$) as tablenames )'
|
|
|
|
+ ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max'
|
|
|
|
+ ' FROM CDB_TableMetadata m'
|
|
|
|
+ ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
|
|
|
}
|
2013-03-28 19:48:00 +08:00
|
|
|
|
2014-08-04 07:30:24 +08:00
|
|
|
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
2013-03-28 19:48:00 +08:00
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_tile4(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb11/4/0/0.png',
|
2013-03-28 19:48:00 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
|
|
|
|
|
|
|
// Check X-Cache-Channel
|
|
|
|
var cc = res.headers['x-cache-channel'];
|
|
|
|
assert.ok(cc);
|
2014-02-21 01:03:43 +08:00
|
|
|
var dbname = test_database;
|
2013-03-28 19:48:00 +08:00
|
|
|
assert.equal(cc.substring(0, dbname.length), dbname);
|
2015-02-09 21:38:29 +08:00
|
|
|
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
|
|
|
var jsonquery = cc.substring(dbname.length + 1);
|
|
|
|
var sentquery = JSON.parse(jsonquery);
|
|
|
|
var expectedQuery = layergroup.layers[0].options.sql
|
|
|
|
.replace('!bbox!', 'ST_MakeEnvelope(0,0,0,0)')
|
|
|
|
.replace('!pixel_width!', '1')
|
|
|
|
.replace('!pixel_height!', '1');
|
|
|
|
assert.equal(sentquery.q, 'WITH querytables AS ( SELECT * FROM CDB_QueryTables($windshaft$'
|
|
|
|
+ expectedQuery
|
|
|
|
+ '$windshaft$) as tablenames )'
|
|
|
|
+ ' SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max'
|
|
|
|
+ ' FROM CDB_TableMetadata m'
|
|
|
|
+ ' WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])');
|
|
|
|
}
|
2013-03-28 19:48:00 +08:00
|
|
|
|
2014-08-04 07:30:24 +08:00
|
|
|
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
2013-03-28 19:48:00 +08:00
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid1(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-04-04 19:15:50 +08:00
|
|
|
+ '/0/1/0/0.grid.json',
|
2013-03-28 19:48:00 +08:00
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
2014-09-24 21:54:13 +08:00
|
|
|
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
2013-03-28 19:48:00 +08:00
|
|
|
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.grid.json', 2,
|
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid4(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-04-04 19:15:50 +08:00
|
|
|
+ '/0/4/0/0.grid.json',
|
2013-03-28 19:48:00 +08:00
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
2014-09-24 21:54:13 +08:00
|
|
|
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
2013-03-28 19:48:00 +08:00
|
|
|
assert.utfgridEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.grid.json', 2,
|
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
var errors = [];
|
2013-04-12 23:28:34 +08:00
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2013-04-12 23:28:34 +08:00
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( errors.length ) done(new Error(errors));
|
|
|
|
else done(null);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test("layergroup creation raises mapviews counter", function(done) {
|
|
|
|
var layergroup = {
|
2013-06-04 19:29:36 +08:00
|
|
|
stat_tag: 'random_tag',
|
2013-04-12 23:28:34 +08:00
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
2013-06-19 23:24:01 +08:00
|
|
|
sql: 'select 1 as cartodb_id, !pixel_height! as h, '
|
2013-04-12 23:28:34 +08:00
|
|
|
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
|
|
|
cartocss: '#layer { polygon-fill:red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
2013-06-04 19:29:36 +08:00
|
|
|
var statskey = "user:localhost:mapviews";
|
2013-04-12 23:28:34 +08:00
|
|
|
var redis_stats_client = redis.createClient(global.environment.redis.port);
|
|
|
|
var expected_token; // will be set on first post and checked on second
|
2013-06-04 19:29:36 +08:00
|
|
|
var now = strftime("%Y%m%d", new Date());
|
|
|
|
var errors = [];
|
2013-04-12 23:28:34 +08:00
|
|
|
Step(
|
|
|
|
function clean_stats()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
redis_stats_client.select(redis_stats_db, function(err) {
|
|
|
|
if ( err ) next(err);
|
2013-06-04 19:29:36 +08:00
|
|
|
else redis_stats_client.del(statskey+':global', next);
|
2013-04-12 23:28:34 +08:00
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_post_1(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2013-04-12 23:28:34 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
expected_token = JSON.parse(res.body).layergroupid;
|
2013-06-04 19:29:36 +08:00
|
|
|
redis_stats_client.zscore(statskey + ":global", now, next);
|
2013-04-12 23:28:34 +08:00
|
|
|
});
|
|
|
|
},
|
2013-06-04 19:29:36 +08:00
|
|
|
function check_global_stats_1(err, val) {
|
2013-04-12 23:28:34 +08:00
|
|
|
if ( err ) throw err;
|
2013-06-04 19:29:36 +08:00
|
|
|
assert.equal(val, 1, "Expected score of " + now + " in "
|
|
|
|
+ statskey + ":global to be 1, got " + val);
|
|
|
|
redis_stats_client.zscore(statskey+':stat_tag:random_tag', now, this);
|
|
|
|
},
|
|
|
|
function check_tag_stats_1_do_post_2(err, val) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(val, 1, "Expected score of " + now + " in "
|
|
|
|
+ statskey + ":stat_tag:" + layergroup.stat_tag + " to be 1, got " + val);
|
2013-04-12 23:28:34 +08:00
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2013-04-12 23:28:34 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(JSON.parse(res.body).layergroupid, expected_token);
|
2013-06-04 19:29:36 +08:00
|
|
|
redis_stats_client.zscore(statskey+':global', now, next);
|
2013-04-12 23:28:34 +08:00
|
|
|
});
|
|
|
|
},
|
2013-06-04 19:29:36 +08:00
|
|
|
function check_global_stats_2(err, val)
|
2013-04-12 23:28:34 +08:00
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
2013-06-04 19:29:36 +08:00
|
|
|
assert.equal(val, 2, "Expected score of " + now + " in "
|
|
|
|
+ statskey + ":global to be 2, got " + val);
|
|
|
|
redis_stats_client.zscore(statskey+':stat_tag:' + layergroup.stat_tag, now, this);
|
|
|
|
},
|
|
|
|
function check_tag_stats_2(err, val)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(val, 2, "Expected score of " + now + " in "
|
|
|
|
+ statskey + ":stat_tag:" + layergroup.stat_tag + " to be 2, got " + val);
|
2013-04-12 23:28:34 +08:00
|
|
|
return 1;
|
|
|
|
},
|
2013-06-04 19:29:36 +08:00
|
|
|
function cleanup_map_style(err) {
|
|
|
|
if ( err ) errors.push('' + err);
|
|
|
|
var next = this;
|
2013-04-04 19:15:50 +08:00
|
|
|
// trip epoch
|
|
|
|
expected_token = expected_token.split(':')[0];
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2013-06-04 19:29:36 +08:00
|
|
|
redis_client.del(matches, next);
|
2013-03-28 19:48:00 +08:00
|
|
|
});
|
2013-06-04 19:29:36 +08:00
|
|
|
},
|
|
|
|
function cleanup_stats(err) {
|
|
|
|
if ( err ) errors.push('' + err);
|
|
|
|
redis_client.del([statskey+':global', statskey+':stat_tag:'+layergroup.stat_tag], this);
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
if ( err ) errors.push('' + err);
|
|
|
|
if ( errors.length ) done(new Error(errors.join(',')));
|
|
|
|
else done(null);
|
2013-03-28 19:48:00 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2013-06-10 17:53:28 +08:00
|
|
|
test("layergroup creation fails if CartoCSS is bogus", function(done) {
|
|
|
|
var layergroup = {
|
|
|
|
stat_tag: 'random_tag',
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select 1 as cartodb_id, !pixel_height! as h'
|
|
|
|
+ 'ST_Buffer(!bbox!, -32*greatest(!pixel_width!,!pixel_height!)) as the_geom_webmercator',
|
|
|
|
cartocss: '#layer { polygon-fit:red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2013-06-10 17:53:28 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 400, res.body);
|
|
|
|
var parsed = JSON.parse(res.body);
|
|
|
|
assert.ok(parsed.errors[0].match(/^style0/));
|
|
|
|
assert.ok(parsed.errors[0].match(/Unrecognized rule: polygon-fit/));
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-01-15 18:53:19 +08:00
|
|
|
// Also tests that server doesn't crash:
|
|
|
|
// see http://github.com/CartoDB/Windshaft-cartodb/issues/109
|
|
|
|
test("layergroup creation fails if sql is bogus", function(done) {
|
|
|
|
var layergroup = {
|
|
|
|
stat_tag: 'random_tag',
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select bogus(0,0) as the_geom_webmercator',
|
|
|
|
cartocss: '#layer { polygon-fill:red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2014-01-15 18:53:19 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
2014-02-28 17:54:18 +08:00
|
|
|
assert.equal(res.statusCode, 404, res.statusCode + ": " + res.body);
|
2014-01-15 18:53:19 +08:00
|
|
|
var parsed = JSON.parse(res.body);
|
|
|
|
var msg = parsed.errors[0];
|
|
|
|
assert.ok(msg.match(/bogus.*exist/), msg);
|
2014-03-04 17:46:15 +08:00
|
|
|
helper.checkNoCache(res);
|
2014-01-15 18:53:19 +08:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-06-17 23:24:09 +08:00
|
|
|
test("layergroup with 2 private-table layers", function(done) {
|
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select * from test_table_private_1 where cartodb_id=1',
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
2013-09-13 00:37:25 +08:00
|
|
|
cartocss_version: '2.1.0',
|
2013-06-17 23:24:09 +08:00
|
|
|
interactivity: 'cartodb_id'
|
|
|
|
} },
|
|
|
|
{ options: {
|
|
|
|
sql: 'select * from test_table_private_1 where cartodb_id=2',
|
|
|
|
cartocss: '#layer { marker-fill:blue; marker-allow-overlap:true; }',
|
2013-09-13 00:37:25 +08:00
|
|
|
cartocss_version: '2.1.0',
|
2013-06-17 23:24:09 +08:00
|
|
|
interactivity: 'cartodb_id'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
2014-02-04 20:30:59 +08:00
|
|
|
var expected_token; // = "b4ed64d93a411a59f330ab3d798e4009";
|
2013-06-17 23:24:09 +08:00
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:26:33 +08:00
|
|
|
url: layergroup_url + '?map_key=1234',
|
2013-06-17 23:24:09 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
var expectedBody = { layergroupid: expected_token };
|
|
|
|
// check last modified
|
|
|
|
var qTables = JSON.stringify({
|
|
|
|
'q': 'SELECT CDB_QueryTables($windshaft$'
|
|
|
|
+ layergroup.layers[0].options.sql + ';'
|
|
|
|
+ layergroup.layers[1].options.sql
|
|
|
|
+ '$windshaft$)'
|
|
|
|
});
|
|
|
|
assert.equal(parsedBody.last_updated, expected_last_updated);
|
|
|
|
if ( expected_token ) {
|
|
|
|
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
else expected_token = parsedBody.layergroupid.split(':')[0];
|
2013-06-17 23:24:09 +08:00
|
|
|
next(null, res);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_tile(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234',
|
2013-06-17 23:24:09 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
|
|
|
|
|
|
|
// Check X-Cache-Channel
|
|
|
|
var cc = res.headers['x-cache-channel'];
|
|
|
|
assert.ok(cc);
|
2014-02-21 01:03:43 +08:00
|
|
|
var dbname = test_database;
|
2013-06-17 23:24:09 +08:00
|
|
|
assert.equal(cc.substring(0, dbname.length), dbname);
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid_layer0(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-06-17 23:24:09 +08:00
|
|
|
+ '/0/0/0/0.grid.json?map_key=1234',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid_layer1(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-06-17 23:24:09 +08:00
|
|
|
+ '/1/0/0/0.grid.json?map_key=1234',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
2014-09-24 21:54:13 +08:00
|
|
|
assert.equal(res.headers['content-type'], "application/json; charset=utf-8");
|
2013-06-17 23:24:09 +08:00
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
2013-09-23 17:59:03 +08:00
|
|
|
function do_get_tile_unauth(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png',
|
2013-09-23 17:59:03 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
2014-03-04 00:18:06 +08:00
|
|
|
assert.equal(res.statusCode, 403);
|
2013-09-23 17:59:03 +08:00
|
|
|
var re = RegExp('permission denied');
|
|
|
|
assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body);
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid_layer0_unauth(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-09-23 17:59:03 +08:00
|
|
|
+ '/0/0/0/0.grid.json',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
2014-03-04 00:18:06 +08:00
|
|
|
assert.equal(res.statusCode, 403);
|
2013-09-23 17:59:03 +08:00
|
|
|
var re = RegExp('permission denied');
|
|
|
|
assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body);
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_grid_layer1_unauth(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token
|
2013-09-23 17:59:03 +08:00
|
|
|
+ '/1/0/0/0.grid.json',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
method: 'GET'
|
|
|
|
}, {}, function(res) {
|
2014-03-04 00:18:06 +08:00
|
|
|
assert.equal(res.statusCode, 403);
|
2013-09-23 17:59:03 +08:00
|
|
|
var re = RegExp('permission denied');
|
|
|
|
assert.ok(res.body.match(re), 'No "permission denied" error: ' + res.body);
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
},
|
2013-06-17 23:24:09 +08:00
|
|
|
function finish(err) {
|
|
|
|
var errors = [];
|
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2013-06-17 23:24:09 +08:00
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( errors.length ) done(new Error(errors));
|
|
|
|
else done(null);
|
|
|
|
});
|
2014-02-19 01:33:00 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/152
|
2014-02-19 17:08:25 +08:00
|
|
|
test("x-cache-channel still works for GETs after tiler restart", function(done) {
|
2014-02-19 01:33:00 +08:00
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select * from test_table where cartodb_id=1',
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
|
|
|
cartocss_version: '2.1.0',
|
|
|
|
interactivity: 'cartodb_id'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
var expected_token; // = "b4ed64d93a411a59f330ab3d798e4009";
|
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:26:33 +08:00
|
|
|
url: layergroup_url + '?map_key=1234',
|
2014-02-19 01:33:00 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function check_post(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
var expectedBody = { layergroupid: expected_token };
|
|
|
|
// check last modified
|
|
|
|
var qTables = JSON.stringify({
|
|
|
|
'q': 'SELECT CDB_QueryTables($windshaft$'
|
|
|
|
+ layergroup.layers[0].options.sql
|
|
|
|
+ '$windshaft$)'
|
|
|
|
});
|
|
|
|
assert.equal(parsedBody.last_updated, expected_last_updated);
|
|
|
|
if ( expected_token ) {
|
|
|
|
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
|
|
|
}
|
|
|
|
else expected_token = parsedBody.layergroupid.split(':')[0];
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function do_get0(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234',
|
2014-02-19 01:33:00 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function do_check0(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
|
|
|
|
|
|
|
// Check X-Cache-Channel
|
|
|
|
var cc = res.headers['x-cache-channel'];
|
2014-02-19 13:45:29 +08:00
|
|
|
assert.ok(cc, "Missing X-Cache-Channel");
|
2014-02-21 01:03:43 +08:00
|
|
|
var dbname = test_database;
|
2014-02-19 01:33:00 +08:00
|
|
|
assert.equal(cc.substring(0, dbname.length), dbname);
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function do_restart_server(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
// hack simulating restart...
|
2014-02-19 13:45:29 +08:00
|
|
|
serverOptions = ServerOptions();
|
|
|
|
server = new CartodbWindshaft(serverOptions);
|
2014-02-19 01:33:00 +08:00
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function do_get1(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:53:49 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?map_key=1234',
|
2014-02-19 01:33:00 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function do_check1(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
|
|
|
|
|
|
|
// Check X-Cache-Channel
|
|
|
|
var cc = res.headers['x-cache-channel'];
|
2014-02-19 13:45:29 +08:00
|
|
|
assert.ok(cc, "Missing X-Cache-Channel on restart");
|
2014-02-21 01:03:43 +08:00
|
|
|
var dbname = test_database;
|
2014-02-19 01:33:00 +08:00
|
|
|
assert.equal(cc.substring(0, dbname.length), dbname);
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
var errors = [];
|
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( errors.length ) done(new Error(errors.join(',')));
|
|
|
|
else done(null);
|
|
|
|
});
|
2013-06-17 23:24:09 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2013-09-23 16:57:22 +08:00
|
|
|
// https://github.com/cartodb/Windshaft-cartodb/issues/81
|
|
|
|
test("invalid text-name in CartoCSS", function(done) {
|
2013-09-12 23:32:10 +08:00
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.1',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: "select 1 as cartodb_id, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
|
|
|
cartocss: '#sample { text-name: cartodb_id; text-face-name: "Dejagnu"; }',
|
2013-09-13 00:37:25 +08:00
|
|
|
cartocss_version: '2.1.0',
|
2013-09-12 23:32:10 +08:00
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
assert.response(server, {
|
|
|
|
url: '/tiles/layergroup?',
|
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
|
|
|
var parsed = JSON.parse(res.body);
|
2013-11-29 01:41:45 +08:00
|
|
|
assert.equal(parsed.errors.length, 1);
|
|
|
|
var errmsg = parsed.errors[0];
|
|
|
|
assert.ok(errmsg.match(/text-face-name.*Dejagnu/), parsed.errors.toString());
|
2013-09-12 23:32:10 +08:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-10-03 23:01:12 +08:00
|
|
|
test("quotes CartoCSS", function(done) {
|
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.1',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: "select 'single''quote' as n, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
|
|
|
cartocss: '#s [n="single\'quote" ] { marker-fill:red; }',
|
|
|
|
cartocss_version: '2.1.0',
|
|
|
|
} },
|
|
|
|
{ options: {
|
|
|
|
sql: "select 'double\"quote' as n, 'SRID=3857;POINT(2 0)'::geometry as the_geom_webmercator",
|
|
|
|
cartocss: '#s [n="double\\"quote" ] { marker-fill:red; }',
|
|
|
|
cartocss_version: '2.1.0',
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
assert.response(server, {
|
|
|
|
url: '/tiles/layergroup?',
|
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-11-08 19:34:34 +08:00
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/87
|
|
|
|
test("exponential notation in CartoCSS filter values", function(done) {
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.1',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: "select .4 as n, 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
|
|
|
cartocss: '#s [n<=.2e-2] { marker-fill:red; }',
|
|
|
|
cartocss_version: '2.1.0',
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
assert.response(server, {
|
|
|
|
url: '/tiles/layergroup?',
|
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-11-29 01:47:45 +08:00
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/93
|
|
|
|
test("accepts unused directives", function(done) {
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: "select 'SRID=3857;POINT(0 0)'::geometry as the_geom_webmercator",
|
|
|
|
cartocss: '#layer { point-transform:"scale(20)"; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7";
|
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2013-11-29 01:47:45 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
var expectedBody = { layergroupid: expected_token };
|
|
|
|
if ( expected_token ) {
|
|
|
|
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var token_components = parsedBody.layergroupid.split(':');
|
|
|
|
expected_token = token_components[0];
|
|
|
|
expected_last_updated_epoch = token_components[1];
|
|
|
|
}
|
|
|
|
next(null, res);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function do_get_tile(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:26:33 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png',
|
2013-11-29 01:47:45 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) {
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
assert.equal(res.headers['content-type'], "image/png");
|
2014-08-04 07:30:24 +08:00
|
|
|
assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
2013-11-29 01:47:45 +08:00
|
|
|
function(err, similarity) {
|
|
|
|
next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
var errors = [];
|
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2013-11-29 01:47:45 +08:00
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( errors.length ) done(new Error(errors));
|
|
|
|
else done(null);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2013-11-29 20:14:43 +08:00
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/91
|
|
|
|
// and https://github.com/CartoDB/Windshaft-cartodb/issues/38
|
2013-11-29 20:20:21 +08:00
|
|
|
test("tiles for private tables can be fetched with api_key", function(done) {
|
2013-11-29 20:14:43 +08:00
|
|
|
var errors = [];
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: "select * from test_table_private_1 LIMIT 0",
|
|
|
|
cartocss: '#layer { marker-fill:red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
var expected_token; // = "e34dd7e235138a062f8ba7ad051aa3a7";
|
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:26:33 +08:00
|
|
|
url: layergroup_url + '?api_key=1234',
|
2013-11-29 20:14:43 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res) { next(null, res); });
|
|
|
|
},
|
|
|
|
function check_result(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
if ( expected_token ) {
|
|
|
|
assert.equal(parsedBody.layergroupid, expected_token + ':' + expected_last_updated_epoch);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var token_components = parsedBody.layergroupid.split(':');
|
|
|
|
expected_token = token_components[0];
|
|
|
|
expected_last_updated_epoch = token_components[1];
|
|
|
|
}
|
|
|
|
next(null, res);
|
|
|
|
},
|
2013-11-29 20:20:21 +08:00
|
|
|
function do_get_tile(err)
|
|
|
|
{
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:26:33 +08:00
|
|
|
url: layergroup_url + "/" + expected_token + ':cb0/0/0/0.png?api_key=1234',
|
2013-11-29 20:20:21 +08:00
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost' },
|
|
|
|
encoding: 'binary'
|
|
|
|
}, {}, function(res) { next(null, res); });
|
|
|
|
},
|
|
|
|
function check_get_tile(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
var next = this;
|
|
|
|
assert.equal(res.statusCode, 200, res.body);
|
|
|
|
return null;
|
|
|
|
},
|
2013-11-29 20:14:43 +08:00
|
|
|
function cleanup(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
if ( ! expected_token ) return null;
|
|
|
|
var next = this;
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2013-11-29 20:14:43 +08:00
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
next();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
if ( err ) {
|
|
|
|
errors.push(err.message);
|
|
|
|
console.log("Error: " + err);
|
|
|
|
}
|
|
|
|
if ( errors.length ) done(new Error(errors));
|
|
|
|
else done(null);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2014-01-17 00:20:30 +08:00
|
|
|
// SQL strings can be of arbitrary length, when using POST
|
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/111
|
|
|
|
test("sql string can be very long", function(done){
|
|
|
|
var long_val = 'pretty';
|
|
|
|
for (var i=0; i<1024; ++i) long_val += ' long'
|
|
|
|
long_val += ' string';
|
|
|
|
var sql = "SELECT ";
|
|
|
|
for (var i=0; i<16; ++i)
|
|
|
|
sql += "'" + long_val + "'::text as pretty_long_field_name_" + i + ", ";
|
|
|
|
sql += "cartodb_id, the_geom_webmercator FROM gadm4 g";
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: sql,
|
|
|
|
cartocss: '#layer { marker-fill:red; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
var errors = [];
|
|
|
|
var expected_token;
|
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var data = JSON.stringify(layergroup);
|
|
|
|
assert.ok(data.length > 1024*64);
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '?api_key=1234',
|
2014-01-17 00:20:30 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: data
|
|
|
|
}, {}, function(res) { next(null, res); });
|
|
|
|
},
|
|
|
|
function check_result(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
var token_components = parsedBody.layergroupid.split(':');
|
|
|
|
expected_token = token_components[0];
|
2015-02-09 21:38:29 +08:00
|
|
|
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
|
|
|
var last_request = sqlapi_server.getLastRequest();
|
|
|
|
assert.equal(last_request.method, 'POST');
|
|
|
|
}
|
2014-01-17 00:20:30 +08:00
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function cleanup(err) {
|
2014-02-20 17:17:48 +08:00
|
|
|
if ( err ) errors.push('' + err);
|
2014-01-17 00:20:30 +08:00
|
|
|
if ( ! expected_token ) return null;
|
|
|
|
var next = this;
|
2014-02-04 20:30:59 +08:00
|
|
|
redis_client.keys("map_cfg|" + expected_token, function(err, matches) {
|
2014-01-17 00:20:30 +08:00
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
assert.equal(matches.length, 1, "Missing expected token " + expected_token + " from redis: " + matches);
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
if ( err ) errors.push(err.message);
|
|
|
|
next();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
if ( err ) errors.push('' + err);
|
|
|
|
if ( errors.length ) done(new Error(errors.join(',')));
|
|
|
|
else done(null);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2014-02-10 18:05:02 +08:00
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/133
|
|
|
|
test("MapConfig with mapnik layer and no cartocss", function(done) {
|
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select cartodb_id, ST_Translate(the_geom_webmercator, 5e6, 0) as the_geom_webmercator from test_table limit 2',
|
|
|
|
interactivity: 'cartodb_id'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2014-02-10 18:05:02 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function check_post(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
|
|
|
var parsed = JSON.parse(res.body);
|
|
|
|
assert.ok(parsed.errors, 'Missing "errors" in response: ' + JSON.stringify(parsed));
|
|
|
|
assert.equal(parsed.errors.length, 1);
|
|
|
|
var msg = parsed.errors[0];
|
|
|
|
assert.equal(msg, 'Missing cartocss for layer 0 options');
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
done(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2015-02-09 21:38:29 +08:00
|
|
|
if (!cdbQueryTablesFromPostgresEnabledValue) { // only test if it was using the SQL API
|
2014-02-27 17:26:42 +08:00
|
|
|
// See https://github.com/CartoDB/Windshaft-cartodb/issues/167
|
|
|
|
test("lack of response from sql-api will result in a timeout", function(done) {
|
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: "select *, 'SQLAPINOANSWER' from test_table",
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
|
|
|
cartocss_version: '2.1.0'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
Step(
|
|
|
|
function do_post()
|
|
|
|
{
|
|
|
|
var next = this;
|
|
|
|
assert.response(server, {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url,
|
2014-02-27 17:26:42 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
}, {}, function(res, err) { next(err, res); });
|
|
|
|
},
|
|
|
|
function check_post(err, res) {
|
|
|
|
if ( err ) throw err;
|
|
|
|
assert.equal(res.statusCode, 400, res.statusCode + ': ' + res.body);
|
|
|
|
var parsed = JSON.parse(res.body);
|
|
|
|
assert.ok(parsed.errors, 'Missing "errors" in response: ' + JSON.stringify(parsed));
|
|
|
|
assert.equal(parsed.errors.length, 1);
|
|
|
|
var msg = parsed.errors[0];
|
2014-02-27 20:37:44 +08:00
|
|
|
assert.ok(msg, /could not fetch source tables/, msg);
|
2014-02-27 17:26:42 +08:00
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
done(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2015-02-09 21:38:29 +08:00
|
|
|
}
|
2014-02-27 17:26:42 +08:00
|
|
|
|
2014-10-24 22:05:41 +08:00
|
|
|
var layergroupTtlRequest = {
|
2015-03-19 00:04:25 +08:00
|
|
|
url: layergroup_url + '?config=' + encodeURIComponent(JSON.stringify({
|
2014-10-24 22:05:41 +08:00
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{ options: {
|
|
|
|
sql: 'select * from test_table limit 2',
|
|
|
|
cartocss: '#layer { marker-fill:red; marker-width:32; marker-allow-overlap:true; }',
|
|
|
|
cartocss_version: '2.0.1'
|
|
|
|
} }
|
|
|
|
]
|
|
|
|
})),
|
|
|
|
method: 'GET',
|
|
|
|
headers: {host: 'localhost'}
|
|
|
|
};
|
|
|
|
var layergroupTtlResponseExpectation = {
|
|
|
|
status: 200
|
|
|
|
};
|
|
|
|
|
|
|
|
test("cache control for layergroup default value", function(done) {
|
|
|
|
global.environment.varnish.layergroupTtl = null;
|
|
|
|
|
|
|
|
assert.response(server, layergroupTtlRequest, layergroupTtlResponseExpectation,
|
|
|
|
function(res) {
|
|
|
|
assert.equal(res.headers['cache-control'], 'public,max-age=86400,must-revalidate');
|
|
|
|
|
|
|
|
done();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
test("cache control for layergroup uses configuration for max-age", function(done) {
|
|
|
|
var layergroupTtl = 300;
|
|
|
|
global.environment.varnish.layergroupTtl = layergroupTtl;
|
|
|
|
|
|
|
|
assert.response(server, layergroupTtlRequest, layergroupTtlResponseExpectation,
|
|
|
|
function(res) {
|
|
|
|
assert.equal(res.headers['cache-control'], 'public,max-age=' + layergroupTtl + ',must-revalidate');
|
|
|
|
|
|
|
|
done();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2014-01-17 00:20:30 +08:00
|
|
|
|
2015-02-05 23:46:56 +08:00
|
|
|
test("it's not possible to override authorization with a crafted layergroup", function(done) {
|
|
|
|
|
|
|
|
var layergroup = {
|
|
|
|
version: '1.0.0',
|
|
|
|
layers: [
|
|
|
|
{
|
|
|
|
options: {
|
|
|
|
sql: 'select * from test_table_private_1',
|
|
|
|
cartocss: '#layer { marker-fill:red; }',
|
|
|
|
cartocss_version: '2.3.0',
|
|
|
|
interactivity: 'cartodb_id'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
template: {
|
|
|
|
auth: {
|
|
|
|
method: "open"
|
|
|
|
},
|
|
|
|
name: "open"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
assert.response(
|
|
|
|
server,
|
|
|
|
{
|
|
|
|
url: '/api/v1/map?signer=localhost',
|
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: 'localhost',
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(layergroup)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
status: 403
|
|
|
|
},
|
|
|
|
function(res, err) {
|
|
|
|
assert.ok(res.body.match(/permission denied for relation test_table_private_1/));
|
|
|
|
done();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2013-02-25 22:08:28 +08:00
|
|
|
suiteTeardown(function(done) {
|
2013-06-04 19:29:36 +08:00
|
|
|
|
2013-02-25 22:08:28 +08:00
|
|
|
// This test will add map_style records, like
|
|
|
|
// 'map_style|null|publicuser|my_table',
|
|
|
|
redis_client.keys("map_style|*", function(err, matches) {
|
2013-03-28 19:48:00 +08:00
|
|
|
redis_client.del(matches, function(err) {
|
2013-06-04 19:29:36 +08:00
|
|
|
redis_client.select(5, function(err, matches) {
|
|
|
|
redis_client.keys("user:localhost:mapviews*", function(err, matches) {
|
|
|
|
redis_client.del(matches, function(err) {
|
|
|
|
sqlapi_server.close(done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2013-03-28 19:48:00 +08:00
|
|
|
});
|
2013-02-25 22:08:28 +08:00
|
|
|
});
|
2013-06-04 19:29:36 +08:00
|
|
|
|
2013-02-25 22:08:28 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2014-08-07 03:48:08 +08:00
|
|
|
});
|
2015-03-19 00:04:25 +08:00
|
|
|
});
|