2018-10-24 00:39:02 +08:00
|
|
|
'use strict';
|
|
|
|
|
2019-10-07 16:44:45 +08:00
|
|
|
var testHelper = require('../../support/test-helper');
|
2015-07-08 05:46:58 +08:00
|
|
|
|
|
|
|
var assert = require('../../support/assert');
|
2020-04-04 23:34:22 +08:00
|
|
|
const mapnik = require('@carto/mapnik');
|
2015-07-08 05:46:58 +08:00
|
|
|
var semver = require('semver');
|
2019-10-07 15:40:50 +08:00
|
|
|
var cartodbServer = require('../../../lib/server');
|
2019-10-07 16:44:45 +08:00
|
|
|
var ServerOptions = require('./support/ported-server-options');
|
|
|
|
var testClient = require('./support/test-client');
|
2015-07-08 05:46:58 +08:00
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
describe('server_gettile', function () {
|
2018-04-16 22:16:23 +08:00
|
|
|
var server;
|
2015-07-08 05:46:58 +08:00
|
|
|
|
2018-04-16 22:16:23 +08:00
|
|
|
before(function () {
|
|
|
|
server = cartodbServer(ServerOptions);
|
|
|
|
server.setMaxListeners(0);
|
|
|
|
});
|
2015-07-08 05:46:58 +08:00
|
|
|
|
|
|
|
var IMAGE_EQUALS_TOLERANCE_PER_MIL = 25;
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
after(function () {
|
2015-09-26 01:56:28 +08:00
|
|
|
testHelper.rmdirRecursiveSync(global.environment.millstone.cache_basedir);
|
2015-07-08 05:46:58 +08:00
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
function imageCompareFn (fixture, done) {
|
|
|
|
return function (err, res) {
|
2015-07-08 05:46:58 +08:00
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
}
|
2016-02-22 23:36:06 +08:00
|
|
|
assert.imageBufferIsSimilarToFile(
|
|
|
|
res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done
|
|
|
|
);
|
2015-07-08 05:46:58 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
/// /////////////////////////////////////////////////////////////////
|
2015-07-08 05:46:58 +08:00
|
|
|
//
|
|
|
|
// GET TILE
|
|
|
|
// --{
|
2019-10-22 01:07:24 +08:00
|
|
|
/// /////////////////////////////////////////////////////////////////
|
2015-07-08 05:46:58 +08:00
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it("get'ing a tile with default style should return an expected tile", function (done) {
|
|
|
|
testClient.getTile(testClient.defaultTableMapConfig('test_table'), 13, 4011, 3088,
|
|
|
|
imageCompareFn('test_table_13_4011_3088.png', done)
|
|
|
|
);
|
2015-07-08 05:46:58 +08:00
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it('response of get tile can be served by renderer cache', function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
var tileUrl = '/13/4011/3088.png';
|
|
|
|
var lastXwc;
|
|
|
|
var mapConfig = testClient.defaultTableMapConfig('test_table');
|
|
|
|
testClient.withLayergroup(mapConfig, function (err, requestTile, finish) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2015-07-08 05:46:58 +08:00
|
|
|
requestTile(tileUrl, function (err, res) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2018-05-28 16:32:31 +08:00
|
|
|
var xwc = parseInt(res.headers['x-windshaft-cache'], 10);
|
2015-07-08 05:46:58 +08:00
|
|
|
assert.ok(xwc);
|
|
|
|
assert.ok(xwc > 0);
|
|
|
|
lastXwc = xwc;
|
|
|
|
|
|
|
|
requestTile(tileUrl, function (err, res) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2018-05-28 16:32:31 +08:00
|
|
|
var xwc = parseInt(res.headers['x-windshaft-cache'], 10);
|
2015-07-08 05:46:58 +08:00
|
|
|
assert.ok(xwc);
|
|
|
|
assert.ok(xwc > 0);
|
|
|
|
assert.ok(xwc >= lastXwc);
|
|
|
|
|
2018-03-19 20:51:03 +08:00
|
|
|
requestTile(tileUrl, { cache_buster: 'wadus' }, function (err, res) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2018-05-28 16:32:31 +08:00
|
|
|
var xwc = parseInt(res.headers['x-windshaft-cache'], 10);
|
2015-07-08 05:46:58 +08:00
|
|
|
assert.ok(!xwc);
|
|
|
|
|
|
|
|
finish(done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it('should not choke when queries end with a semicolon', function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2;'), 0, 0, 0, done);
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it('should not choke when sql ends with a semicolon and some blanks', function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2; \t\n'), 0, 0, 0, done);
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it('should not strip quoted semicolons within an sql query', function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
testClient.getTile(
|
|
|
|
testClient.singleLayerMapConfig("SELECT * FROM test_table where name != ';\n'"), 0, 0, 0, done
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it('getting two tiles with same configuration uses renderer cache', function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
var imageFixture = './test/fixtures/test_table_13_4011_3088_styled.png';
|
|
|
|
var tileUrl = '/13/4011/3088.png';
|
|
|
|
var mapConfig = testClient.defaultTableMapConfig(
|
|
|
|
'test_table',
|
|
|
|
'#test_table{marker-fill: blue;marker-line-color: black;}'
|
|
|
|
);
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
function validateLayergroup (res) {
|
2015-07-08 05:46:58 +08:00
|
|
|
// cache is hit because we create a renderer to validate the map config
|
2019-10-22 05:33:27 +08:00
|
|
|
assert.ok(!Object.prototype.hasOwnProperty.call(res.headers, 'x-windshaft-cache'), 'Did hit renderer cache on first time');
|
2015-07-08 05:46:58 +08:00
|
|
|
}
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
testClient.withLayergroup(mapConfig, validateLayergroup, function (err, requestTile, finish) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2019-10-22 01:07:24 +08:00
|
|
|
requestTile(tileUrl, function (err, res) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2018-05-28 16:32:31 +08:00
|
|
|
var xwc = parseInt(res.headers['x-windshaft-cache'], 10);
|
2018-03-19 20:51:03 +08:00
|
|
|
assert.ok(!xwc);
|
|
|
|
|
|
|
|
requestTile(tileUrl, function (err, res) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2018-03-19 20:51:03 +08:00
|
|
|
assert.ok(
|
2019-10-22 05:33:27 +08:00
|
|
|
Object.prototype.hasOwnProperty.call(res.headers, 'x-windshaft-cache'),
|
2019-10-22 01:07:24 +08:00
|
|
|
'Did not hit renderer cache on second time'
|
2018-03-19 20:51:03 +08:00
|
|
|
);
|
2018-05-28 16:32:31 +08:00
|
|
|
assert.ok(parseInt(res.headers['x-windshaft-cache'], 10) >= 0);
|
2018-03-19 20:51:03 +08:00
|
|
|
|
|
|
|
assert.imageBufferIsSimilarToFile(res.body, imageFixture, IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
2019-10-22 01:07:24 +08:00
|
|
|
function (err) {
|
|
|
|
finish(function (finishErr) {
|
2018-03-19 20:51:03 +08:00
|
|
|
done(err || finishErr);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
2015-07-08 05:46:58 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2019-11-14 02:36:30 +08:00
|
|
|
var testStyleBlack200 = '#test_table{marker-fill:black;marker-line-color:black;marker-width:5}';
|
|
|
|
var testStyleBlack210 = '#test_table{marker-fill:black;marker-line-color:black;marker-width:10}';
|
2015-07-08 05:46:58 +08:00
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it("get'ing a tile with url specified 2.0.0 style should return an expected tile", function (done) {
|
2019-11-14 02:36:30 +08:00
|
|
|
testClient.getTile(testClient.defaultTableMapConfig('test_table', testStyleBlack200, '2.0.0'),
|
2015-07-08 05:46:58 +08:00
|
|
|
13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
it("get'ing a tile with url specified 2.1.0 style should return an expected tile", function (done) {
|
2019-11-14 02:36:30 +08:00
|
|
|
testClient.getTile(testClient.defaultTableMapConfig('test_table', testStyleBlack210, '2.1.0'),
|
2015-07-08 05:46:58 +08:00
|
|
|
13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
|
|
|
|
});
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
if (semver.satisfies(mapnik.versions.mapnik, '2.3.x')) {
|
2016-12-19 23:16:50 +08:00
|
|
|
// See http://github.com/CartoDB/Windshaft/issues/99
|
2019-10-22 01:07:24 +08:00
|
|
|
it('unused directives are tolerated', function (done) {
|
2016-12-19 23:16:50 +08:00
|
|
|
var style = "#test_table{point-transform: 'scale(100)';}";
|
|
|
|
var sql = "SELECT 1 as cartodb_id, 'SRID=4326;POINT(0 0)'::geometry as the_geom";
|
|
|
|
testClient.getTile(testClient.singleLayerMapConfig(sql, style), 0, 0, 0,
|
|
|
|
imageCompareFn('test_default_mapnik_point.png', done));
|
|
|
|
});
|
|
|
|
}
|
2015-07-08 05:46:58 +08:00
|
|
|
|
|
|
|
// See http://github.com/CartoDB/Windshaft/issues/100
|
2019-11-14 02:36:30 +08:00
|
|
|
var testStrictness = function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
var nonStrictMapConfig = testClient.singleLayerMapConfig(
|
|
|
|
"SELECT 1 as cartodb_id, 'SRID=3857;POINT(666 666)'::geometry as the_geom",
|
|
|
|
"#test_table{point-transform: 'scale(100)';}"
|
|
|
|
);
|
2019-10-22 01:07:24 +08:00
|
|
|
testClient.withLayergroup(nonStrictMapConfig, function (err, requestTile, finish) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2015-07-08 05:46:58 +08:00
|
|
|
var options = {
|
|
|
|
statusCode: 400,
|
|
|
|
contentType: 'application/json; charset=utf-8'
|
|
|
|
};
|
2019-10-22 01:07:24 +08:00
|
|
|
requestTile('/0/0/0.png?strict=1', options, function () {
|
2015-07-08 05:46:58 +08:00
|
|
|
finish(done);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2019-11-14 02:36:30 +08:00
|
|
|
var testStrictLbl = 'unused directives are not tolerated if strict';
|
2019-10-22 01:07:24 +08:00
|
|
|
if (semver.satisfies(mapnik.versions.mapnik, '2.3.x')) {
|
|
|
|
// Strictness handling changed in 2.3.x, possibly a bug: see http://github.com/mapnik/mapnik/issues/2301
|
2019-11-14 02:36:30 +08:00
|
|
|
it.skip('[skipped due to http://github.com/mapnik/mapnik/issues/2301]' + testStrictLbl, testStrictness);
|
2019-10-22 01:07:24 +08:00
|
|
|
} else if (!semver.satisfies(mapnik.versions.mapnik, '3.0.x')) {
|
2019-11-14 02:36:30 +08:00
|
|
|
it(testStrictLbl, testStrictness);
|
2015-07-08 05:46:58 +08:00
|
|
|
}
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
if (semver.satisfies(mapnik.versions.mapnik, '2.3.x')) {
|
|
|
|
it('high cpu regression with mapnik <2.3.x', function (done) {
|
2016-12-19 23:16:50 +08:00
|
|
|
var sql = [
|
|
|
|
"SELECT 'my polygon name here' AS name,",
|
2019-10-22 01:07:24 +08:00
|
|
|
'st_envelope(st_buffer(st_transform(',
|
|
|
|
'st_setsrid(st_makepoint(-26.6592894004,49.7990296995),4326),3857),10000000)) AS the_geom',
|
|
|
|
'FROM generate_series(-6,6) x',
|
|
|
|
'UNION ALL',
|
2016-12-19 23:16:50 +08:00
|
|
|
"SELECT 'my marker name here' AS name,",
|
2019-10-22 01:07:24 +08:00
|
|
|
' st_transform(st_setsrid(st_makepoint(49.6042060319,-49.0522997372),4326),3857) AS the_geom',
|
|
|
|
'FROM generate_series(-6,6) x'
|
2016-12-19 23:16:50 +08:00
|
|
|
].join(' ');
|
|
|
|
|
|
|
|
var style = [
|
|
|
|
'#test_table {marker-fill:#ff7;',
|
|
|
|
' marker-max-error:0.447492761618;',
|
|
|
|
' marker-line-opacity:0.659371340628;',
|
|
|
|
' marker-allow-overlap:true;',
|
|
|
|
' polygon-fill:green;',
|
|
|
|
' marker-spacing:0.0;',
|
|
|
|
' marker-width:4.0;',
|
|
|
|
' marker-height:18.0;',
|
|
|
|
' marker-opacity:0.942312062822;',
|
|
|
|
' line-color:green;',
|
|
|
|
' line-gamma:0.945973211092;',
|
|
|
|
' line-cap:square;',
|
|
|
|
' polygon-opacity:0.12576055992;',
|
|
|
|
' marker-type:arrow;',
|
|
|
|
' polygon-gamma:0.46354913107;',
|
|
|
|
' line-dasharray:33,23;',
|
|
|
|
' line-join:bevel;',
|
|
|
|
' marker-placement:line;',
|
|
|
|
' line-width:1.0;',
|
|
|
|
' marker-line-color:#ff7;',
|
|
|
|
' line-opacity:0.39403752154;',
|
|
|
|
' marker-line-width:3.0;',
|
|
|
|
'}'
|
|
|
|
].join('');
|
|
|
|
|
|
|
|
testClient.getTile(testClient.singleLayerMapConfig(sql, style), 13, 4011, 3088, done);
|
|
|
|
});
|
|
|
|
}
|
2015-07-08 05:46:58 +08:00
|
|
|
// https://github.com/CartoDB/Windshaft-cartodb/issues/316
|
2019-10-22 01:07:24 +08:00
|
|
|
it('should return errors with better formatting', function (done) {
|
2015-07-08 05:46:58 +08:00
|
|
|
var mapConfig = {
|
2019-10-22 01:07:24 +08:00
|
|
|
version: '1.0.1',
|
|
|
|
minzoom: 0,
|
|
|
|
maxzoom: 20,
|
|
|
|
layers: [
|
2015-07-08 05:46:58 +08:00
|
|
|
{
|
2019-10-22 01:07:24 +08:00
|
|
|
type: 'mapnik',
|
|
|
|
options: {
|
|
|
|
cartocss_version: '2.1.1',
|
|
|
|
sql: 'SELECT null::geometry AS the_geom',
|
|
|
|
cartocss: [
|
2015-07-08 05:46:58 +08:00
|
|
|
'@water: #cdd2d4;',
|
|
|
|
'Map {',
|
|
|
|
'\tbackground-color: @water;',
|
|
|
|
'\tbufferz-size: 256;',
|
|
|
|
'}',
|
|
|
|
'@landmass_fill: lighten(#e3e3dc, 8%);'
|
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
2019-10-22 01:07:24 +08:00
|
|
|
type: 'mapnik',
|
|
|
|
options: {
|
|
|
|
cartocss_version: '2.1.1',
|
|
|
|
sql: "SELECT the_geom FROM false_background_zoomed('!scale_denominator!', !bbox!) AS _",
|
|
|
|
cartocss: [
|
2015-07-08 05:46:58 +08:00
|
|
|
'#false_background {',
|
|
|
|
'\tpolygon-fill: @landmass_fill;',
|
|
|
|
'}'
|
|
|
|
].join('\n')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
};
|
|
|
|
|
|
|
|
var options = {
|
|
|
|
statusCode: 400
|
|
|
|
};
|
|
|
|
|
2019-10-22 01:07:24 +08:00
|
|
|
testClient.createLayergroup(mapConfig, options, function (err, res, parsedBody) {
|
2019-10-25 00:38:37 +08:00
|
|
|
assert.ifError(err);
|
2015-07-08 05:46:58 +08:00
|
|
|
assert.ok(parsedBody.errors);
|
|
|
|
// more assertions when errors is populated with better format
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|