b8365e9f6e
Some sample tests, which cannot use RNG seeding, are nondeterministical. Increment size of test table used in sampling tests to make less likely that the sample is empty
592 lines
22 KiB
JavaScript
592 lines
22 KiB
JavaScript
require('../../support/test_helper');
|
|
|
|
var assert = require('../../support/assert');
|
|
var TestClient = require('../../support/test-client');
|
|
|
|
describe('Create mapnik layergroup', function() {
|
|
before(function() {
|
|
this.layerStatsConfig = global.environment.enabledFeatures.layerStats;
|
|
global.environment.enabledFeatures.layerStats = true;
|
|
});
|
|
|
|
after(function() {
|
|
global.environment.enabledFeatures.layerStats = this.layerStatsConfig;
|
|
});
|
|
|
|
var cartocssVersion = '2.3.0';
|
|
var cartocss = '#layer { line-width:16; }';
|
|
|
|
var mapnikLayer1 = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: 'select * from test_table limit 1',
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
var mapnikLayer2 = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: 'select * from test_table_2 limit 2',
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
var mapnikLayer3 = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: 'select * from test_table_3 limit 3',
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
var mapnikLayer4 = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: [
|
|
'select t1.cartodb_id, t1.the_geom, t1.the_geom_webmercator, t2.address',
|
|
' from test_table t1, test_table_2 t2',
|
|
' where t1.cartodb_id = t2.cartodb_id'
|
|
].join(''),
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
var mapnikLayer100 = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: [
|
|
'SELECT * FROM test_table_100'
|
|
].join(''),
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
var httpLayer = {
|
|
type: 'http',
|
|
options: {
|
|
urlTemplate: 'http://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png',
|
|
subdomains: ['a','b','c']
|
|
}
|
|
};
|
|
|
|
var mapnikLayerGeomColumn = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: 'select *, the_geom as my_geom from test_table_3 limit 2',
|
|
geom_column: 'my_geom',
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
var mapnikLayerNullCats = {
|
|
type: 'mapnik',
|
|
options: {
|
|
sql: `
|
|
WITH geom AS (
|
|
SELECT
|
|
'SRID=4326;POINT(0 0)'::geometry AS the_geom,
|
|
'SRID=3857;POINT(0 0)'::geometry AS the_geom_webmercator
|
|
)
|
|
SELECT 1 AS cartodb_id, 'A' As cat, geom.* FROM geom
|
|
UNION
|
|
SELECT 2 AS cartodb_id, 'B' As cat, geom.* FROM geom
|
|
UNION
|
|
SELECT 2 AS cartodb_id, NULL::text As cat, geom.* FROM geom
|
|
`,
|
|
cartocss_version: cartocssVersion,
|
|
cartocss: cartocss
|
|
}
|
|
};
|
|
|
|
function mapnikBasicLayerId(index) {
|
|
return 'layer' + index;
|
|
}
|
|
function typeLayerId(type, index) {
|
|
return type + '-' + mapnikBasicLayerId(index);
|
|
}
|
|
|
|
it('with one mapnik layer should response with meta-stats for that layer', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer1
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 1);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with two mapnik layer should response with meta-stats for every layer', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer1,
|
|
mapnikLayer2
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 1);
|
|
assert.equal(layergroup.metadata.layers[1].id, mapnikBasicLayerId(1));
|
|
assert.equal(layergroup.metadata.layers[1].meta.stats.estimatedFeatureCount, 2);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with three mapnik layer should response with meta-stats for every layer', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer1,
|
|
mapnikLayer2,
|
|
mapnikLayer3
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 1);
|
|
assert.equal(layergroup.metadata.layers[1].id, mapnikBasicLayerId(1));
|
|
assert.equal(layergroup.metadata.layers[1].meta.stats.estimatedFeatureCount, 2);
|
|
assert.equal(layergroup.metadata.layers[2].id, mapnikBasicLayerId(2));
|
|
assert.equal(layergroup.metadata.layers[2].meta.stats.estimatedFeatureCount, 3);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with one mapnik layer (sql with join) should response with meta-stats for that layer', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer4
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with two mapnik layer (sql with join) should response with meta-stats for every layer', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer4,
|
|
mapnikLayer4
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
assert.equal(layergroup.metadata.layers[1].id, mapnikBasicLayerId(1));
|
|
assert.equal(layergroup.metadata.layers[1].meta.stats.estimatedFeatureCount, 5);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with two mapnik layer (with & without join) should response with meta-stats for every layer', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer3,
|
|
mapnikLayer4
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 3);
|
|
assert.ok(!layergroup.metadata.layers[0].meta.stats[1]);
|
|
assert.equal(layergroup.metadata.layers[1].id, mapnikBasicLayerId(1));
|
|
assert.equal(layergroup.metadata.layers[1].meta.stats.estimatedFeatureCount, 5);
|
|
assert.ok(!layergroup.metadata.layers[2]);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with mapnik and layer and httplayer should response with layer metadata with same order', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayer1,
|
|
httpLayer
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].type, 'mapnik');
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 1);
|
|
assert.equal(layergroup.metadata.layers[1].id, typeLayerId('http', 0));
|
|
assert.equal(layergroup.metadata.layers[1].type, 'http');
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('with httpLayer and mapnik layer should response with layer metadata with same order', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
httpLayer,
|
|
mapnikLayer1
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function (err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, typeLayerId('http', 0));
|
|
assert.equal(layergroup.metadata.layers[0].type, 'http');
|
|
assert.ok(!layergroup.metadata.layers[0].meta.cartocss);
|
|
assert.equal(layergroup.metadata.layers[1].meta.stats.estimatedFeatureCount, 1);
|
|
assert.equal(layergroup.metadata.layers[1].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[1].type, 'mapnik');
|
|
assert.equal(layergroup.metadata.layers[1].meta.cartocss, cartocss);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should work with different geom_column', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
mapnikLayerGeomColumn
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
// we don't care about stats here as is an aliased column
|
|
assert.ok(layergroup.metadata.layers[0].meta.stats.hasOwnProperty('estimatedFeatureCount'));
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should not include the stats part if the FF is disabled', function(done) {
|
|
global.environment.enabledFeatures.layerStats = false;
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
httpLayer,
|
|
mapnikLayer1,
|
|
httpLayer
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, typeLayerId('http', 0));
|
|
assert.equal(layergroup.metadata.layers[0].type, 'http');
|
|
assert.equal(layergroup.metadata.layers[1].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[1].type, 'mapnik');
|
|
assert.ok(!layergroup.metadata.layers[1].meta.hasOwnProperty('stats'));
|
|
assert.equal(layergroup.metadata.layers[2].id, typeLayerId('http', 1));
|
|
assert.equal(layergroup.metadata.layers[2].type, 'http');
|
|
global.environment.enabledFeatures.layerStats = true;
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
function layerWithMetadata(layer, metadata) {
|
|
return Object.assign(layer, {
|
|
options: Object.assign(layer.options, { metadata })
|
|
});
|
|
}
|
|
|
|
it('should provide columns as optional metadata', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer4, {
|
|
columns: true
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
const expectedColumns = {
|
|
cartodb_id: { type: 'number' },
|
|
the_geom: { type: 'geometry' },
|
|
the_geom_webmercator: { type: 'geometry' },
|
|
address: { type: 'string' }
|
|
};
|
|
assert.deepEqual(layergroup.metadata.layers[0].meta.stats.columns, expectedColumns);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
// metadata categories are ordered only partially by descending frequency;
|
|
// this orders them completely to avoid ambiguities when comparing
|
|
function withSortedCategories(columns) {
|
|
function catOrder(a, b) {
|
|
if (a.frequency !== b.frequency) {
|
|
return b.frequency - a.frequency;
|
|
}
|
|
if (a.category < b.category) {
|
|
return -1;
|
|
}
|
|
if (a.category > b.category) {
|
|
return +1;
|
|
}
|
|
return 0;
|
|
}
|
|
let sorted = {};
|
|
Object.keys(columns).forEach(name => {
|
|
let data = columns[name];
|
|
if (data.hasOwnProperty('categories')) {
|
|
data = Object.assign(data, { categories: data.categories.sort(catOrder)});
|
|
}
|
|
sorted[name] = data;
|
|
});
|
|
return sorted;
|
|
}
|
|
|
|
it('should provide column stats as optional metadata', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer4, {
|
|
columnStats: true
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
const expectedColumns = {
|
|
cartodb_id: {
|
|
type: 'number',
|
|
avg: 3,
|
|
max: 5,
|
|
min: 1,
|
|
sum: 15
|
|
},
|
|
the_geom: { type: 'geometry' },
|
|
the_geom_webmercator: { type: 'geometry' },
|
|
address: {
|
|
type: 'string',
|
|
categories: [
|
|
{
|
|
category: "Calle de la Palma 72, Madrid, Spain",
|
|
frequency: 1
|
|
},
|
|
{
|
|
category: "Calle de Pérez Galdós 9, Madrid, Spain",
|
|
frequency: 1
|
|
},
|
|
{
|
|
category: "Calle Divino Pastor 12, Madrid, Spain",
|
|
frequency: 1
|
|
},
|
|
{
|
|
category: "Manuel Fernández y González 8, Madrid, Spain",
|
|
frequency: 1
|
|
},
|
|
{
|
|
category: "Plaza Conde de Toreno 2, Madrid, Spain",
|
|
frequency: 1
|
|
}
|
|
]
|
|
}
|
|
};
|
|
assert.deepEqual(
|
|
withSortedCategories(layergroup.metadata.layers[0].meta.stats.columns),
|
|
withSortedCategories(expectedColumns)
|
|
);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should limit the number of categories as requested', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer4, {
|
|
columnStats: { topCategories: 2 }
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
const columnsMetadata = layergroup.metadata.layers[0].meta.stats.columns;
|
|
assert.equal(columnsMetadata.address.categories.length, 2);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should include null categories if requested', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayerNullCats, {
|
|
columnStats: { includeNulls: true }
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
const columnsMetadata = layergroup.metadata.layers[0].meta.stats.columns;
|
|
assert.equal(columnsMetadata.cat.categories.length, 3);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should not include null categories if not requested', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayerNullCats, {
|
|
columnStats: { includeNulls: false }
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
const columnsMetadata = layergroup.metadata.layers[0].meta.stats.columns;
|
|
assert.equal(columnsMetadata.cat.categories.length, 2);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should provide row count as optional metadata', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer4, {
|
|
featureCount: true
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.featureCount, 5);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should provide geometry type as optional metadata', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer4, {
|
|
geometryType: true
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.geometryType, 'ST_Point');
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('should provide a sample as optional metadata', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer100, {
|
|
sample: { num_rows: 30 }
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 100);
|
|
assert(layergroup.metadata.layers[0].meta.stats.sample.length > 0);
|
|
const expectedCols = [ 'cartodb_id', 'value', 'the_geom', 'the_geom_webmercator' ].sort();
|
|
assert.deepEqual(Object.keys(layergroup.metadata.layers[0].meta.stats.sample[0]).sort(), expectedCols);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
it('can specify sample columns', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer100, {
|
|
sample: {
|
|
num_rows: 30,
|
|
include_columns: [ 'cartodb_id', 'the_geom' ]
|
|
}
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 100);
|
|
assert(layergroup.metadata.layers[0].meta.stats.sample.length > 0);
|
|
const expectedCols = [ 'cartodb_id', 'the_geom' ].sort();
|
|
assert.deepEqual(Object.keys(layergroup.metadata.layers[0].meta.stats.sample[0]).sort(), expectedCols);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
|
|
it('should only provide requested optional metadata', function(done) {
|
|
var testClient = new TestClient({
|
|
version: '1.4.0',
|
|
layers: [
|
|
layerWithMetadata(mapnikLayer4, {
|
|
geometryType: true,
|
|
featureCount: true
|
|
})
|
|
]
|
|
});
|
|
|
|
testClient.getLayergroup(function(err, layergroup) {
|
|
assert.ifError(err);
|
|
assert.equal(layergroup.metadata.layers[0].id, mapnikBasicLayerId(0));
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.estimatedFeatureCount, 5);
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.geometryType, 'ST_Point');
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.featureCount, 5);
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.sample, undefined);
|
|
assert.equal(layergroup.metadata.layers[0].meta.stats.columns, undefined);
|
|
testClient.drain(done);
|
|
});
|
|
});
|
|
|
|
});
|