diff --git a/test/integration/lib/render.js b/test/integration/lib/render.js index 2b16198b232..cad6e6c092e 100644 --- a/test/integration/lib/render.js +++ b/test/integration/lib/render.js @@ -5,24 +5,43 @@ const path = require('path'); const PNG = require('pngjs').PNG; const harness = require('./harness'); const pixelmatch = require('pixelmatch'); +const glob = require('glob'); -function compare(path1, path2, diffPath, callback) { +function compare(actualPath, expectedPaths, diffPath, callback) { + + const actualImg = fs.createReadStream(actualPath).pipe(new PNG()).on('parsed', doneReading); + + const expectedImgs = []; + for (const path of expectedPaths) { + expectedImgs.push(fs.createReadStream(path).pipe(new PNG()).on('parsed', doneReading)); + } - const img1 = fs.createReadStream(path1).pipe(new PNG()).on('parsed', doneReading); - const img2 = fs.createReadStream(path2).pipe(new PNG()).on('parsed', doneReading); let read = 0; function doneReading() { - if (++read < 2) return; + if (++read < expectedPaths.length + 1) return; - const diff = new PNG({width: img1.width, height: img1.height}); + // if we have multiple expected images, we'll compare against each one and pick the one with + // the least amount of difference; this is useful for covering features that render differently + // depending on platform, i.e. heatmaps use half-float textures for improved rendering where supported - const numPixels = pixelmatch(img1.data, img2.data, diff.data, img1.width, img1.height, { - threshold: 0.13 - }); + let minNumPixels = Infinity; + let minDiff, minIndex; + + for (let i = 0; i < expectedImgs.length; i++) { + const diff = new PNG({width: actualImg.width, height: actualImg.height}); + const numPixels = pixelmatch(actualImg.data, expectedImgs[i].data, + diff.data, actualImg.width, actualImg.height, {threshold: 0.13}); - diff.pack().pipe(fs.createWriteStream(diffPath)).on('finish', () => { - callback(null, numPixels / (diff.width * diff.height)); + if (numPixels < minNumPixels) { + minNumPixels = numPixels; + minDiff = diff; + minIndex = i; + } + } + + minDiff.pack().pipe(fs.createWriteStream(diffPath)).on('finish', () => { + callback(null, minNumPixels / (minDiff.width * minDiff.height), expectedPaths[minIndex]); }); } } @@ -125,6 +144,13 @@ exports.run = function (implementation, ignores, render) { png.data = data; + // there may be multiple expected images, covering different platforms + const expectedPaths = glob.sync(path.join(dir, 'expected*.png')); + + if (expectedPaths.length === 0) { + throw new Error('No expected*.png files found; did you mean to run tests with UPDATE=true?'); + } + if (process.env.UPDATE) { png.pack() .pipe(fs.createWriteStream(expected)) @@ -133,18 +159,7 @@ exports.run = function (implementation, ignores, render) { png.pack() .pipe(fs.createWriteStream(actual)) .on('finish', () => { - - try { - stats = fs.statSync(expected, fs.R_OK | fs.W_OK); - if (!stats.isFile()) throw new Error(); - } catch (e) { // no expected.png, create it - png.pack() - .pipe(fs.createWriteStream(expected)) - .on('finish', done); - return; - } - - compare(actual, expected, diff, (err, difference) => { + compare(actual, expectedPaths, diff, (err, difference, expected) => { if (err) return done(err); params.difference = difference; diff --git a/test/integration/package.json b/test/integration/package.json index f516047d30f..cb77b6c0f98 100644 --- a/test/integration/package.json +++ b/test/integration/package.json @@ -14,6 +14,7 @@ "pixelmatch": "^4.0.2", "pngjs": "^3.0.0", "shuffle-seed": "^1.1.6", - "st": "^1.1.0" + "st": "^1.1.0", + "glob": "^7.0.3" } } diff --git a/test/integration/render-tests/heatmap-color/default/expected-half-float.png b/test/integration/render-tests/heatmap-color/default/expected-half-float.png new file mode 100644 index 00000000000..0c589d20940 Binary files /dev/null and b/test/integration/render-tests/heatmap-color/default/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-color/default/style.json b/test/integration/render-tests/heatmap-color/default/style.json index c2245712924..f41200873b9 100644 --- a/test/integration/render-tests/heatmap-color/default/style.json +++ b/test/integration/render-tests/heatmap-color/default/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 64, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-color/expression/expected-half-float.png b/test/integration/render-tests/heatmap-color/expression/expected-half-float.png new file mode 100644 index 00000000000..0c589d20940 Binary files /dev/null and b/test/integration/render-tests/heatmap-color/expression/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-color/expression/style.json b/test/integration/render-tests/heatmap-color/expression/style.json index a95bde7d7a5..9beaa0dff6e 100644 --- a/test/integration/render-tests/heatmap-color/expression/style.json +++ b/test/integration/render-tests/heatmap-color/expression/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 64, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-intensity/default/expected-half-float.png b/test/integration/render-tests/heatmap-intensity/default/expected-half-float.png new file mode 100644 index 00000000000..0adb438d402 Binary files /dev/null and b/test/integration/render-tests/heatmap-intensity/default/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-intensity/default/style.json b/test/integration/render-tests/heatmap-intensity/default/style.json index e9f0c94a348..c7a936dad49 100644 --- a/test/integration/render-tests/heatmap-intensity/default/style.json +++ b/test/integration/render-tests/heatmap-intensity/default/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-intensity/function/expected-half-float.png b/test/integration/render-tests/heatmap-intensity/function/expected-half-float.png new file mode 100644 index 00000000000..9c452b45ddb Binary files /dev/null and b/test/integration/render-tests/heatmap-intensity/function/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-intensity/function/style.json b/test/integration/render-tests/heatmap-intensity/function/style.json index 7482b3f0d69..2492d147287 100644 --- a/test/integration/render-tests/heatmap-intensity/function/style.json +++ b/test/integration/render-tests/heatmap-intensity/function/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-intensity/literal/expected-half-float.png b/test/integration/render-tests/heatmap-intensity/literal/expected-half-float.png new file mode 100644 index 00000000000..985348745f5 Binary files /dev/null and b/test/integration/render-tests/heatmap-intensity/literal/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-intensity/literal/style.json b/test/integration/render-tests/heatmap-intensity/literal/style.json index 73a3087cee2..f1be28bf29b 100644 --- a/test/integration/render-tests/heatmap-intensity/literal/style.json +++ b/test/integration/render-tests/heatmap-intensity/literal/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-opacity/default/expected-half-float.png b/test/integration/render-tests/heatmap-opacity/default/expected-half-float.png new file mode 100644 index 00000000000..5685eb92698 Binary files /dev/null and b/test/integration/render-tests/heatmap-opacity/default/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-opacity/default/style.json b/test/integration/render-tests/heatmap-opacity/default/style.json index 949c68239fb..4b4c3fb0711 100644 --- a/test/integration/render-tests/heatmap-opacity/default/style.json +++ b/test/integration/render-tests/heatmap-opacity/default/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 32, - "width": 128 + "width": 128, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-opacity/function/expected-half-float.png b/test/integration/render-tests/heatmap-opacity/function/expected-half-float.png new file mode 100644 index 00000000000..2ebb331af17 Binary files /dev/null and b/test/integration/render-tests/heatmap-opacity/function/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-opacity/function/style.json b/test/integration/render-tests/heatmap-opacity/function/style.json index 9af60ce75fc..291fbc019f5 100644 --- a/test/integration/render-tests/heatmap-opacity/function/style.json +++ b/test/integration/render-tests/heatmap-opacity/function/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 32, - "width": 128 + "width": 128, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-opacity/literal/expected-half-float.png b/test/integration/render-tests/heatmap-opacity/literal/expected-half-float.png new file mode 100644 index 00000000000..737bb7f1dbb Binary files /dev/null and b/test/integration/render-tests/heatmap-opacity/literal/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-opacity/literal/style.json b/test/integration/render-tests/heatmap-opacity/literal/style.json index b1307e14cb2..51c87df9122 100644 --- a/test/integration/render-tests/heatmap-opacity/literal/style.json +++ b/test/integration/render-tests/heatmap-opacity/literal/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 32, - "width": 128 + "width": 128, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-radius/antimeridian/expected-half-float.png b/test/integration/render-tests/heatmap-radius/antimeridian/expected-half-float.png new file mode 100644 index 00000000000..3f5b61ef57c Binary files /dev/null and b/test/integration/render-tests/heatmap-radius/antimeridian/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-radius/antimeridian/style.json b/test/integration/render-tests/heatmap-radius/antimeridian/style.json index 96895e082fc..9cf4e90e269 100644 --- a/test/integration/render-tests/heatmap-radius/antimeridian/style.json +++ b/test/integration/render-tests/heatmap-radius/antimeridian/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "width": 514, - "height": 64 + "height": 64, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-radius/data-expression/expected-half-float.png b/test/integration/render-tests/heatmap-radius/data-expression/expected-half-float.png new file mode 100644 index 00000000000..f0ce9b71b33 Binary files /dev/null and b/test/integration/render-tests/heatmap-radius/data-expression/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-radius/data-expression/style.json b/test/integration/render-tests/heatmap-radius/data-expression/style.json index bc414ef1a21..89e94f1aa71 100644 --- a/test/integration/render-tests/heatmap-radius/data-expression/style.json +++ b/test/integration/render-tests/heatmap-radius/data-expression/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 64, - "width": 64 + "width": 64, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "sources": { diff --git a/test/integration/render-tests/heatmap-radius/default/expected-half-float.png b/test/integration/render-tests/heatmap-radius/default/expected-half-float.png new file mode 100644 index 00000000000..0adb438d402 Binary files /dev/null and b/test/integration/render-tests/heatmap-radius/default/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-radius/default/style.json b/test/integration/render-tests/heatmap-radius/default/style.json index e9f0c94a348..c7a936dad49 100644 --- a/test/integration/render-tests/heatmap-radius/default/style.json +++ b/test/integration/render-tests/heatmap-radius/default/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-radius/function/expected-half-float.png b/test/integration/render-tests/heatmap-radius/function/expected-half-float.png new file mode 100644 index 00000000000..0a5daa456bc Binary files /dev/null and b/test/integration/render-tests/heatmap-radius/function/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-radius/function/style.json b/test/integration/render-tests/heatmap-radius/function/style.json index 0b12e47f675..5ad88e9c009 100644 --- a/test/integration/render-tests/heatmap-radius/function/style.json +++ b/test/integration/render-tests/heatmap-radius/function/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-radius/literal/expected-half-float.png b/test/integration/render-tests/heatmap-radius/literal/expected-half-float.png new file mode 100644 index 00000000000..bbd63d3d67a Binary files /dev/null and b/test/integration/render-tests/heatmap-radius/literal/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-radius/literal/style.json b/test/integration/render-tests/heatmap-radius/literal/style.json index a794f8014a3..7e092f0d72d 100644 --- a/test/integration/render-tests/heatmap-radius/literal/style.json +++ b/test/integration/render-tests/heatmap-radius/literal/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-radius/pitch30/expected-half-float.png b/test/integration/render-tests/heatmap-radius/pitch30/expected-half-float.png new file mode 100644 index 00000000000..509615854aa Binary files /dev/null and b/test/integration/render-tests/heatmap-radius/pitch30/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-radius/pitch30/style.json b/test/integration/render-tests/heatmap-radius/pitch30/style.json index bf5e3703a95..ae024a3ac1e 100644 --- a/test/integration/render-tests/heatmap-radius/pitch30/style.json +++ b/test/integration/render-tests/heatmap-radius/pitch30/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-weight/default/expected-half-float.png b/test/integration/render-tests/heatmap-weight/default/expected-half-float.png new file mode 100644 index 00000000000..0adb438d402 Binary files /dev/null and b/test/integration/render-tests/heatmap-weight/default/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-weight/default/style.json b/test/integration/render-tests/heatmap-weight/default/style.json index e9f0c94a348..c7a936dad49 100644 --- a/test/integration/render-tests/heatmap-weight/default/style.json +++ b/test/integration/render-tests/heatmap-weight/default/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-weight/identity-property-function/expected-half-float.png b/test/integration/render-tests/heatmap-weight/identity-property-function/expected-half-float.png new file mode 100644 index 00000000000..d4eecc1333e Binary files /dev/null and b/test/integration/render-tests/heatmap-weight/identity-property-function/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-weight/identity-property-function/style.json b/test/integration/render-tests/heatmap-weight/identity-property-function/style.json index db8f3440026..52dd5348db5 100644 --- a/test/integration/render-tests/heatmap-weight/identity-property-function/style.json +++ b/test/integration/render-tests/heatmap-weight/identity-property-function/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [ diff --git a/test/integration/render-tests/heatmap-weight/literal/expected-half-float.png b/test/integration/render-tests/heatmap-weight/literal/expected-half-float.png new file mode 100644 index 00000000000..985348745f5 Binary files /dev/null and b/test/integration/render-tests/heatmap-weight/literal/expected-half-float.png differ diff --git a/test/integration/render-tests/heatmap-weight/literal/style.json b/test/integration/render-tests/heatmap-weight/literal/style.json index dc135b59b3b..956e52a58ba 100644 --- a/test/integration/render-tests/heatmap-weight/literal/style.json +++ b/test/integration/render-tests/heatmap-weight/literal/style.json @@ -3,7 +3,8 @@ "metadata": { "test": { "height": 128, - "width": 256 + "width": 256, + "description": "Contains two expected images (for ubyte-based rendering and half-float-based); one of them should pass depending on platform." } }, "center": [