CDB-3686 Adds support for per mil tolerance when comparing images as in Mac OS X some results from ImageMagick are a bit odd
This commit is contained in:
parent
9b5921e8e1
commit
73d1db3bd2
@ -14,6 +14,9 @@ var helper = require(__dirname + '/../support/test_helper');
|
|||||||
|
|
||||||
var windshaft_fixtures = __dirname + '/../../node_modules/windshaft/test/fixtures';
|
var windshaft_fixtures = __dirname + '/../../node_modules/windshaft/test/fixtures';
|
||||||
|
|
||||||
|
var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20;
|
||||||
|
var IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL = 25;
|
||||||
|
|
||||||
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft');
|
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft');
|
||||||
var ServerOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
var ServerOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
||||||
serverOptions = ServerOptions();
|
serverOptions = ServerOptions();
|
||||||
@ -117,7 +120,7 @@ suite('multilayer', function() {
|
|||||||
+ expectedQuery
|
+ expectedQuery
|
||||||
+ '$windshaft$)::regclass[])');
|
+ '$windshaft$)::regclass[])');
|
||||||
|
|
||||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png', 2,
|
assert.imageEqualsFile(res.body, 'test/fixtures/test_table_0_0_0_multilayer1.png', IMAGE_EQUALS_HIGHER_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
@ -400,7 +403,7 @@ suite('multilayer', function() {
|
|||||||
+ expectedQuery
|
+ expectedQuery
|
||||||
+ '$windshaft$)::regclass[])');
|
+ '$windshaft$)::regclass[])');
|
||||||
|
|
||||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', 2,
|
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
@ -438,7 +441,7 @@ suite('multilayer', function() {
|
|||||||
+ expectedQuery
|
+ expectedQuery
|
||||||
+ '$windshaft$)::regclass[])');
|
+ '$windshaft$)::regclass[])');
|
||||||
|
|
||||||
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', 2,
|
assert.imageEqualsFile(res.body, 'test/fixtures/test_multilayer_bbox.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
@ -1067,7 +1070,7 @@ suite('multilayer', function() {
|
|||||||
}, {}, function(res) {
|
}, {}, function(res) {
|
||||||
assert.equal(res.statusCode, 200, res.body);
|
assert.equal(res.statusCode, 200, res.body);
|
||||||
assert.equal(res.headers['content-type'], "image/png");
|
assert.equal(res.headers['content-type'], "image/png");
|
||||||
assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png', 2,
|
assert.imageEqualsFile(res.body, windshaft_fixtures + '/test_default_mapnik_point.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,9 @@ var SQLAPIEmu = require(__dirname + '/../support/SQLAPIEmu.js');
|
|||||||
|
|
||||||
var helper = require(__dirname + '/../support/test_helper');
|
var helper = require(__dirname + '/../support/test_helper');
|
||||||
|
|
||||||
|
var IMAGE_EQUALS_TOLERANCE_PER_MIL = 20,
|
||||||
|
IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL = 0;
|
||||||
|
|
||||||
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft');
|
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/cartodb_windshaft');
|
||||||
var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')();
|
var serverOptions = require(__dirname + '/../../lib/cartodb/server_options')();
|
||||||
var server = new CartodbWindshaft(serverOptions);
|
var server = new CartodbWindshaft(serverOptions);
|
||||||
@ -842,7 +845,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', 2,
|
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
done();
|
done();
|
||||||
@ -873,7 +876,7 @@ suite('server', function() {
|
|||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body,
|
assert.imageEqualsFile(res.body,
|
||||||
'./test/fixtures/test_table_15_16046_12354_styled_black.png',
|
'./test/fixtures/test_table_15_16046_12354_styled_black.png',
|
||||||
2, this);
|
IMAGE_EQUALS_TOLERANCE_PER_MIL, this);
|
||||||
},
|
},
|
||||||
function checkImage(err, similarity) {
|
function checkImage(err, similarity) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@ -910,7 +913,7 @@ suite('server', function() {
|
|||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body,
|
assert.imageEqualsFile(res.body,
|
||||||
'./test/fixtures/test_table_15_16046_12354_styled_black.png',
|
'./test/fixtures/test_table_15_16046_12354_styled_black.png',
|
||||||
2, this);
|
IMAGE_EQUALS_TOLERANCE_PER_MIL, this);
|
||||||
},
|
},
|
||||||
function checkImage(err, similarity) {
|
function checkImage(err, similarity) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@ -934,7 +937,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', 2,
|
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
done();
|
done();
|
||||||
@ -971,7 +974,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', 2,
|
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
@ -1011,7 +1014,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/blank.png', 0,
|
assert.imageEqualsFile(res.body, './test/fixtures/blank.png', IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
if (err) next(err);
|
if (err) next(err);
|
||||||
else next();
|
else next();
|
||||||
@ -1031,7 +1034,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/blank.png', 0,
|
assert.imageEqualsFile(res.body, './test/fixtures/blank.png', IMAGE_EQUALS_ZERO_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
if (err) next(err);
|
if (err) next(err);
|
||||||
else next();
|
else next();
|
||||||
@ -1068,7 +1071,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', 2,
|
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
// NOTE: we expect them to be EQUAL here
|
// NOTE: we expect them to be EQUAL here
|
||||||
if (err) { next(err); return; }
|
if (err) { next(err); return; }
|
||||||
@ -1105,7 +1108,7 @@ suite('server', function() {
|
|||||||
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
|
||||||
var ct = res.headers['content-type'];
|
var ct = res.headers['content-type'];
|
||||||
assert.equal(ct, 'image/png');
|
assert.equal(ct, 'image/png');
|
||||||
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', 2,
|
assert.imageEqualsFile(res.body, './test/fixtures/test_table_15_16046_12354_styled_black.png', IMAGE_EQUALS_TOLERANCE_PER_MIL,
|
||||||
function(err, similarity) {
|
function(err, similarity) {
|
||||||
// NOTE: we expect them to be different here
|
// NOTE: we expect them to be different here
|
||||||
if (err) next();
|
if (err) next();
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
// Cribbed from the ever prolific Konstantin Kaefer
|
// Cribbed from the ever prolific Konstantin Kaefer
|
||||||
// https://github.com/mapbox/tilelive-mapnik/blob/master/test/support/assert.js
|
// https://github.com/mapbox/tilelive-mapnik/blob/master/test/support/assert.js
|
||||||
|
|
||||||
var fs = require('fs');
|
var exec = require('child_process').exec,
|
||||||
var http = require('http');
|
fs = require('fs'),
|
||||||
var path = require('path');
|
http = require('http'),
|
||||||
var exec = require('child_process').exec;
|
path = require('path'),
|
||||||
|
util = require('util');
|
||||||
|
|
||||||
var assert = module.exports = exports = require('assert');
|
var assert = module.exports = exports = require('assert');
|
||||||
|
|
||||||
@ -66,35 +67,51 @@ assert.utfgridEqualsFile = function(buffer, file_b, tolerance, callback) {
|
|||||||
callback(err);
|
callback(err);
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
/**
|
||||||
// @param tol tolerated color distance as a percent over max channel value
|
* Takes an image data as an input and an image path and compare them using ImageMagick fuzz algorithm, if case the
|
||||||
// by default this is zero. For meaningful values, see
|
* similarity is not within the tolerance limit it will callback with an error.
|
||||||
// http://www.imagemagick.org/script/command-line-options.php#metric
|
*
|
||||||
//
|
* @param buffer The image data to compare from
|
||||||
assert.imageEqualsFile = function(buffer, file_b, tol, callback) {
|
* @param {string} referenceImageRelativeFilePath The relative file to compare against
|
||||||
|
* @param {number} tolerance tolerated mean color distance, as a per mil (‰)
|
||||||
|
* @param {function} callback Will call to home with null in case there is no error, otherwise with the error itself
|
||||||
|
* @see FUZZY in http://www.imagemagick.org/script/command-line-options.php#metric
|
||||||
|
*/
|
||||||
|
assert.imageEqualsFile = function(buffer, referenceImageRelativeFilePath, tolerance, callback) {
|
||||||
if (!callback) callback = function(err) { if (err) throw err; };
|
if (!callback) callback = function(err) { if (err) throw err; };
|
||||||
file_b = path.resolve(file_b);
|
var referenceImageFilePath = path.resolve(referenceImageRelativeFilePath),
|
||||||
var file_a = '/tmp/windshaft-test-image-test.png'; // + (Math.random() * 1e16); // TODO: make predictable
|
testImageFilePath = '/tmp/windshaft-test-image-' + (Math.random() * 1e16); // TODO: make predictable
|
||||||
var err = fs.writeFileSync(file_a, buffer, 'binary');
|
var err = fs.writeFileSync(testImageFilePath, buffer, 'binary');
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
var fuzz = tol + '%';
|
var imageMagickCmd = util.format(
|
||||||
exec('compare -fuzz ' + fuzz + ' -metric AE "' + file_a + '" "' +
|
'compare -metric fuzz "%s" "%s" /dev/null',
|
||||||
file_b + '" /dev/null', function(err, stdout, stderr) {
|
testImageFilePath, referenceImageFilePath
|
||||||
|
);
|
||||||
|
|
||||||
|
exec(imageMagickCmd, function(err, stdout, stderr) {
|
||||||
if (err) {
|
if (err) {
|
||||||
fs.unlinkSync(file_a);
|
fs.unlinkSync(testImageFilePath);
|
||||||
callback(err);
|
callback(err);
|
||||||
} else {
|
} else {
|
||||||
stderr = stderr.trim();
|
stderr = stderr.trim();
|
||||||
var similarity = parseFloat(stderr);
|
var metrics = stderr.match(/([0-9]*) \((.*)\)/);
|
||||||
if ( similarity > 0 ) {
|
if ( ! metrics ) {
|
||||||
var err = new Error('Images not equal(' + similarity + '): ' +
|
callback(new Error("No match for " + stderr));
|
||||||
file_a + ' ' + file_b);
|
return;
|
||||||
err.similarity = similarity;
|
}
|
||||||
callback(err);
|
var similarity = parseFloat(metrics[2]),
|
||||||
|
tolerancePerMil = (tolerance / 1000);
|
||||||
|
if (similarity > tolerancePerMil) {
|
||||||
|
err = new Error(util.format(
|
||||||
|
'Images %s and %s are not equal (got %d similarity, expected %d)',
|
||||||
|
testImageFilePath, referenceImageFilePath, similarity, tolerancePerMil)
|
||||||
|
);
|
||||||
|
err.similarity = similarity;
|
||||||
|
callback(err);
|
||||||
} else {
|
} else {
|
||||||
fs.unlinkSync(file_a);
|
fs.unlinkSync(testImageFilePath);
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user