diff --git a/tools/index.js b/tools/index.js index d112ef85..43a4bac1 100644 --- a/tools/index.js +++ b/tools/index.js @@ -1,4 +1,5 @@ module.exports = { gzipTileset : require('./lib/gzipTileset'), + makeCompositeTile : require('./lib/makeCompositeTile'), pipeline : require('./lib/runPipeline') }; diff --git a/tools/lib/getDefaultWriteCallback.js b/tools/lib/getDefaultWriteCallback.js index c5289e09..c07b32d0 100644 --- a/tools/lib/getDefaultWriteCallback.js +++ b/tools/lib/getDefaultWriteCallback.js @@ -1,18 +1,13 @@ 'use strict'; -var fsExtra = require('fs-extra'); -var path = require('path'); -var Promise = require('bluebird'); - -var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile); +var writeTile = require('./writeTile'); module.exports = getDefaultWriteCallback; /** * @private */ -function getDefaultWriteCallback(outputDirectory) { - return function(file, data) { - var outputFile = path.join(outputDirectory, file); - return fsExtraOutputFile(outputFile, data); +function getDefaultWriteCallback() { + return function(file, data, options) { + return writeTile(file, data, options); }; } diff --git a/tools/lib/getFilesInDirectory.js b/tools/lib/getFilesInDirectory.js new file mode 100644 index 00000000..30a61a73 --- /dev/null +++ b/tools/lib/getFilesInDirectory.js @@ -0,0 +1,39 @@ +'use strict'; +var Cesium = require('cesium'); +var Promise = require('bluebird'); +var fsExtra = require('fs-extra'); +var path = require('path'); + +var defaultValue = Cesium.defaultValue; + +var fsExtraReaddir = Promise.promisify(fsExtra.readdir); +var fsExtraStat = Promise.promisify(fsExtra.stat); + +module.exports = getFilesInDirectory; + +function getFilesInDirectory(directory, options) { + var files = []; + options = defaultValue(options, defaultValue); + var recursive = defaultValue(options.recursive, false); + var filter = defaultValue(options.filter, function() { + return true; + }); + return findFiles(directory, files, recursive, filter); +} + +function findFiles(directory, files, recursive, filter) { + return fsExtraReaddir(directory).map(function(fileName) { + var fullPath = path.join(directory, fileName); + return fsExtraStat(fullPath) + .then(function(stats) { + if (stats.isFile() && filter(fullPath)) { + files.push(fullPath); + } else if (recursive && stats.isDirectory()) { + return findFiles(fullPath, files, recursive, filter); + } + }); + }) + .then(function() { + return files; + }); +} \ No newline at end of file diff --git a/tools/lib/gzipTileset.js b/tools/lib/gzipTileset.js index 4bde853c..d543f770 100644 --- a/tools/lib/gzipTileset.js +++ b/tools/lib/gzipTileset.js @@ -1,18 +1,19 @@ 'use strict'; var Cesium = require('cesium'); -var fsExtra = require('fs-extra'); -var path = require('path'); var Promise = require('bluebird'); +var path = require('path'); var zlib = require('zlib'); var getDefaultWriteCallback = require('./getDefaultWriteCallback'); -var isGzipped = require('./isGzipped'); - -var fsExtraReadFile = Promise.promisify(fsExtra.readFile); +var getFilesInDirectory = require('./getFilesInDirectory'); +var isTileFile = require('./isTileFile'); +var readTile = require('./readTile'); var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; var DeveloperError = Cesium.DeveloperError; +var zlibGzip = Promise.promisify(zlib.gzip); + module.exports = gzipTileset; /** @@ -40,100 +41,26 @@ function gzipTileset(options) { outputDirectory = path.normalize(defaultValue(outputDirectory, path.join(path.dirname(inputDirectory), path.basename(inputDirectory) + '-' + (gzip ? 'gzipped' : 'ungzipped')))); - var writeCallback = defaultValue(options.writeCallback, getDefaultWriteCallback(outputDirectory)); + var writeCallback = defaultValue(options.writeCallback, getDefaultWriteCallback()); var logCallback = options.logCallback; if (defined(logCallback)) { logCallback((gzip ? 'Compressing' : 'Uncompressing') + ' files...'); } - var operation = gzip ? zlib.gzipSync : zlib.gunzipSync; - - return new Promise(function(resolve, reject) { - getNumberOfFilesInDirectory(inputDirectory) - .then(function(numberOfFiles) { - var writeFile = getWriteFile(writeCallback, numberOfFiles, resolve, reject); - fsExtra.walk(inputDirectory) - .on('data', function (item) { - if (!item.stats.isDirectory()) { - var inputFile = item.path; - var file = path.relative(inputDirectory, item.path); - - if (gzip && tilesOnly && !isTile(inputFile)) { - copyFile(inputFile, file, writeFile); - } else { - isGzipped(inputFile) - .then(function(fileIsGzipped) { - if (fileIsGzipped === gzip) { - // File is already in the correct state - copyFile(inputFile, file, writeFile); - } else { - fsExtraReadFile(inputFile) - .then(function(data) { - data = operation(data); - writeFile(file, data); - }) - .catch(reject); - } - }) - .catch(reject); - } - } - }) - .on('error', reject); - }) - .catch(reject); - }); -} - -function isTile(file) { - var extension = path.extname(file); - return extension === '.b3dm' || - extension === '.i3dm' || - extension === '.pnts' || - extension === '.cmpt' || - extension === '.vctr'; -} - -function getNumberOfFilesInDirectory(directory) { - return new Promise(function(resolve, reject) { - var numberOfFiles = 0; - fsExtra.walk(directory) - .on('data', function (item) { - if (!item.stats.isDirectory()) { - ++numberOfFiles; + return getFilesInDirectory(inputDirectory, { + recursive: true + }).map(function (filename) { + var writeFile = path.join(outputDirectory, path.relative(inputDirectory, filename)); + return readTile(filename) + .then(function(data) { + if (gzip && (!tilesOnly || isTileFile(writeFile))) { + return zlibGzip(data); } + return Promise.resolve(data); }) - .on('end', function () { - resolve(numberOfFiles); - }) - .on('error', reject); + .then(function(data) { + return writeCallback(writeFile, data); + }); }); } - -function getWriteFile(writeCallback, numberOfFiles, resolve, reject) { - var numberComplete = 0; - function complete() { - ++numberComplete; - if (numberComplete === numberOfFiles) { - resolve(); - } - } - return function(file, data) { - var promise = writeCallback(file, data); - if (defined(promise)) { - promise - .then(complete) - .catch(reject); - } else { - complete(); - } - }; -} - -function copyFile(inputFile, file, writeFile) { - return fsExtraReadFile(inputFile) - .then(function(data) { - return writeFile(file, data); - }); -} diff --git a/tools/lib/isGzipped.js b/tools/lib/isGzipped.js index 9313a6f3..ac094843 100644 --- a/tools/lib/isGzipped.js +++ b/tools/lib/isGzipped.js @@ -1,17 +1,20 @@ 'use strict'; -var fsExtra = require('fs-extra'); -var Promise = require('bluebird'); +var Cesium = require('cesium'); -var fsExtraReadFile = Promise.promisify(fsExtra.readFile); +var DeveloperError = Cesium.DeveloperError; +var defined = Cesium.defined; module.exports = isGzipped; /** - * @private + * Test if the provided data is gzipped. + * + * @param {Buffer} data A buffer containing the data to test. + * @returns {Boolean} True if the data is gzipped, False if not. */ -function isGzipped(file) { - return fsExtraReadFile(file) - .then(function (data) { - return (data[0] === 0x1f) && (data[1] === 0x8b); - }); -} +function isGzipped(data) { + if (!defined(data)) { + throw new DeveloperError('data must be defined.'); + } + return data[0] === 0x1f && data[1] === 0x8b; +} \ No newline at end of file diff --git a/tools/lib/isGzippedFile.js b/tools/lib/isGzippedFile.js new file mode 100644 index 00000000..f75cc8ff --- /dev/null +++ b/tools/lib/isGzippedFile.js @@ -0,0 +1,18 @@ +'use strict'; +var Promise = require('bluebird'); +var fsExtra = require('fs-extra'); +var isGzipped = require('./isGzipped'); + +var fsExtraReadFile = Promise.promisify(fsExtra.readFile); + +module.exports = isGzippedFile; + +/** + * @private + */ +function isGzippedFile(file) { + return fsExtraReadFile(file) + .then(function (data) { + return isGzipped(data); + }); +} diff --git a/tools/lib/isTileFile.js b/tools/lib/isTileFile.js new file mode 100644 index 00000000..0d56b3ff --- /dev/null +++ b/tools/lib/isTileFile.js @@ -0,0 +1,13 @@ +'use strict'; +var path = require('path'); + +module.exports = isTileFile; + +function isTileFile(file) { + var extension = path.extname(file); + return extension === '.b3dm' || + extension === '.i3dm' || + extension === '.pnts' || + extension === '.cmpt' || + extension === '.vctr'; +} \ No newline at end of file diff --git a/tools/lib/makeCompositeTile.js b/tools/lib/makeCompositeTile.js new file mode 100644 index 00000000..19ea7f88 --- /dev/null +++ b/tools/lib/makeCompositeTile.js @@ -0,0 +1,31 @@ +'use strict'; +module.exports = makeCompositeTile; + +/** + * Combines an array of tile buffers into a single composite tile. + * + * @param {Buffer[]} tileBuffers An array of buffers holding tile data. + * @returns {Buffer} A single buffer holding the composite tile. + */ +function makeCompositeTile(tileBuffers) { + var header = new Buffer(16); + var buffers = []; + buffers.push(header); + var byteLength = header.length; + for (var i = 0; i < tileBuffers.length; i++) { + var tile = tileBuffers[i]; + // Byte align all tiles to 4 bytes + var tilePadding = tile.length % 4; + if (tilePadding !== 0) { + tile = Buffer.concat([tile, new Buffer(4 - tilePadding)]); + } + tile.writeUInt32LE(tile.length, 8); // byteLength + byteLength += tile.length; + buffers.push(tile); + } + header.write('cmpt', 0); // magic + header.writeUInt32LE(1, 4); // version + header.writeUInt32LE(byteLength, 8); // byteLength + header.writeUInt32LE(tileBuffers.length, 12); // tilesLength + return Buffer.concat(buffers); +} \ No newline at end of file diff --git a/tools/lib/readTile.js b/tools/lib/readTile.js new file mode 100644 index 00000000..3cc4ae82 --- /dev/null +++ b/tools/lib/readTile.js @@ -0,0 +1,33 @@ +'use strict'; +var Cesium = require('cesium'); +var Promise = require('bluebird'); +var fsExtra = require('fs-extra'); +var zlib = require('zlib'); +var isGzipped = require('./isGzipped'); + +var DeveloperError = Cesium.DeveloperError; +var defined = Cesium.defined; + +var fsExtraReadFile = Promise.promisify(fsExtra.readFile); +var zlibGunzip = Promise.promisify(zlib.gunzip); + +module.exports = readTile; + +/** + * Reads tile data from a file. + * + * @param {String} filePath The file path to read from. + * @returns {Promise} A promise that resolves with the data when the read operation completes. + */ +function readTile(filePath) { + if (!defined(filePath)) { + throw new DeveloperError('filePath must be defined'); + } + return fsExtraReadFile(filePath) + .then(function(buffer) { + if (isGzipped(buffer)) { + return zlibGunzip(buffer); + } + return buffer; + }); +} \ No newline at end of file diff --git a/tools/lib/runPipeline.js b/tools/lib/runPipeline.js index cc771f0d..4a21c67e 100644 --- a/tools/lib/runPipeline.js +++ b/tools/lib/runPipeline.js @@ -1,8 +1,8 @@ 'use strict'; var Cesium = require('cesium'); +var Promise = require('bluebird'); var fsExtra = require('fs-extra'); var path = require('path'); -var Promise = require('bluebird'); var getWorkingDirectory = require('./getWorkingDirectory'); var gzipTileset = require('./gzipTileset'); @@ -90,22 +90,22 @@ function runPipeline(pipeline, options) { } stageObjects.push({ - options : stageOptions, - stageFunction : stageFunction, - name : stageName + options: stageOptions, + stageFunction: stageFunction, + name: stageName }); } // Run the stages in sequence - return Promise.each(stageObjects, function(stage) { + return Promise.each(stageObjects, function (stage) { return fsExtraEmptyDir(stage.options.outputDirectory) - .then(function() { + .then(function () { if (defined(logCallback)) { logCallback('Running ' + stage.name); } return stage.stageFunction(stage.options); }); - }).finally(function() { + }).finally(function () { return Promise.all([ fsExtraRemove(workingDirectory1), fsExtraRemove(workingDirectory2) diff --git a/tools/lib/writeTile.js b/tools/lib/writeTile.js new file mode 100644 index 00000000..d6869666 --- /dev/null +++ b/tools/lib/writeTile.js @@ -0,0 +1,43 @@ +'use strict'; +var Cesium = require('cesium'); +var Promise = require('bluebird'); +var fsExtra = require('fs-extra'); +var zlib = require('zlib'); + +var DeveloperError = Cesium.DeveloperError; +var defaultValue = Cesium.defaultValue; +var defined = Cesium.defined; + +var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile); +var zlibGzip = Promise.promisify(zlib.gzip); + +module.exports = writeTile; + +/** + * Writes the tile data to a file. + * + * @param {String} filePath The file path where the tile should be written. + * @param {Buffer} tileData A buffer containing the tile data to write. + * @param {Object} [options] Defines custom behavior for writing. + * @param {Boolean} [options.gzip=false] Flag to gzip the buffer data before writing. + * @returns {Promise} A promise that resolves when the write operation completes. + */ +function writeTile(filePath, tileData, options) { + if (!defined(filePath)) { + throw new DeveloperError('filePath must be defined.'); + } + if (!defined(tileData)) { + throw new DeveloperError('tileData must be defined.'); + } + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var gzip = defaultValue(options.gzip, false); + var promise; + if (gzip) { + promise = zlibGzip(tileData); + } else { + promise = Promise.resolve(tileData); + } + return promise.then(function(data) { + return fsExtraOutputFile(filePath, data); + }); +} \ No newline at end of file diff --git a/tools/specs/data/justHeader.i3dm b/tools/specs/data/justHeader.i3dm new file mode 100644 index 00000000..43627d9e Binary files /dev/null and b/tools/specs/data/justHeader.i3dm differ diff --git a/tools/specs/data/justHeaderGzipped.i3dm b/tools/specs/data/justHeaderGzipped.i3dm new file mode 100644 index 00000000..a8a4d461 Binary files /dev/null and b/tools/specs/data/justHeaderGzipped.i3dm differ diff --git a/tools/specs/lib/getFilesInDirectorySpec.js b/tools/specs/lib/getFilesInDirectorySpec.js new file mode 100644 index 00000000..947f74aa --- /dev/null +++ b/tools/specs/lib/getFilesInDirectorySpec.js @@ -0,0 +1,73 @@ +'use strict'; +var Promise = require('bluebird'); +var fsExtra = require('fs-extra'); +var path = require('path'); +var isTileFile = require('../../lib/isTileFile'); +var getFilesInDirectory = require('../../lib/getFilesInDirectory'); + +var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile); +var fsExtraRemove = Promise.promisify(fsExtra.remove); + +describe('getFilesInDirectory', function() { + beforeAll(function(done) { + Promise.all([ + fsExtraOutputFile('tmp/0.b3dm', ''), + fsExtraOutputFile('tmp/1.i3dm', ''), + fsExtraOutputFile('tmp/0/2.cmpt', ''), + fsExtraOutputFile('tmp/0/0/3.vctr', ''), + fsExtraOutputFile('tmp/1/4.pnts', ''), + fsExtraOutputFile('tmp/1/5.not-a-tile', '') + ]) + .then(done); + }); + + afterAll(function(done) { + fsExtraRemove('tmp') + .then(done); + }); + + it('gets files in a directory', function(done) { + expect(getFilesInDirectory('tmp') + .then(function(files) { + files.sort(); + expect(files).toEqual([ + path.normalize('tmp/0.b3dm'), + path.normalize('tmp/1.i3dm') + ]); + }), done).toResolve(); + }); + + it('gets files in a directory recursively', function(done) { + expect(getFilesInDirectory('tmp', { + recursive : true + }) + .then(function(files) { + files.sort(); + expect(files).toEqual([ + path.normalize('tmp/0.b3dm'), + path.normalize('tmp/0/0/3.vctr'), + path.normalize('tmp/0/2.cmpt'), + path.normalize('tmp/1.i3dm'), + path.normalize('tmp/1/4.pnts'), + path.normalize('tmp/1/5.not-a-tile') + ]); + }), done).toResolve(); + }); + + it('gets files in a directory with a filter', function(done) { + expect(getFilesInDirectory('tmp', { + recursive : true, + filter : isTileFile + }) + .then(function(files) { + files.sort(); + expect(files).toEqual([ + path.normalize('tmp/0.b3dm'), + path.normalize('tmp/0/0/3.vctr'), + path.normalize('tmp/0/2.cmpt'), + path.normalize('tmp/1.i3dm'), + path.normalize('tmp/1/4.pnts') + ]); + }), done).toResolve(); + }); +}); \ No newline at end of file diff --git a/tools/specs/lib/gzipTilesetSpec.js b/tools/specs/lib/gzipTilesetSpec.js index 5708e12d..59281a31 100644 --- a/tools/specs/lib/gzipTilesetSpec.js +++ b/tools/specs/lib/gzipTilesetSpec.js @@ -1,8 +1,7 @@ 'use strict'; var fsExtra = require('fs-extra'); -var path = require('path'); var Promise = require('bluebird'); -var isGzipped = require('../../lib/isGzipped'); +var isGzippedFile = require('../../lib/isGzippedFile'); var gzipTileset = require('../../lib/gzipTileset'); var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile); @@ -34,9 +33,9 @@ describe('gzipTileset', function() { }; expect(gzipTileset(gzipOptions) .then(function() { - return isGzipped(gzippedJson) - .then(function(isGzipped) { - expect(isGzipped).toBe(true); + return isGzippedFile(gzippedJson) + .then(function(gzipped) { + expect(gzipped).toBe(true); }); }), done).toResolve(); }); @@ -56,9 +55,9 @@ describe('gzipTileset', function() { .then(function() { return gzipTileset(ungzipOptions) .then(function() { - return isGzipped(ungzippedJson) - .then(function(isGzipped) { - expect(isGzipped).toBe(false); + return isGzippedFile(ungzippedJson) + .then(function(gzipped) { + expect(gzipped).toBe(false); }); }); }), done).toResolve(); @@ -71,9 +70,9 @@ describe('gzipTileset', function() { }; expect(gzipTileset(gzipOptions) .then(function() { - return isGzipped(gzippedJson) - .then(function(isGzipped) { - expect(isGzipped).toBe(true); + return isGzippedFile(gzippedJson) + .then(function(gzipped) { + expect(gzipped).toBe(true); }); }), done).toResolve(); }); @@ -133,9 +132,9 @@ describe('gzipTileset', function() { }; expect(gzipTileset(gzipOptions) .then(function() { - return isGzipped(gzippedJson) - .then(function(isGzipped) { - expect(isGzipped).toBe(false); + return isGzippedFile(gzippedJson) + .then(function(gzipped) { + expect(gzipped).toBe(false); }); }), done).toResolve(); }); @@ -173,21 +172,20 @@ describe('gzipTileset', function() { }); it('accepts custom writeCallback that returns a promise', function (done) { - var outputDirectory = gzippedDirectory; var writeCallback = function(file, data) { - var outputFile = path.join(outputDirectory, file); - return fsExtraOutputFile(outputFile, data); + return fsExtraOutputFile(file, data); }; var gzipOptions = { inputDirectory : tilesetDirectory, + outputDirectory : gzippedDirectory, gzip : true, writeCallback : writeCallback }; expect(gzipTileset(gzipOptions) .then(function() { - return isGzipped(gzippedJson) - .then(function(isGzipped) { - expect(isGzipped).toBe(true); + return isGzippedFile(gzippedJson) + .then(function(gzipped) { + expect(gzipped).toBe(true); }); }), done).toResolve(); }); diff --git a/tools/specs/lib/isGzippedSpec.js b/tools/specs/lib/isGzippedSpec.js new file mode 100644 index 00000000..b5b14a94 --- /dev/null +++ b/tools/specs/lib/isGzippedSpec.js @@ -0,0 +1,23 @@ +'use strict'; +var Promise = require('bluebird'); +var zlib = require('zlib'); +var isGzipped = require('../../lib/isGzipped'); + +var zlibGzip = Promise.promisify(zlib.gzip); + +describe('isGzipped', function() { + it('throws DeveloperError if data is undefined', function() { + expect(function() { + isGzipped(undefined); + }).toThrowDeveloperError(); + }); + + it('detects when data is gzipped', function(done) { + var data = new Buffer(40); + expect(isGzipped(data)).toBe(false); + expect(zlibGzip(data, undefined) + .then(function(zippedData) { + expect(isGzipped(zippedData)).toBe(true); + }), done).toResolve(); + }); +}); \ No newline at end of file diff --git a/tools/specs/lib/makeCompositeTileSpec.js b/tools/specs/lib/makeCompositeTileSpec.js new file mode 100644 index 00000000..4c2ad732 --- /dev/null +++ b/tools/specs/lib/makeCompositeTileSpec.js @@ -0,0 +1,28 @@ +'use strict'; +var makeCompositeTile = require('../../lib/makeCompositeTile'); +var readTile = require('../../lib/readTile'); + +var justHeaderI3dmPath = './specs/data/justHeader.i3dm'; + +describe('makeCompositeTile', function() { + it('makes a composite tile', function(done) { + expect(readTile(justHeaderI3dmPath) + .then(function(tile) { + var tiles = [tile, tile]; + return makeCompositeTile(tiles); + }) + .then(function(tileData) { + var magic = tileData.toString('utf8', 0, 4); + var byteLength = 16 + 32 + 32; + expect(tileData.length).toBe(byteLength); + expect(magic).toEqual('cmpt'); // magic + expect(tileData.readUInt32LE(4)).toBe(1); // version + expect(tileData.readUInt32LE(8)).toBe(byteLength); // byteLength + expect(tileData.readUInt32LE(12)).toBe(2); // tilesLength + var tileMagic = tileData.toString('utf8', 16, 20); + expect(tileMagic).toEqual('i3dm'); + tileMagic = tileData.toString('utf8', 48, 52); + expect(tileMagic).toEqual('i3dm'); + }), done).toResolve(); + }); +}); \ No newline at end of file diff --git a/tools/specs/lib/readTileSpec.js b/tools/specs/lib/readTileSpec.js new file mode 100644 index 00000000..58e975ae --- /dev/null +++ b/tools/specs/lib/readTileSpec.js @@ -0,0 +1,26 @@ +'use strict'; +var readTile = require('../../lib/readTile'); + +describe('readTile', function() { + it('throws DeveloperError if filePath is undefined', function() { + expect(function() { + readTile(); + }).toThrowDeveloperError(); + }); + + it('reads a tile', function(done) { + expect(readTile('./specs/data/justHeader.i3dm') + .then(function(tileData) { + var magic = tileData.toString('utf8', 0, 4); + expect(magic).toEqual('i3dm'); + }), done).toResolve(); + }); + + it('reads a gzipped tile', function(done) { + expect(readTile('./specs/data/justHeaderGzipped.i3dm') + .then(function(tileData) { + var magic = tileData.toString('utf8', 0, 4); + expect(magic).toEqual('i3dm'); + }), done).toResolve(); + }); +}); \ No newline at end of file diff --git a/tools/specs/lib/runPipelineSpec.js b/tools/specs/lib/runPipelineSpec.js index 140534b4..bf9fdbd1 100644 --- a/tools/specs/lib/runPipelineSpec.js +++ b/tools/specs/lib/runPipelineSpec.js @@ -1,8 +1,7 @@ 'use strict'; var fsExtra = require('fs-extra'); -var path = require('path'); var Promise = require('bluebird'); -var isGzipped = require('../../lib/isGzipped'); +var isGzipped = require('../../lib/isGzippedFile'); var runPipeline = require('../../lib/runPipeline'); var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile); @@ -177,12 +176,12 @@ describe('runPipeline', function() { it('accepts custom writeCallback', function (done) { var writeCallback = function(file, data) { - var outputFile = path.join(outputDirectory, file); - return fsExtraOutputFile(outputFile, data); + return fsExtraOutputFile(file, data); }; var pipeline = { input : inputDirectory, + output : outputDirectory, stages : ['gzip'] }; diff --git a/tools/specs/lib/writeTileSpec.js b/tools/specs/lib/writeTileSpec.js new file mode 100644 index 00000000..757592e5 --- /dev/null +++ b/tools/specs/lib/writeTileSpec.js @@ -0,0 +1,54 @@ +'use strict'; +var Promise = require('bluebird'); +var fsExtra = require('fs-extra'); +var isGzipped = require('../../lib/isGzipped'); +var writeTile = require('../../lib/writeTile'); + +var fsExtraReadFile = Promise.promisify(fsExtra.readFile); +var fsExtraRemove = Promise.promisify(fsExtra.remove); + +var testOutputPath = './specs/data/.test/'; + +describe('writeTile', function() { + afterAll(function(done) { + fsExtraRemove(testOutputPath) + .then(done); + }); + + it('throws DeveloperError if filePath is undefined', function() { + expect(function() { + writeTile(undefined, new Buffer(0)); + }).toThrowDeveloperError(); + }); + + it('throws DeveloperError if tileData is undefined', function() { + expect(function() { + writeTile('', undefined); + }).toThrowDeveloperError(); + }); + + it('writes a tile', function(done) { + var path = testOutputPath + 'justmagic.i3dm'; + var data = new Buffer('i3dm'); + expect(writeTile(path, data) + .then(function() { + return fsExtraReadFile(path); + }) + .then(function(tileData) { + var magic = tileData.toString('utf8', 0, 4); + expect(magic).toEqual('i3dm'); + }), done).toResolve(); + }); + + it('writes a gzipped tile', function(done) { + var path = testOutputPath + 'justmagic.i3dm'; + var data = new Buffer('i3dm'); + expect(writeTile(path, data, {gzip : true}) + .then(function() { + return fsExtraReadFile(path); + }) + .then(function(tileData) { + expect(isGzipped(tileData)).toBeTruthy(); + }), done).toResolve(); + }); +}); \ No newline at end of file