From 51d8b9aea688f936591dce79f40d9a209422bb7f Mon Sep 17 00:00:00 2001 From: humbletim Date: Tue, 23 Jan 2018 03:12:50 -0500 Subject: [PATCH] update and expand on js unit tests --- .../tests/unit_tests/assetUnitTests.js | 383 ++++++++++++++++-- 1 file changed, 352 insertions(+), 31 deletions(-) diff --git a/scripts/developer/tests/unit_tests/assetUnitTests.js b/scripts/developer/tests/unit_tests/assetUnitTests.js index be8710e50d..5d43eaf1de 100644 --- a/scripts/developer/tests/unit_tests/assetUnitTests.js +++ b/scripts/developer/tests/unit_tests/assetUnitTests.js @@ -1,34 +1,46 @@ /* eslint-env jasmine */ +if (!Entities.canWriteAssets()) { + Window.alert('!Entities.canWriteAssets -- please goto a domain with asset rights and reload this test script'); + throw new Error('!Entities.canWriteAssets'); +} + instrument_testrunner(true); describe("Assets", function () { var context = { + memo: {}, + cache: {}, definedHash: null, definedPath: null, definedContent: null, }; + var ATP_TIMEOUT_MS = 1000; // ms + var NULL_HASH = new Array(64+1).join('0'); // 64 hex var SAMPLE_FOLDER = '/assetUnitTests'; var SAMPLE_FILE_PATH = SAMPLE_FOLDER + "/test.json"; var SAMPLE_CONTENTS = 'Test Run on ' + JSON.stringify(Date()); + var SAMPLE_JSON = JSON.stringify({ content: SAMPLE_CONTENTS }); + var SAMPLE_FLOATS = [ Math.PI, 1.1, 2.2, 3.3 ]; + var SAMPLE_BUFFER = new Float32Array(SAMPLE_FLOATS).buffer; + var IS_ASSET_HASH_REGEX = /^[a-f0-9]{64}$/i; var IS_ASSET_URL = /^atp:/; - it('Entities.canWriteAssets', function() { expect(Entities.canWriteAssets()).toBe(true); }); - it('Assets.extractAssetHash(input)', function() { + describe('extractAssetHash(input)', function() { // new helper method that provides a catch-all way to get at the sha256 hash // considering the multiple, different ways ATP hash URLs are found across the // system and in content. - + var POSITIVE_TEST_URLS = [ 'atp:HASH', 'atp:HASH.obj', + 'atp:HASH.fbx#cache-buster', 'atp:HASH.fbx?cache-buster', - 'atp:/.baked/HASH/asset.fbx', 'HASH' ]; var NEGATIVE_TEST_URLS = [ @@ -36,25 +48,278 @@ describe("Assets", function () { 'http://domain.tld', '/path/filename.fbx', 'atp:/path/filename.fbx?#HASH', + 'atp:/.baked/HASH/asset.fbx', '' ]; - pending(); + it("POSITIVE_TEST_URLS", function() { + POSITIVE_TEST_URLS.forEach(function(url) { + url = url.replace('HASH', NULL_HASH); + expect([url, Assets.extractAssetHash(url)].join('|')).toEqual([url, NULL_HASH].join('|')); + }); + }); + it("NEGATIVE_TEST_URLS", function() { + NEGATIVE_TEST_URLS.forEach(function(url) { + expect(Assets.extractAssetHash(url.replace('HASH', NULL_HASH))).toEqual(''); + }); + }); }); // new APIs + describe('.putAsset', function() { + it("data", function(done) { + Assets.putAsset(SAMPLE_CONTENTS, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.hash).toMatch(IS_ASSET_HASH_REGEX); + context.memo.stringURL = result.url; + done(); + }); + }); + it('nopath.text', function(done) { + Assets.putAsset({ + data: SAMPLE_CONTENTS, + }, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.hash).toMatch(IS_ASSET_HASH_REGEX); + context.memo.textHash = result.hash; + context.memo.textURL = result.url; + done(); + }); + }); + it('path.text', function(done) { + var samplePath = SAMPLE_FOLDER + '/content.json'; + Assets.putAsset({ + path: samplePath, + data: SAMPLE_JSON, + }, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.path).toEqual(samplePath); + expect(result.hash).toMatch(IS_ASSET_HASH_REGEX); + context.memo.jsonPath = result.path; + done(); + }); + }); + it('path.buffer', function(done) { + var samplePath = SAMPLE_FOLDER + '/content.buffer'; + Assets.putAsset({ + path: samplePath, + data: SAMPLE_BUFFER, + }, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.path).toEqual(samplePath); + expect(result.hash).toMatch(IS_ASSET_HASH_REGEX); + expect(result.byteLength).toEqual(SAMPLE_BUFFER.byteLength); + context.memo.bufferURL = result.url; + context.memo.bufferHash = result.hash; + done(); + }); + }); + it('path.json.gz', function(done) { + var samplePath = SAMPLE_FOLDER + '/content.json.gz'; + Assets.putAsset({ + path: samplePath, + data: SAMPLE_JSON, + compress: true, + }, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.path).toEqual(samplePath); + expect(result.hash).toMatch(IS_ASSET_HASH_REGEX); + context.memo.jsonCompressedPath = result.path; + done(); + }); + }); + }); + // it('.deleteAsset(options, {callback(error, result)})', function() { pending(); }); + it('.resolveAsset', function(done) { + expect(context.memo.bufferURL).toBeDefined(); + Assets.resolveAsset(context.memo.bufferURL, function(error, result) { + expect(error).toBe(null); + expect(result.url).toEqual(context.memo.bufferURL); + expect(result.hash).toEqual(context.memo.bufferHash); + done(); + }); + }); + describe('.getAsset', function() { + it('path/', function(done) { + expect(context.memo.jsonPath).toBeDefined(); + Assets.getAsset(context.memo.jsonPath, function(error, result) { + expect(error).toBe(null); + expect(result.response).toEqual(SAMPLE_JSON); + done(); + }); + }); + it('text', function(done) { + expect(context.memo.textURL).toBeDefined(); + Assets.getAsset({ + url: context.memo.textURL, + responseType: 'text', + }, function(error, result) { + expect(error).toBe(null); + expect(result.response).toEqual(SAMPLE_CONTENTS); + expect(result.url).toEqual(context.memo.textURL); + done(); + }); + }); + it('arraybuffer', function(done) { + expect(context.memo.bufferURL).toBeDefined(); + Assets.getAsset({ + url: context.memo.bufferURL, + responseType: 'arraybuffer', + }, function(error, result) { + expect(error).toBe(null); + expect(result.response.byteLength).toEqual(SAMPLE_BUFFER.byteLength); + var expected = [].slice.call(new Float32Array(SAMPLE_BUFFER)).join(','); + var actual = [].slice.call(new Float32Array(result.response)).join(','); + expect(actual).toEqual(expected); + done(); + }); + }); + it('json', function(done) { + expect(context.memo.jsonPath).toBeDefined(); + Assets.getAsset({ + url: context.memo.jsonPath, + responseType: 'json', + }, function(error, result) { + expect(error).toBe(null); + expect(result.response.content).toEqual(SAMPLE_CONTENTS); + done(); + }); + }); + it('json.gz', function(done) { + expect(context.memo.jsonCompressedPath).toBeDefined(); + Assets.getAsset({ + url: context.memo.jsonCompressedPath, + responseType: 'json', + decompress: true, + }, function(error, result) { + expect(error).toBe(null); + expect(result.decompressed).toBe(true); + expect(result.response.content).toEqual(SAMPLE_CONTENTS); + done(); + }); + }); + }); - it('Assets.getAsset(options, {callback(error, result)})', function() { pending(); }); - it('Assets.putAsset(options, {callback(error, result)})', function() { pending(); }); - it('Assets.deleteAsset(options, {callback(error, result)})', function() { pending(); }); - it('Assets.resolveAsset(options, {callback(error, result)})', function() { pending(); }); + // cache APIs + it('.getCacheStatus', function(done) { + Assets.getCacheStatus(function(error, result) { + expect(error).toBe(null); + expect(result.cacheSize).toBeGreaterThan(0); + expect(result.maximumCacheSize).toBeGreaterThan(0); + done(); + }); + }); + describe('.saveToCache', function() { + it(".data", function(done) { + Assets.saveToCache({ data: SAMPLE_CONTENTS }, function(error, result) { + expect(error).toBe(null); + expect(result.success).toBe(true); + context.cache.textURL = result.url; + done(); + }); + }); + it('.url', function(done) { + var sampleURL = 'atp:' + SAMPLE_FOLDER + '/cache.json'; + Assets.saveToCache({ + url: sampleURL, + data: SAMPLE_JSON, + }, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.url).toEqual(sampleURL); + expect(result.success).toBe(true); + context.cache.jsonURL = result.url; + done(); + }); + }); + it('.buffer', function(done) { + var sampleURL = 'atp:' + SAMPLE_FOLDER + '/cache.buffer'; + Assets.saveToCache({ + url: sampleURL, + data: SAMPLE_BUFFER, + }, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.url).toEqual(sampleURL); + expect(result.success).toBe(true); + expect(result.byteLength).toEqual(SAMPLE_BUFFER.byteLength); + context.cache.bufferURL = result.url; + done(); + }); + }); + }); + it('.queryCacheMeta', function(done) { + expect(context.cache.bufferURL).toBeDefined(); + Assets.queryCacheMeta(context.cache.bufferURL, function(error, result) { + expect(error).toBe(null); + expect(result.url).toMatch(IS_ASSET_URL); + expect(result.url).toEqual(context.cache.bufferURL); + done(); + }); + }); + describe('.loadFromCache', function() { + it('urlString', function(done) { + expect(context.cache.jsonURL).toBeDefined(); + Assets.loadFromCache(context.cache.jsonURL, function(error, result) { + expect(error).toBe(null); + expect(result.response).toEqual(SAMPLE_JSON); + done(); + }); + }); + it('.responseType=text', function(done) { + expect(context.cache.textURL).toBeDefined(); + Assets.loadFromCache({ + url: context.cache.textURL, + responseType: 'text', + }, function(error, result) { + expect(error).toBe(null); + expect(result.response).toEqual(SAMPLE_CONTENTS); + done(); + }); + }); + it('.responseType=arraybuffer', function(done) { + expect(context.cache.bufferURL).toBeDefined(); + Assets.loadFromCache({ + url: context.cache.bufferURL, + responseType: 'arraybuffer', + }, function(error, result) { + expect(error).toBe(null); + expect(result.response.byteLength).toEqual(SAMPLE_BUFFER.byteLength); + var expected = [].slice.call(new Float32Array(SAMPLE_BUFFER)).join(','); + var actual = [].slice.call(new Float32Array(result.response)).join(','); + expect(actual).toEqual(expected); + done(); + }); + }); + it('.responseType=json', function(done) { + expect(context.cache.jsonURL).toBeDefined(); + Assets.loadFromCache({ + url: context.cache.jsonURL, + responseType: 'json', + }, function(error, result) { + expect(error).toBe(null); + expect(result.response.content).toEqual(SAMPLE_CONTENTS); + done(); + }); + }); + }); - - // existing APIs - it('Assets.getATPUrl(input)', function() { pending(); }); - it('Assets.isValidPath(input)', function() { pending(); }); - it('Assets.isValidFilePath(input)', function() { pending(); }); - it('Assets.isValidHash(input)', function() { pending(); }); - it('Assets.setBakingEnabled(path, enabled, {callback(error)})', function() { pending(); }); + // existing newly-mapped APIs + it('.getATPUrl', function() { + expect(Assets.getATPUrl(SAMPLE_FILE_PATH)).toEqual('atp:' + SAMPLE_FILE_PATH); + expect(Assets.getATPUrl(NULL_HASH)).toEqual('atp:' + NULL_HASH); + expect(Assets.getATPUrl("/file.ext?a=b#c=d")).toEqual('atp:/file.ext?a=b#c=d'); + expect(Assets.getATPUrl("atp:xxx")).toEqual(''); + expect(Assets.getATPUrl("xxx")).toEqual(''); + }); + xit('.isValidPath', function(done) { pending(); }); + xit('.isValidFilePath', function() { pending(); }); + xit('.isValidHash', function() { pending(); }); + xit('.setBakingEnabled', function() { pending(); }); it("Assets.uploadData(data, {callback(url, hash)})", function (done) { Assets.uploadData(SAMPLE_CONTENTS, function(url, hash) { @@ -68,7 +333,7 @@ describe("Assets", function () { }); }); - it("Assets.setMapping(path, hash {callback(error)})", function (done) { + it("Assets.setMapping", function (done) { expect(context.definedHash).toMatch(IS_ASSET_HASH_REGEX); Assets.setMapping(SAMPLE_FILE_PATH, context.definedHash, function(error) { if (error) error += ' ('+JSON.stringify([SAMPLE_FILE_PATH, context.definedHash])+')'; @@ -79,7 +344,7 @@ describe("Assets", function () { }); }); - it("Assets.getMapping(path, {callback(error, hash)})", function (done) { + it("Assets.getMapping", function (done) { expect(context.definedHash).toMatch(IS_ASSET_HASH_REGEX, 'asfasdf'); expect(context.definedPath).toMatch(/^\//, 'asfasdf'); Assets.getMapping(context.definedPath, function(error, hash) { @@ -91,36 +356,47 @@ describe("Assets", function () { }); }); - it('Assets.getMapping(nullHash, {callback(data)})', function(done) { + it('.getMapping(nullHash)', function(done) { // FIXME: characterization test -- current behavior is that downloadData silently fails // when given an asset that doesn't exist Assets.downloadData(NULL_HASH, function(result) { throw new Error("this callback 'should' not be triggered"); }); - setTimeout(function() { done(); }, 2000); + setTimeout(function() { done(); }, ATP_TIMEOUT_MS); }); - it('Assets.downloadData(hash, {callback(data)})', function(done) { + it('.downloadData(hash)', function(done) { expect(context.definedHash).toMatch(IS_ASSET_HASH_REGEX, 'asfasdf'); Assets.downloadData('atp:' + context.definedHash, function(result) { expect(result).toEqual(context.definedContent); done(); }); }); - - it('Assets.downloadData(nullHash, {callback(data)})', function(done) { + + it('.downloadData(nullHash)', function(done) { // FIXME: characterization test -- current behavior is that downloadData silently fails // when given an asset doesn't exist Assets.downloadData(NULL_HASH, function(result) { throw new Error("this callback 'should' not be triggered"); }); - setTimeout(function() { - done(); - }, 2000); + setTimeout(function() { done(); }, ATP_TIMEOUT_MS); }); - + describe('exceptions', function() { - describe('Asset.setMapping', function() { + describe('.getAsset', function() { + it('-- invalid data.gz', function(done) { + expect(context.memo.jsonPath).toBeDefined(); + Assets.getAsset({ + url: context.memo.jsonPath, + responseType: 'json', + decompress: true, + }, function(error, result) { + expect(error).toMatch(/gunzip error/); + done(); + }); + }); + }); + describe('.setMapping', function() { it('-- invalid path', function(done) { Assets.setMapping('foo', NULL_HASH, function(error/*, result*/) { expect(error).toEqual('Path is invalid'); @@ -136,7 +412,7 @@ describe("Assets", function () { }); }); }); - describe('Asset.getMapping', function() { + describe('.getMapping', function() { it('-- invalid path throws immediate', function() { expect(function() { Assets.getMapping('foo', function(error, hash) { @@ -161,12 +437,57 @@ describe("Assets", function () { function run() {} function instrument_testrunner(force) { if (force || typeof describe === 'undefined') { + var oldPrint = print; + window = new OverlayWebWindow({ + title: 'assetUnitTests.js', + width: 640, + height: 480, + source: 'about:blank', + }); + Script.scriptEnding.connect(window, 'close'); + window.closed.connect(Script, 'stop'); + // wait for window (ready) and test runner (ran) both to initialize + var ready = false; + var ran = false; + window.webEventReceived.connect(function() { ready = true; maybeRun(); }); + run = function() { ran = true; maybeRun(); }; + + window.setURL([ + 'data:text/html;text,', + '', + '
', + '', + '', + ].join('\n')); + print = function() { + var str = [].slice.call(arguments).join(' '); + if (ready) { + window.emitScriptEvent(str + '\n'); + } else { + oldPrint('!ready', str); + } + }; + // Include testing library Script.include('../../libraries/jasmine/jasmine.js'); Script.include('../../libraries/jasmine/hifi-boot.js'); - run = function() { - if (!/:console/.test(Script.resolvePath(''))) { + function maybeRun() { + if (!ran || !ready) { + return oldPrint('doRun -- waiting for both script and web window to become available'); + } + if (!force) { // invoke Script.stop (after any async tests complete) jasmine.getEnv().addReporter({ jasmineDone: Script.stop }); } else {