219 lines
7 KiB
JavaScript
219 lines
7 KiB
JavaScript
// Any copyright is dedicated to the Public Domain.
|
|
// - http://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
// Portions of this file are originally from narwhal.js (http://narwhaljs.org)
|
|
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
// MIT license: http://opensource.org/licenses/MIT
|
|
|
|
/* eslint-env worker */
|
|
|
|
"use strict";
|
|
|
|
/* import-globals-from /testing/mochitest/tests/SimpleTest/WorkerSimpleTest.js */
|
|
importScripts("chrome://mochikit/content/tests/SimpleTest/WorkerSimpleTest.js");
|
|
|
|
importScripts("file_ioutils_test_fixtures.js");
|
|
|
|
self.onmessage = async function () {
|
|
const tmpDir = await PathUtils.getTempDir();
|
|
|
|
// IOUtils functionality is the same when called from the main thread, or a
|
|
// web worker. These tests are a modified subset of the main thread tests, and
|
|
// serve as a confidence check that the implementation is thread-safe.
|
|
await test_api_is_available_on_worker();
|
|
await test_full_read_and_write();
|
|
await test_move_file();
|
|
await test_copy_file();
|
|
await test_make_directory();
|
|
|
|
finish();
|
|
info("test_ioutils_worker.xhtml: Test finished");
|
|
|
|
async function test_api_is_available_on_worker() {
|
|
ok(self.IOUtils, "IOUtils is present in web workers");
|
|
}
|
|
|
|
async function test_full_read_and_write() {
|
|
// Write a file.
|
|
const tmpFileName = PathUtils.join(tmpDir, "test_ioutils_numbers.tmp");
|
|
const bytes = Uint8Array.of(...new Array(50).keys());
|
|
const bytesWritten = await IOUtils.write(tmpFileName, bytes);
|
|
is(bytesWritten, 50, "IOUtils::write can write entire byte array to file");
|
|
|
|
// Read it back.
|
|
let fileContents = await IOUtils.read(tmpFileName);
|
|
ok(
|
|
_deepEqual(bytes, fileContents) && bytes.length == fileContents.length,
|
|
"IOUtils::read can read back entire file"
|
|
);
|
|
|
|
const tooManyBytes = bytes.length + 1;
|
|
fileContents = await IOUtils.read(tmpFileName, { maxBytes: tooManyBytes });
|
|
ok(
|
|
_deepEqual(bytes, fileContents) && fileContents.length == bytes.length,
|
|
"IOUtils::read can read entire file when requested maxBytes is too large"
|
|
);
|
|
|
|
await cleanup(tmpFileName);
|
|
}
|
|
|
|
async function test_move_file() {
|
|
const src = PathUtils.join(tmpDir, "test_move_file_src.tmp");
|
|
const dest = PathUtils.join(tmpDir, "test_move_file_dest.tmp");
|
|
const bytes = Uint8Array.of(...new Array(50).keys());
|
|
await IOUtils.write(src, bytes);
|
|
|
|
await IOUtils.move(src, dest);
|
|
ok(
|
|
!(await fileExists(src)) && (await fileExists(dest)),
|
|
"IOUtils::move can move files from a worker"
|
|
);
|
|
|
|
await cleanup(dest);
|
|
}
|
|
|
|
async function test_copy_file() {
|
|
const tmpFileName = PathUtils.join(tmpDir, "test_ioutils_orig.tmp");
|
|
const destFileName = PathUtils.join(tmpDir, "test_ioutils_copy.tmp");
|
|
await createFile(tmpFileName, "original");
|
|
|
|
await IOUtils.copy(tmpFileName, destFileName);
|
|
ok(
|
|
(await fileExists(tmpFileName)) &&
|
|
(await fileHasTextContents(destFileName, "original")),
|
|
"IOUtils::copy can copy source to dest in same directory"
|
|
);
|
|
|
|
await cleanup(tmpFileName, destFileName);
|
|
}
|
|
|
|
async function test_make_directory() {
|
|
const dir = PathUtils.join(tmpDir, "test_make_dir.tmp.d");
|
|
await IOUtils.makeDirectory(dir);
|
|
const stat = await IOUtils.stat(dir);
|
|
is(
|
|
stat.type,
|
|
"directory",
|
|
"IOUtils::makeDirectory can make a new directory from a worker"
|
|
);
|
|
|
|
await cleanup(dir);
|
|
}
|
|
};
|
|
|
|
// This is copied from the ObjectUtils module, as it is difficult to translate
|
|
// file_ioutils_test_fixtures.js into a ES module and have it used in non-module
|
|
// contexts.
|
|
|
|
// ... Start of previously MIT-licensed code.
|
|
// This deepEqual implementation is originally from narwhal.js (http://narwhaljs.org)
|
|
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
// MIT license: http://opensource.org/licenses/MIT
|
|
|
|
function _deepEqual(a, b) {
|
|
// The numbering below refers to sections in the CommonJS spec.
|
|
|
|
// 7.1 All identical values are equivalent, as determined by ===.
|
|
if (a === b) {
|
|
return true;
|
|
// 7.2 If the b value is a Date object, the a value is
|
|
// equivalent if it is also a Date object that refers to the same time.
|
|
}
|
|
let aIsDate = instanceOf(a, "Date");
|
|
let bIsDate = instanceOf(b, "Date");
|
|
if (aIsDate || bIsDate) {
|
|
if (!aIsDate || !bIsDate) {
|
|
return false;
|
|
}
|
|
if (isNaN(a.getTime()) && isNaN(b.getTime())) {
|
|
return true;
|
|
}
|
|
return a.getTime() === b.getTime();
|
|
// 7.3 If the b value is a RegExp object, the a value is
|
|
// equivalent if it is also a RegExp object with the same source and
|
|
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
|
}
|
|
let aIsRegExp = instanceOf(a, "RegExp");
|
|
let bIsRegExp = instanceOf(b, "RegExp");
|
|
if (aIsRegExp || bIsRegExp) {
|
|
return (
|
|
aIsRegExp &&
|
|
bIsRegExp &&
|
|
a.source === b.source &&
|
|
a.global === b.global &&
|
|
a.multiline === b.multiline &&
|
|
a.lastIndex === b.lastIndex &&
|
|
a.ignoreCase === b.ignoreCase
|
|
);
|
|
// 7.4 Other pairs that do not both pass typeof value == "object",
|
|
// equivalence is determined by ==.
|
|
}
|
|
if (typeof a != "object" || typeof b != "object") {
|
|
return a == b;
|
|
}
|
|
// 7.5 For all other Object pairs, including Array objects, equivalence is
|
|
// determined by having the same number of owned properties (as verified
|
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
// (although not necessarily the same order), equivalent values for every
|
|
// corresponding key, and an identical 'prototype' property. Note: this
|
|
// accounts for both named and indexed properties on Arrays.
|
|
return objEquiv(a, b);
|
|
}
|
|
|
|
function instanceOf(object, type) {
|
|
return Object.prototype.toString.call(object) == "[object " + type + "]";
|
|
}
|
|
|
|
function isUndefinedOrNull(value) {
|
|
return value === null || value === undefined;
|
|
}
|
|
|
|
function isArguments(object) {
|
|
return instanceOf(object, "Arguments");
|
|
}
|
|
|
|
function objEquiv(a, b) {
|
|
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) {
|
|
return false;
|
|
}
|
|
// An identical 'prototype' property.
|
|
if ((a.prototype || undefined) != (b.prototype || undefined)) {
|
|
return false;
|
|
}
|
|
// Object.keys may be broken through screwy arguments passing. Converting to
|
|
// an array solves the problem.
|
|
if (isArguments(a)) {
|
|
if (!isArguments(b)) {
|
|
return false;
|
|
}
|
|
a = Array.prototype.slice.call(a);
|
|
b = Array.prototype.slice.call(b);
|
|
return _deepEqual(a, b);
|
|
}
|
|
let ka, kb;
|
|
try {
|
|
ka = Object.keys(a);
|
|
kb = Object.keys(b);
|
|
} catch (e) {
|
|
// Happens when one is a string literal and the other isn't
|
|
return false;
|
|
}
|
|
// Having the same number of owned properties (keys incorporates
|
|
// hasOwnProperty)
|
|
if (ka.length != kb.length) {
|
|
return false;
|
|
}
|
|
// The same set of keys (although not necessarily the same order),
|
|
ka.sort();
|
|
kb.sort();
|
|
// Equivalent values for every corresponding key, and possibly expensive deep
|
|
// test
|
|
for (let key of ka) {
|
|
if (!_deepEqual(a[key], b[key])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ... End of previously MIT-licensed code.
|