test running, but web worker isn't being called?

master
Qvazar 2015-08-26 16:45:13 +02:00
rodzic d49886d085
commit 4d871a39f5
9 zmienionych plików z 361 dodań i 166 usunięć

Wyświetl plik

@ -6,7 +6,7 @@ var gulp = require("gulp"),
addSrc = require("gulp-add-src"),
concat = require("gulp-concat"),
jshint = require("gulp-jshint"),
jasmine = require("gulp-jasmine");
KarmaServer = require('karma').Server;
gulp.task("default", function() {
return gulp.src("untar-worker.js")
@ -16,7 +16,7 @@ gulp.task("default", function() {
.pipe(jshint.reporter("fail"))
.pipe(uglify())
.pipe(insert.transform(function(contents, file) {
var str = ["\nworkerScriptUri = URL.createObjectURL(new Blob([\""];
var str = ["\nvar workerScriptUri = URL.createObjectURL(createBlob([\""];
str.push(contents.replace(/"/g, '\\"'));
str.push("\"]));");
@ -37,10 +37,9 @@ gulp.task("default", function() {
.pipe(gulp.dest("build/dist"));
});
gulp.task("test", ["default"], function() {
return gulp.src("spec/*.js")
.pipe(jasmine({
includeStackTrace: true,
verbose: true
}));
gulp.task("test", ["default"], function(done) {
new KarmaServer({
configFile: __dirname + '/karma.conf.js',
singleRun: true
}, done).start();
});

69
karma.conf.js 100644
Wyświetl plik

@ -0,0 +1,69 @@
// Karma configuration
// Generated on Wed Aug 26 2015 11:44:53 GMT+0200 (Vesteuropa, sommertid)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'requirejs'],
// list of files / patterns to load in the browser
files: [
'https://www.promisejs.org/polyfills/promise-6.1.0.js',
'test-main.js',
{pattern: 'build/dev/**/*.js', included: false},
{pattern: 'spec/**/*.*', included: false}
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
browserNoActivityTimeout: 60000,
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
})
}

Wyświetl plik

@ -26,14 +26,21 @@
},
"homepage": "https://github.com/Qvazar/js-untar",
"devDependencies": {
"es6-promise": "^3.0.2",
"gulp": "^3.9.0",
"gulp-add-src": "^0.2.0",
"gulp-concat": "^2.6.0",
"gulp-insert": "^0.5.0",
"gulp-jasmine": "^2.0.1",
"gulp-jshint": "^1.11.2",
"gulp-sourcemaps": "^1.5.2",
"gulp-uglify": "^1.3.0",
"gulp-umd": "^0.2.0"
"gulp-umd": "^0.2.0",
"jasmine-core": "^2.3.4",
"karma": "^0.13.9",
"karma-jasmine": "^0.3.6",
"karma-phantomjs-launcher": "^0.2.1",
"karma-requirejs": "^0.2.2",
"phantomjs": "^1.9.18",
"requirejs": "^2.1.20"
}
}

18
spec/untar-spec.js 100644
Wyświetl plik

@ -0,0 +1,18 @@
define(["build/dev/untar"], function(untar) {
describe("untar", function() {
it("should unpack 3 files and a directory with 3 files", function(done) {
untar("/base/spec/data/test.tar", {
onExtract: function(file) { done(); }
}).then(
function(files) {
expect(files.length).toBe(6);
done();
},
function(err) {
done.fail(JSON.stringify(err));
}
);
}, 20000);
});
});

Wyświetl plik

@ -1,9 +0,0 @@
var untar = require("../build/dev/untar.js");
describe("untar", function() {
it("should unpack 3 files and a directory with 3 files", function() {
untar("data/test.tar").then(function(files) {
expect(files.length).toBe(6);
});
});
})

24
test-main.js 100644
Wyświetl plik

@ -0,0 +1,24 @@
var allTestFiles = [];
var TEST_REGEXP = /(spec|test)\.js$/i;
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule);
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base',
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});

Wyświetl plik

@ -1,169 +1,163 @@
(function() {
"use strict";
/* globals postMessage: false, DataView: false, self: false */
/* jshint -W097 */
"use strict";
onmessage = function(source) {
if (typeof source === "string") {
loadArrayBuffer(source).then(
untarBuffer,
function(err) { postMessage({ type: "error", data: err }); }
);
self.onmessage = function(msg) {
postLog("info", "Received message.");
try {
if (msg.data.type === "extract") {
untarBuffer(msg.data.buffer);
} else {
untarBuffer(source);
throw new Error("Unknown message type.");
}
};
function loadArrayBuffer(uri) {
return new Promise(function(resolve, reject) {
try {
var request = new XMLHttpRequest();
request.addEventListener("progress", function(e) {
postMessage({ type: "loading", data: e });
});
request.addEventListener("load", function(e) {
resolve(request.response);
});
request.addEventListener("error", reject);
request.addEventListener("abort", reject);
request.open("GET", uri);
request.responseType = "arraybuffer";
request.send();
} catch (err) {
reject(err);
}
});
} catch (err) {
postError(err);
}
};
function untarBuffer(arrayBuffer) {
try {
var tarFileStream = new TarFileStream(arrayBuffer);
while (tarFileStream.hasNext()) {
var file = tarFileStream.next();
function postError(err) {
postMessage({ type: "error", data: err });
}
function postLog(level, msg) {
postMessage({ type: "log", data: { level: level, msg: msg }});
}
function untarBuffer(arrayBuffer) {
try {
postLog("info", "buffer size: " + arrayBuffer.byteLength);
var tarFileStream = new TarFileStream(arrayBuffer);
while (tarFileStream.hasNext()) {
var file = tarFileStream.next();
if (file.buffer) {
postMessage({ type: "extract", data: file }, [file.buffer]);
}
postMessage({ type: "complete" });
} catch (err) {
postMessage({ type: "error", data: err });
}
postMessage({ type: "complete" });
} catch (err) {
postError(err);
}
}
function TarFile() {
function TarFile() {
}
}
TarFile.prototype = {
TarFile.prototype = {
};
};
function Stream(arrayBuffer) {
this._bufferView = new DataView(arrayBuffer);
this._position = 0;
}
function Stream(arrayBuffer) {
this._bufferView = new DataView(arrayBuffer);
this._position = 0;
}
Stream.prototype = {
readString: function(charCount) {
var charSize = 1;
var byteCount = charCount * charSize;
Stream.prototype = {
readString: function(charCount) {
var charSize = 1;
var byteCount = charCount * charSize;
var charCodes = [];
var charCodes = [];
for (var i = 0; i < charCount; ++i) {
var charCode = this._bufferView.getUint8(this.position() + (i * charSize));
if (charCode !== 0) {
charCodes.push(charCode);
} else {
break;
}
}
this.seek(byteCount);
return String.fromCharCode.apply(null, charCodes);
},
readBuffer: function(byteCount) {
return this._bufferView.buffer.slice(this._position, byteCount);
},
seek: function(byteCount) {
this._position += byteCount;
},
peekUint32: function() {
return this._bufferView.getUint32(this.position());
},
position: function(newpos) {
if (newpos === undefined) {
return this._position;
for (var i = 0; i < charCount; ++i) {
var charCode = this._bufferView.getUint8(this.position() + (i * charSize));
if (charCode !== 0) {
charCodes.push(charCode);
} else {
this._position = newpos;
break;
}
}
};
function TarFileStream(arrayBuffer) {
this._stream = new Stream(arrayBuffer);
this.seek(byteCount);
return String.fromCharCode.apply(null, charCodes);
},
readBuffer: function(byteCount) {
return this._bufferView.buffer.slice(this._position, byteCount);
},
seek: function(byteCount) {
this._position += byteCount;
},
peekUint32: function() {
return this._bufferView.getUint32(this.position());
},
position: function(newpos) {
if (newpos === undefined) {
return this._position;
} else {
this._position = newpos;
}
},
size: function() {
return this._bufferView.byteLength;
}
};
TarFileStream.prototype = {
hasNext: function() {
return this._stream.peekUint32() !== 0;
},
function TarFileStream(arrayBuffer) {
this._stream = new Stream(arrayBuffer);
}
next: function() {
var stream = this._stream;
var file = new TarFile();
TarFileStream.prototype = {
hasNext: function() {
return this._stream.position() < this._stream.size() && this._stream.peekUint32() !== 0;
},
var headerBeginPos = stream.position;
var dataBeginPos = headerBeginPos + 512;
next: function() {
var stream = this._stream;
var file = new TarFile();
// Read header
file.name = stream.readString(100);
file.mode = stream.readString(8);
file.uid = stream.readString(8);
file.gid = stream.readString(8);
file.size = parseInt(stream.readString(12), 8);
file.modificationTime = parseInt(stream.readString(12), 8);
file.checksum = stream.readString(8);
file.type = stream.readString(1);
file.linkname = stream.readString(1);
file.ustarFormat = stream.readString(6);
var headerBeginPos = stream.position;
var dataBeginPos = headerBeginPos + 512;
if (file.ustarFormat === "ustar") {
file.version = stream.readString(2);
file.uname = stream.readString(32);
file.gname = stream.readString(32);
file.devmajor = stream.readString(8);
file.devminor = stream.readString(8);
file.namePrefix = stream.readString(155);
// Read header
file.name = stream.readString(100);
file.mode = stream.readString(8);
file.uid = stream.readString(8);
file.gid = stream.readString(8);
file.size = parseInt(stream.readString(12), 8);
file.modificationTime = parseInt(stream.readString(12), 8);
file.checksum = stream.readString(8);
file.type = stream.readString(1);
file.linkname = stream.readString(1);
file.ustarFormat = stream.readString(6);
if (file.namePrefix.length > 0) {
file.name = file.namePrefix + file.name;
}
if (file.ustarFormat === "ustar") {
file.version = stream.readString(2);
file.uname = stream.readString(32);
file.gname = stream.readString(32);
file.devmajor = stream.readString(8);
file.devminor = stream.readString(8);
file.namePrefix = stream.readString(155);
if (file.namePrefix.length > 0) {
file.name = file.namePrefix + file.name;
}
stream.position(dataBeginPos);
// Normal file is either "\0" or 0.
if (file.type === 0 || file.type === "\0") {
file.buffer = stream.readBuffer(file.size);
} else if (file.type == 5) {
// Directory - should we do anything with this? Nope!
} else {
// We only care about real files, not symlinks.
}
// File data is padded to reach a 512 byte boundary; skip the padded bytes.
var bytesToSkipCount = 512 - file.size % 512;
stream.seek(bytesToSkipCount);
return file;
}
};
}());
stream.position(dataBeginPos);
// Normal file is either "\0" or 0.
if (file.type === 0 || file.type === "\0") {
file.buffer = stream.readBuffer(file.size);
} else if (file.type == 5) {
// Directory - should we do anything with this? Nope!
} else {
// We only care about real files, not symlinks.
}
// File data is padded to reach a 512 byte boundary; skip the padded bytes.
var bytesToSkipCount = 512 - file.size % 512;
stream.seek(bytesToSkipCount);
return file;
}
};
postMessage({ type: "ready" });

111
untar.js
Wyświetl plik

@ -1,5 +1,73 @@
/* globals window: false, Blob: false, Promise: false, console: false, XMLHttpRequest: false, Worker: false */
/* jshint -W097 */
"use strict";
var workerScriptUri; // Included at compile time
var URL = window.URL || window.webkitURL;
var createBlob = (function() {
if (typeof window.Blob === "function") {
return function(dataArray) { return new Blob(dataArray); };
} else {
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;
return function(dataArray) {
var builder = new BlobBuilder();
for (var i = 0; i < dataArray.length; ++i) {
builder.append(dataArray[i]);
}
return builder.getBlob();
};
}
}());
function createBlob(dataArray) {
if (typeof window.Blob === "function") {
return new Blob(dataArray);
} else {
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;
var builder = new BlobBuilder();
for (var i = 0; i < dataArray.length; ++i) {
builder.append(dataArray[i]);
}
return builder.getBlob();
}
}
function loadArrayBuffer(uri) {
console.info("loadArrayBuffer called");
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
/*
request.addEventListener("progress", function(e) {
postMessage({ type: "loading", data: e });
});
*/
request.addEventListener("load", function(e) {
if (request.status >= 200 && request.status < 400) {
resolve(request.response);
} else {
reject(new Error(request.status + " " + request.statusText));
}
});
request.addEventListener("error", function(err) { reject(err); });
request.addEventListener("abort", function(err) { reject(err); });
request.open("GET", uri, true);
request.responseType = "arraybuffer";
request.send();
});
}
/**
source = ArrayBuffer or a url string. If an ArrayBuffer, it will be transfered to the web worker and will thus not be available in the window after.
options = {
@ -10,12 +78,13 @@ options = {
}
*/
function untar(source, options) {
"use strict";
console.info("untar called");
if (typeof Promise !== "function") {
throw new Error("Promise implementation not available in this environment.");
}
if (typeof Worker !== "function") {
if (!window.Worker) {
throw new Error("Worker implementation not available in this environment.");
}
@ -29,11 +98,40 @@ function untar(source, options) {
var onError = options.onError || noop;
var worker = new Worker(workerScriptUri);
function initWorker() {
// Is source a string? Then assume it's a URL and download it.
if (typeof source === "string") {
loadArrayBuffer(source).then(
function(buffer) {
console.info("Loaded tar file, extracting.");
worker.postMessage({ type: "extract", buffer: buffer }, [buffer]);
},
function(err) {
onError(err);
reject(err);
}
);
} else {
console.info("Extracting tar file.");
worker.postMessage({ type: "extract", buffer: source }, [source]);
}
}
var files = [];
var msgData;
worker.onmessage = function(message) {
message = message.data;
switch (message.type) {
case "ready":
console.info("Worker is ready.");
initWorker();
break;
case "log":
console[message.data.level]("Worker: " + message.data.msg);
break;
case "loading":
onLoading(message.data);
break;
@ -52,26 +150,22 @@ function untar(source, options) {
reject(msgData);
break;
default:
msgData = new Error("Unknown message from worker.");
msgData = new Error("Unknown message from worker: " + message.type);
onError(msgData);
reject(msgData);
break;
}
};
// Don't transfer if source is a string. Only ArrayBuffer can be transfered.
worker.postMessage(source, (typeof source === "string" ? undefined : [source]));
});
}
function TarFile(orig) {
"use strict";
this._blobUrl = null;
for (var p in orig) {
switch (p) {
case "buffer":
this.blob = new Blob([orig.buffer]);
this.blob = createBlob([orig.buffer]);
break;
default:
this[p] = orig[p];
@ -82,7 +176,6 @@ function TarFile(orig) {
TarFile.prototype = {
getObjectUrl: function() {
"use strict";
if (!this._blobUrl) {
this._blobUrl = URL.createObjectURL(this.blob);
}