From 15a66b8989645b702d207d96f6693ea3ddd93bdc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 2 Sep 2015 16:53:41 -0700 Subject: [PATCH] Consolidate test-suite rendering harnesses (#2236) --- .gitmodules | 4 - package.json | 6 +- platform/node/README.md | 2 + platform/node/test/compare.js | 27 --- platform/node/test/expected/gzip/success.png | Bin 42195 -> 0 bytes .../node/test/expected/gzip/unhandled.png | Bin 5636 -> 0 bytes platform/node/test/expected/map/image.png | Bin 42195 -> 0 bytes platform/node/test/js/consecutive.test.js | 82 -------- platform/node/test/js/gzip.test.js | 125 ------------ platform/node/test/js/map.test.js | 84 ++++---- platform/node/test/render.test.js | 175 ++--------------- scripts/compare_images.sh | 6 - scripts/linux/after_script.sh | 15 -- scripts/linux/run.sh | 6 - scripts/main.mk | 4 - scripts/node/after_script.sh | 13 ++ scripts/node/run.sh | 15 -- test/api/repeated_render.cpp | 2 +- test/api/set_style.cpp | 2 +- test/headless/headless.cpp | 184 ------------------ test/headless/server.js | 19 -- .../custom_sprites.cpp | 2 +- test/suite | 1 - test/test.gypi | 3 +- 24 files changed, 81 insertions(+), 696 deletions(-) delete mode 100644 platform/node/test/compare.js delete mode 100644 platform/node/test/expected/gzip/success.png delete mode 100644 platform/node/test/expected/gzip/unhandled.png delete mode 100644 platform/node/test/expected/map/image.png delete mode 100644 platform/node/test/js/consecutive.test.js delete mode 100644 platform/node/test/js/gzip.test.js delete mode 100755 scripts/compare_images.sh delete mode 100755 scripts/linux/after_script.sh delete mode 100644 test/headless/headless.cpp delete mode 100755 test/headless/server.js rename test/{headless => miscellaneous}/custom_sprites.cpp (97%) delete mode 160000 test/suite diff --git a/.gitmodules b/.gitmodules index d84cfecbc..2aa6d52be 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "test/suite"] - path = test/suite - url = https://github.com/mapbox/mapbox-gl-test-suite.git - [submodule ".mason"] path = .mason url = https://github.com/mapbox/mason.git diff --git a/package.json b/package.json index 3795ca8f5..0fd6887ba 100644 --- a/package.json +++ b/package.json @@ -26,16 +26,14 @@ ], "devDependencies": { "aws-sdk": "^2.1.47", - "mkdirp": "^0.5.1", - "pngjs": "^0.4.0", + "mapbox-gl-test-suite": "git+https://github.com/mapbox/mapbox-gl-test-suite.git#6cfd7eb20de77018a7f10770f56df9ce1f8a76ac", "request": "^2.61.0", - "st": "^0.5.5", "tape": "^4.2.0" }, "scripts": { "install": "node-pre-gyp install --fallback-to-build=false || make node", "test": "tape platform/node/test/js/**/*.test.js", - "test-suite": "tape platform/node/test/render.test.js" + "test-suite": "node platform/node/test/render.test.js" }, "gypfile": true, "binary": { diff --git a/platform/node/README.md b/platform/node/README.md index 870151fd2..72a08e853 100644 --- a/platform/node/README.md +++ b/platform/node/README.md @@ -92,6 +92,8 @@ The `kind` is an enum and defined in [`mbgl.Resource`](https://github.com/mapbox It has no significance for anything but serves as a hint to your implemention as to what sort of resource to expect. E.g., your implementation could choose caching strategies based on the expected file type. +THe `request` implementation should pass uncompressed data to `req.respond`. If you are downloading assets from a source that applies gzip transport encoding, the implementation must decompress the results before passing them on. + A sample implementation that reads files from disk would look like the following: ```js diff --git a/platform/node/test/compare.js b/platform/node/test/compare.js deleted file mode 100644 index 3e5221de5..000000000 --- a/platform/node/test/compare.js +++ /dev/null @@ -1,27 +0,0 @@ -var spawn = require('child_process').spawn; - -module.exports = function compare(actual, expected, diff, t, callback) { - var compare = spawn('compare', ['-metric', 'MAE', actual, expected, diff]); - var error = ''; - - compare.stderr.on('data', function(data) { - error += data.toString(); - }); - - compare.on('error', function(err) { - t.error(err); - }); - - compare.on('exit', function(code) { - // The compare program returns 2 on error otherwise 0 if the images are similar or 1 if they are dissimilar. - if (code === 2) { - callback(error.trim(), Infinity); - } else { - var match = error.match(/^\d+(?:\.\d+)?\s+\(([^\)]+)\)\s*$/); - var difference = match ? parseFloat(match[1]) : Infinity; - callback(match ? '' : error, difference); - } - }); - - compare.stdin.end(); -}; diff --git a/platform/node/test/expected/gzip/success.png b/platform/node/test/expected/gzip/success.png deleted file mode 100644 index de41e0fe2bf7eed4a6caba1cd37fab041a9c9fa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42195 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

E1VzHEYCH5^t{_O7 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 diff --git a/platform/node/test/expected/gzip/unhandled.png b/platform/node/test/expected/gzip/unhandled.png deleted file mode 100644 index ddb90d8b8fd296d0f46fff1bf364d55cec915dac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5636 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4Yzkn2Dage(c!@6@aFBup__j$TF zhEy=Vz2+#$puofIcwqnYLkW+!@ojpkTzya1y@7#|iG^bci=Woo4J;f23Jwhi#0?m1 zm_VWe99$9%2QRs*Ie=8LHOK>Hfec4RW`&4dC%~!?FnnMJGZZuu7+Ac;XM&BBV5ozb z%fiajknmDT7_5=`06)llhQ5bDIgmZ5*U7ftx^yWF<@v~+U*0@$irX{wu+^R ziOpd{$wW?&#s|hr<1RP-Cn5Jh0)@Z=+2W;o4V@E@FG|i4?u+h?Bw44FVdQ&MBb@0Qlf}hyVZp diff --git a/platform/node/test/expected/map/image.png b/platform/node/test/expected/map/image.png deleted file mode 100644 index de41e0fe2bf7eed4a6caba1cd37fab041a9c9fa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42195 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

E1VzHEYCH5^t{_O7 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 diff --git a/platform/node/test/js/consecutive.test.js b/platform/node/test/js/consecutive.test.js deleted file mode 100644 index 928ca1d83..000000000 --- a/platform/node/test/js/consecutive.test.js +++ /dev/null @@ -1,82 +0,0 @@ -'use strict'; - -/* jshint node:true */ - -var test = require('tape'); -var mbgl = require('../../../..'); -var fs = require('fs'); -var path = require('path'); - -var suitePath = path.join(__dirname, '../../../../test/suite'); - -function renderTest(style, info, dir, key) { - return function (t) { - var completed = 0; - var remaining = 10; - var start = +new Date; - - var options = {}; - options.request = function(req) { - fs.readFile(path.join(suitePath, decodeURIComponent(req.url)), function(err, data) { - req.respond(err, { data: data }); - t.error(err); - }); - }; - options.cancel = function() {}; - options.ratio = 1.0; - - var map = new mbgl.Map(options); - map.load(style); - - function render() { - map.render(info[key], function(err, image) { - t.error(err); - - t.ok(true, 'render @ ' + ((+new Date) - start) + 'ms'); - if (++completed === remaining) { - map.release(); - t.end(); - } else { - render(); - } - }); - } - - render(); - }; -} - -function rewriteLocalSchema(uri) { - return uri.replace(/^local:\/\//, ''); -} - -test('Consecutive', function(t) { - var dir = 'line-join'; - var k = 'round'; - - var style = require(path.join(suitePath, 'tests', dir, 'style.json')), - info = require(path.join(suitePath, 'tests', dir, 'info.json')); - - for (var k in style.sources) { - var source = style.sources[k]; - - if (source.tiles) { - source.tiles = source.tiles.map(rewriteLocalSchema); - } - - if (source.url) { - source.url = rewriteLocalSchema(source.url); - } - } - - if (style.sprite) style.sprite = rewriteLocalSchema(style.sprite); - if (style.glyphs) style.glyphs = rewriteLocalSchema(style.glyphs); - - style = JSON.stringify(style); - - for (k in info) { - t.test(dir + ' ' + k, renderTest(style, info, dir, k)); - } - - t.end(); -}); diff --git a/platform/node/test/js/gzip.test.js b/platform/node/test/js/gzip.test.js deleted file mode 100644 index 4545a18cf..000000000 --- a/platform/node/test/js/gzip.test.js +++ /dev/null @@ -1,125 +0,0 @@ -'use strict'; - -/* jshint node: true */ - -var test = require('tape').test; -var mbgl = require('../../../..'); -var fs = require('fs'); -var path = require('path'); -var mkdirp = require('mkdirp'); -var http = require('http'); -var request = require('request'); -var st = require('st'); -var style = require('../fixtures/style.json'); -var PNG = require('pngjs').PNG; -var compare = require('../compare.js'); - -var server = http.createServer(st({ path: path.join(__dirname, '..') })); -server.listen(0); - -function filePath(name) { - return ['expected', 'actual', 'diff'].reduce(function(prev, key) { - var dir = path.join(__dirname, '..', key, 'gzip'); - mkdirp.sync(dir); - prev[key] = path.join(dir, name); - return prev; - }, {}); -} - -function setup(options, callback) { - callback(new mbgl.Map(options)); -} - -function getOptions(gzip, t) { - return { - request: function(req) { - var parts = req.url.split('.'); - var filetype = parts[parts.length - 1]; - - request({ - url: 'http://localhost:' + server.address().port + path.join('/', req.url), - encoding: null, - gzip: filetype === 'pbf' ? gzip : true, - headers: { - 'Accept-Encoding': 'gzip' - } - }, function (err, res, body) { - t.error(err); - var response = {}; - response.data = res.body; - req.respond(null, response); - }); - }, - ratio: 1.0 - }; -} - -test('gzip', function(t) { - t.test('success', function(t) { - mbgl.on('message', function(msg) { - if (msg.severity == 'ERROR') t.error(msg); - }); - - setup(getOptions(true, t), function(map) { - map.load(style); - map.render({}, function(err, data) { - mbgl.removeAllListeners('message'); - map.release(); - - t.error(err); - - var filename = filePath('success.png'); - - var png = new PNG({ - width: data.width, - height: data.height - }); - - png.data = data.pixels; - - if (process.env.UPDATE) { - png.pack() - .pipe(fs.createWriteStream(filename.expected)) - .on('finish', t.end); - } else { - png.pack() - .pipe(fs.createWriteStream(filename.actual)) - .on('finish', function() { - compare(filename.actual, filename.expected, filename.diff, t, function(err, diff) { - t.error(err); - t.ok(diff <= 0.01, 'actual matches expected'); - t.end(); - }); - }); - } - }); - }); - }); - - t.test('unhandled', function(t) { - mbgl.once('message', function(msg) { - if (msg.severity == 'ERROR') { - t.ok(msg, 'emits error'); - t.equal(msg.class, 'Style'); - t.equal(msg.severity, 'ERROR'); - t.ok(msg.text.match(/pbf unknown field type exception/), 'error text matches'); - } - }); - - setup(getOptions(false, t), function(map) { - map.load(style); - map.render({}, function(err, data) { - map.release(); - - t.ok(err, 'returns error'); - t.ok(err.message.match(/Failed to parse/), 'error text matches'); - - t.end(); - }); - }); - }); - - t.test('teardown', function(t) { - server.close(t.end); - }); -}); diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js index 09870abaa..c4e341632 100644 --- a/platform/node/test/js/map.test.js +++ b/platform/node/test/js/map.test.js @@ -1,24 +1,10 @@ 'use strict'; -/* jshint node: true */ - var test = require('tape'); var mbgl = require('../../../..'); var fs = require('fs'); var path = require('path'); -var mkdirp = require('mkdirp'); var style = require('../fixtures/style.json'); -var PNG = require('pngjs').PNG; -var compare = require('../compare.js'); - -function filePath(name) { - return ['expected', 'actual', 'diff'].reduce(function(prev, key) { - var dir = path.join(__dirname, '..', key, 'map'); - mkdirp.sync(dir); - prev[key] = path.join(dir, name); - return prev; - }, {}); -} test('Map', function(t) { t.test('must be constructed with new', function(t) { @@ -250,31 +236,53 @@ test('Map', function(t) { map.release(); - var filename = filePath('image.png'); - - var png = new PNG({ - width: data.width, - height: data.height - }); - - png.data = data.pixels; - - if (process.env.UPDATE) { - png.pack() - .pipe(fs.createWriteStream(filename.expected)) - .on('finish', t.end); - } else { - png.pack() - .pipe(fs.createWriteStream(filename.actual)) - .on('finish', function() { - compare(filename.actual, filename.expected, filename.diff, t, function(err, diff) { - t.error(err); - t.ok(diff <= 0.01, 'actual matches expected'); - t.end(); - }); - }); - } + t.ok(data.pixels); + t.equal(data.width, 512); + t.equal(data.height, 512); + t.end(); }); }); + + t.test('can be called several times in serial', function(t) { + var completed = 0; + var remaining = 10; + var start = +new Date; + + var map = new mbgl.Map(options); + map.load(style); + + function render() { + map.render({}, function(err, data) { + t.error(err); + + t.ok(true, 'render @ ' + ((+new Date) - start) + 'ms'); + if (++completed === remaining) { + map.release(); + t.end(); + } else { + render(); + } + }); + } + + render(); + }); + + t.skip('throws if called in parallel', function(t) { + var completed = 0; + var remaining = 10; + var start = +new Date; + + var map = new mbgl.Map(options); + map.load(style); + + t.throws(function() { + map.render({}, function() {}); + map.render({}, function() {}); + }); + + map.release(); + t.end(); + }); }); }); diff --git a/platform/node/test/render.test.js b/platform/node/test/render.test.js index 10a7afcb5..b9f13a28f 100644 --- a/platform/node/test/render.test.js +++ b/platform/node/test/render.test.js @@ -1,175 +1,28 @@ 'use strict'; -/* jshint node:true */ - -var test = require('tape'); var mbgl = require('../../..'); -var fs = require('fs'); -var path = require('path'); -var mkdirp = require('mkdirp'); -var PNG = require('pngjs').PNG; -var compare = require('./compare.js'); -var suitePath = path.join(__dirname, '../../../test/suite'); - -function template(name) { - return fs.readFileSync(path.join(suitePath, 'templates', name + '.html.tmpl')).toString(); -} - -var results = ''; -var resultTemplate = template('result'); - -function format(tmpl, kwargs) { - return tmpl.replace(/\{\{|\}\}|\{([^}]+)\}/g, function(match, key) { - if (match === '{{') return '{'; - if (match === '}}') return '}'; - return kwargs[key]; - }); -} - -function renderTest(style, info, base, key) { - var dir = path.join(suitePath, 'tests', base, key); - mkdirp.sync(dir); - - return function(t) { - var watchdog = setTimeout(function() { - t.fail('timed out after 20 seconds'); - }, 20000); - - t.once('end', function() { - clearTimeout(watchdog); - - if (map) { - map.release(); - map = null; - } - }); - - var options = {}; - options.request = function(req) { - var url = decodeURIComponent(req.url); - fs.readFile(path.join(suitePath, url), function(err, data) { - req.respond(err, { data: data }); - }); - }; - options.ratio = info[key].pixelRatio || 1; - - var map = new mbgl.Map(options); - map.load(style); - - map.render(info[key], function(err, data) { - if (err) { - t.error(err); - return t.end(); - } - - var expected = path.join(dir, 'expected.png'); - var actual = path.join(dir, 'actual.png'); - var diff = path.join(dir, 'diff.png'); - - var png = new PNG({ - width: data.width, - height: data.height - }); - - png.data = data.pixels; - - if (process.env.UPDATE) { - png.pack() - .pipe(fs.createWriteStream(expected)) - .on('finish', t.end); - } else { - png.pack() - .pipe(fs.createWriteStream(actual)) - .on('finish', function() { - compare(actual, expected, diff, t, function(err, diff) { - t.error(err); - - var allowed = 0.001; - - if ('diff' in info[key]) { - if (typeof info[key].diff === 'number') { - allowed = info[key].diff; - } else if ('native' in info[key].diff) { - allowed = info[key].diff.native; - } - } - - results += format(resultTemplate, { - name: base, - key: key, - color: diff <= allowed ? 'green' : 'red', - error: err ? '

' + err + '

' : '', - difference: diff, - zoom: info.zoom || 0, - center: info.center || [0, 0], - bearing: info.bearing || 0, - width: info.width || 512, - height: info.height || 512 - }); - - if (!info[key].ignored || !('native' in info[key].ignored)) { - t.ok(diff <= allowed, 'expected ' + diff + ' to be less than ' + allowed); - } - - t.end(); - }); - }); - } - }); - }; -} - -function rewriteLocalSchema(url) { - var regex = /^local:\/\//; - if (url instanceof Array) { - return url.map(function(str) { - return str.replace(regex, ''); - }); - } else if (typeof url === "string") { - return url.replace(regex, ''); - } -} +var suite = require('mapbox-gl-test-suite'); +var request = require('request'); var tests; -if (process.argv[1] === __filename) { +if (process.argv[1] === __filename && process.argv.length > 2) { tests = process.argv.slice(2); } -test('Render', function(t) { - fs.readdirSync(path.join(suitePath, 'tests')).forEach(function(dir) { - if (dir === 'index.html' || dir[0] === '.') return; - if (tests && tests.length && tests.indexOf(dir) < 0) return; - - var style = require(path.join(suitePath, 'tests', dir, 'style.json')), - info = require(path.join(suitePath, 'tests', dir, 'info.json')); - - for (var k in style.sources) { - var source = style.sources[k]; - - if (source.tiles) { - source.tiles = source.tiles.map(rewriteLocalSchema); - } - - if (source.url) { - source.url = rewriteLocalSchema(source.url); - } - } - - if (style.sprite) style.sprite = rewriteLocalSchema(style.sprite); - if (style.glyphs) style.glyphs = rewriteLocalSchema(style.glyphs); - - style = JSON.stringify(style); - - for (k in info) { - (info[k].native === false ? t.skip : t.test)(dir + ' ' + k, renderTest(style, info, dir, k)); +suite.run('native', {tests: tests}, function (style, options, callback) { + var map = new mbgl.Map({ + ratio: options.pixelRatio, + request: function (req) { + request(req.url, {encoding: null}, function (err, response, body) { + req.respond(err, {data: body}); + }); } }); - t.test('results', function(t) { - var p = path.join(suitePath, 'tests', 'index.html'); - fs.writeFileSync(p, format(template('results'), {results: results})); - console.warn('Results at: ' + p); - t.end(); + map.load(style); + map.render(options, function (err, result) { + map.release(); + callback(err, result && result.pixels); }); }); diff --git a/scripts/compare_images.sh b/scripts/compare_images.sh deleted file mode 100755 index 240772646..000000000 --- a/scripts/compare_images.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -o pipefail - -(cd ./test/suite/ && ./bin/compare_images.py native) diff --git a/scripts/linux/after_script.sh b/scripts/linux/after_script.sh deleted file mode 100755 index c38af0a79..000000000 --- a/scripts/linux/after_script.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -o pipefail - -if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then - # Install and add awscli to PATH for uploading the results - mapbox_time "install_awscli" \ - pip install --user awscli - export PATH="`python -m site --user-base`/bin:${PATH}" - - mapbox_time_start "deploy_results" - (cd ./test/suite/ && ./bin/deploy_results.sh) - mapbox_time_finish -fi diff --git a/scripts/linux/run.sh b/scripts/linux/run.sh index 42d2a16d9..31272ea1c 100755 --- a/scripts/linux/run.sh +++ b/scripts/linux/run.sh @@ -27,11 +27,5 @@ make test -j${JOBS} BUILDTYPE=${BUILDTYPE} # Test ################################################################################ -mapbox_time "checkout_test_suite" \ -git submodule update --init test/suite - mapbox_time "run_tests" \ make test-* BUILDTYPE=${BUILDTYPE} - -mapbox_time "compare_results" \ -./scripts/compare_images.sh diff --git a/scripts/main.mk b/scripts/main.mk index 65f283b21..3639a780a 100644 --- a/scripts/main.mk +++ b/scripts/main.mk @@ -46,10 +46,6 @@ SUBMODULES += src/mbgl/util/geojsonvt/geojsonvt.hpp src/mbgl/util/geojsonvt/geojsonvt.hpp: ./scripts/flock.py .git/Submodule.lock git submodule update --init src/mbgl/util/geojsonvt -SUBMODULES += test/suite/package.json -test/suite/package.json: - ./scripts/flock.py .git/Submodule.lock git submodule update --init test/suite - ifeq ($(HOST),ios) SUBMODULES += platform/ios/vendor/SMCalloutView/SMCalloutView.h platform/ios/vendor/SMCalloutView/SMCalloutView.h: diff --git a/scripts/node/after_script.sh b/scripts/node/after_script.sh index d78e820e9..237f9fe60 100755 --- a/scripts/node/after_script.sh +++ b/scripts/node/after_script.sh @@ -35,3 +35,16 @@ if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then npm test fi fi + +if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then + # Install and add awscli to PATH for uploading the results + pip install --user awscli + export PATH="`python -m site --user-base`/bin:${PATH}" + + REPO_NAME=$(basename $TRAVIS_REPO_SLUG) + gzip --stdout node_modules/mapbox-gl-test-suite/tests/index.html | \ + aws s3 cp --acl public-read --content-encoding gzip --content-type text/html \ + - s3://mapbox/$REPO_NAME/tests/$TRAVIS_JOB_NUMBER/index.html + + echo http://mapbox.s3.amazonaws.com/$REPO_NAME/tests/$TRAVIS_JOB_NUMBER/index.html +fi diff --git a/scripts/node/run.sh b/scripts/node/run.sh index 8566fc3b3..22db3fded 100755 --- a/scripts/node/run.sh +++ b/scripts/node/run.sh @@ -26,24 +26,9 @@ npm install --build-from-source # Travis OS X has no GPU if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then - mapbox_time "checkout_test_suite" \ - git submodule update --init test/suite - mapbox_time "run_tests" \ npm test mapbox_time "run_render_tests" \ npm run test-suite - - if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then - # Install and add awscli to PATH for uploading the results - mapbox_time "install_awscli" \ - pip install --user awscli - export PATH="`python -m site --user-base`/bin:${PATH}" - - pushd test/suite - mapbox_time "deploy_results" \ - ./bin/deploy_results.sh - popd - fi fi diff --git a/test/api/repeated_render.cpp b/test/api/repeated_render.cpp index f8b92b85b..3317b4e3a 100644 --- a/test/api/repeated_render.cpp +++ b/test/api/repeated_render.cpp @@ -25,7 +25,7 @@ TEST(API, RepeatedRender) { Map map(view, fileSource, MapMode::Still); { - map.setStyleJSON(style, "test/suite"); + map.setStyleJSON(style, ""); std::promise> promise; map.renderStill([&promise](std::exception_ptr, std::unique_ptr image) { promise.set_value(std::move(image)); diff --git a/test/api/set_style.cpp b/test/api/set_style.cpp index db31254db..c3e62def2 100644 --- a/test/api/set_style.cpp +++ b/test/api/set_style.cpp @@ -18,7 +18,7 @@ TEST(API, SetStyle) { { Map map(view, fileSource, MapMode::Still); - map.setStyleJSON("invalid", "test/suite"); + map.setStyleJSON("invalid", ""); } auto observer = Log::removeObserver(); diff --git a/test/headless/headless.cpp b/test/headless/headless.cpp deleted file mode 100644 index 80951433e..000000000 --- a/test/headless/headless.cpp +++ /dev/null @@ -1,184 +0,0 @@ -#include "../fixtures/util.hpp" -#include "../fixtures/fixture_log_observer.hpp" - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -void rewriteLocalScheme(rapidjson::Value &value, rapidjson::Document::AllocatorType &allocator) { - ASSERT_TRUE(value.IsString()); - auto string = std::string { value.GetString(),value.GetStringLength() }; - if (string.compare(0, 8, "local://") == 0) { - string.replace(0, 8, "http://127.0.0.1:2900/"); - value.SetString(string.data(), string.size(), allocator); - } -} - - -class HeadlessTest : public ::testing::TestWithParam { -public: - static void SetUpTestCase() { - const auto server = mbgl::platform::applicationRoot() + "/TEST_DATA/headless/server.js"; - pid = mbgl::test::startServer(server.c_str()); - display = std::make_shared(); - } - - static void TearDownTestCase() { - display.reset(); - mbgl::test::stopServer(pid); - } - -protected: - static pid_t pid; - static std::shared_ptr display; -}; - -pid_t HeadlessTest::pid = 0; -std::shared_ptr HeadlessTest::display; - -TEST_P(HeadlessTest, render) { - using namespace mbgl; - - const std::string& base = GetParam(); - - std::string style = util::read_file("test/suite/tests/" + base + "/style.json"); - std::string info = util::read_file("test/suite/tests/" + base + "/info.json"); - - // Parse style. - rapidjson::Document styleDoc; - styleDoc.Parse<0>((const char *const)style.c_str()); - ASSERT_FALSE(styleDoc.HasParseError()); - ASSERT_TRUE(styleDoc.IsObject()); - - // Rewrite "local://" to "http://127.0.0.1:2900/". - if (styleDoc.HasMember("sprite")) { - rewriteLocalScheme(styleDoc["sprite"], styleDoc.GetAllocator()); - } - - if (styleDoc.HasMember("glyphs")) { - rewriteLocalScheme(styleDoc["glyphs"], styleDoc.GetAllocator()); - } - - if (styleDoc.HasMember("sources")) { - auto &sources = styleDoc["sources"]; - ASSERT_TRUE(sources.IsObject()); - for (auto source = sources.MemberBegin(), end = sources.MemberEnd(); source != end; source++) { - if (source->value.HasMember("tiles")) { - auto &tiles = source->value["tiles"]; - ASSERT_TRUE(tiles.IsArray()); - for (rapidjson::SizeType i = 0; i < tiles.Size(); i++) { - rewriteLocalScheme(tiles[i], styleDoc.GetAllocator()); - } - } - - if (source->value.HasMember("url") && source->value["url"].IsString()) { - rewriteLocalScheme(source->value["url"], styleDoc.GetAllocator()); - } - } - } - - // Convert the JSON object back into a stringified version. - rapidjson::StringBuffer buffer; - rapidjson::Writer writer(buffer); - styleDoc.Accept(writer); - style = buffer.GetString(); - - // Parse settings. - rapidjson::Document infoDoc; - infoDoc.Parse<0>((const char *const)info.c_str()); - ASSERT_FALSE(infoDoc.HasParseError()); - ASSERT_TRUE(infoDoc.IsObject()); - - for (auto it = infoDoc.MemberBegin(), end = infoDoc.MemberEnd(); it != end; it++) { - const std::string name { - it->name.GetString(), it->name.GetStringLength() - }; - - Log::Info(Event::General, "%s %s", base.c_str(), name.c_str()); - - const rapidjson::Value& value = it->value; - ASSERT_TRUE(value.IsObject()); - - if (value.HasMember("native") && !value["native"].GetBool()) - continue; - - if (value.HasMember("center")) ASSERT_TRUE(value["center"].IsArray()); - - const std::string actual_image = "test/suite/tests/" + base + "/" + name + "/actual.png"; - - const double zoom = value.HasMember("zoom") ? value["zoom"].GetDouble() : 0; - const double bearing = value.HasMember("bearing") ? value["bearing"].GetDouble() : 0; - const double latitude = value.HasMember("center") ? value["center"][rapidjson::SizeType(0)].GetDouble() : 0; - const double longitude = value.HasMember("center") ? value["center"][rapidjson::SizeType(1)].GetDouble() : 0; - const unsigned int width = value.HasMember("width") ? value["width"].GetUint() : 512; - const unsigned int height = value.HasMember("height") ? value["height"].GetUint() : 512; - const unsigned int pixelRatio = value.HasMember("pixelRatio") ? value["pixelRatio"].GetUint() : 1; - - std::vector classes; - if (value.HasMember("classes")) { - const rapidjson::Value& js_classes = value["classes"]; - ASSERT_TRUE(js_classes.IsArray()); - for (rapidjson::SizeType i = 0; i < js_classes.Size(); i++) { - const rapidjson::Value& js_class = js_classes[i]; - ASSERT_TRUE(js_class.IsString()); - classes.push_back({ js_class.GetString(), js_class.GetStringLength() }); - } - } - - std::promise promise; - - HeadlessView view(display, pixelRatio, width, height); - DefaultFileSource fileSource(nullptr); - Map map(view, fileSource, MapMode::Still); - - map.setClasses(classes); - map.setStyleJSON(style, "test/suite"); - map.setLatLngZoom(mbgl::LatLng(latitude, longitude), zoom); - map.setBearing(bearing); - - map.renderStill([&](std::exception_ptr error, std::unique_ptr image) { - if (error) { - promise.set_exception(error); - return; - } - const std::string png = util::compress_png(image->width, image->height, image->pixels.get()); - util::write_file("test/suite/tests/" + base + "/" + name + "/actual.png", png); - promise.set_value(); - }); - - promise.get_future().get(); - } -} - -INSTANTIATE_TEST_CASE_P(Headless, HeadlessTest, ::testing::ValuesIn([] { - std::vector names; - - const auto tests = mbgl::platform::applicationRoot() + "/TEST_DATA/suite/tests"; - DIR *dir = opendir(tests.c_str()); - if (dir != nullptr) { - for (dirent *dp = nullptr; (dp = readdir(dir)) != nullptr;) { - const std::string name = dp->d_name; - if (name != "index.html" && !(name.size() >= 1 && name[0] == '.')) { - names.push_back(name); - } - } - closedir(dir); - } - - EXPECT_GT(names.size(), 0ul); - return names; -}())); diff --git a/test/headless/server.js b/test/headless/server.js deleted file mode 100755 index ff349b050..000000000 --- a/test/headless/server.js +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env node -/* jshint node: true */ -'use strict'; - -var express = require('express'); -var app = express(); - -app.use(express.static('test/suite')); - -var server = app.listen(2900, function () { - var host = server.address().address; - var port = server.address().port; - console.log('Test server listening at http://%s:%s', host, port); - - if (process.argv[2]) { - // Allow the test to continue running. - process.stdin.write("Go!\n"); - } -}); diff --git a/test/headless/custom_sprites.cpp b/test/miscellaneous/custom_sprites.cpp similarity index 97% rename from test/headless/custom_sprites.cpp rename to test/miscellaneous/custom_sprites.cpp index e2c479a5c..a72119ea6 100644 --- a/test/headless/custom_sprites.cpp +++ b/test/miscellaneous/custom_sprites.cpp @@ -30,7 +30,7 @@ TEST(Headless, CustomSpriteImages) { map.setLatLngZoom(LatLng{ 52.499167, 13.418056 }, 15); - map.setStyleJSON(style, "test/suite"); + map.setStyleJSON(style, ""); map.setSprite("cafe", std::make_shared(12, 12, 1, std::string(12 * 12 * 4, '\xFF'))); std::promise> promise; diff --git a/test/suite b/test/suite deleted file mode 160000 index 023eb9512..000000000 --- a/test/suite +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 023eb9512a2f73389f00e38fd9da272833992b32 diff --git a/test/test.gypi b/test/test.gypi index 4e669aee1..a35b00133 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -50,13 +50,12 @@ 'api/repeated_render.cpp', 'api/set_style.cpp', - 'headless/custom_sprites.cpp', - 'headless/headless.cpp', 'miscellaneous/clip_ids.cpp', 'miscellaneous/binpack.cpp', 'miscellaneous/bilinear.cpp', 'miscellaneous/comparisons.cpp', + 'miscellaneous/custom_sprites.cpp', 'miscellaneous/enums.cpp', 'miscellaneous/functions.cpp', 'miscellaneous/geo.cpp',