Source code

Revision control

Copy as Markdown

Other Tools

// Any copyright is dedicated to the Public Domain.
// Portions of this file are originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
/* eslint-env worker */
"use strict";
/* import-globals-from /testing/mochitest/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>
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.