Update wmts-hidpi, add nicer-api-docs

This commit is contained in:
Andreas Hocevar
2014-05-06 13:02:46 -05:00
parent b3ac1afd00
commit 1e25fc5585
2239 changed files with 3726515 additions and 37010 deletions

View File

@@ -0,0 +1,116 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock blob object.
*
*/
goog.provide('goog.testing.fs.Blob');
goog.require('goog.crypt.base64');
/**
* A mock Blob object. The data is stored as a string.
*
* @param {string=} opt_data The string data encapsulated by the blob.
* @param {string=} opt_type The mime type of the blob.
* @constructor
*/
goog.testing.fs.Blob = function(opt_data, opt_type) {
/**
* @see http://www.w3.org/TR/FileAPI/#dfn-type
* @type {string}
*/
this.type = opt_type || '';
this.setDataInternal(opt_data || '');
};
/**
* The string data encapsulated by the blob.
* @type {string}
* @private
*/
goog.testing.fs.Blob.prototype.data_;
/**
* @see http://www.w3.org/TR/FileAPI/#dfn-size
* @type {number}
*/
goog.testing.fs.Blob.prototype.size;
/**
* @see http://www.w3.org/TR/FileAPI/#dfn-slice
* @param {number} start The start byte offset.
* @param {number} length The number of bytes to slice.
* @param {string=} opt_contentType The type of the resulting Blob.
* @return {!goog.testing.fs.Blob} The result of the slice operation.
*/
goog.testing.fs.Blob.prototype.slice = function(
start, length, opt_contentType) {
start = Math.max(0, start);
return new goog.testing.fs.Blob(
this.data_.substring(start, start + Math.max(length, 0)),
opt_contentType);
};
/**
* @return {string} The string data encapsulated by the blob.
* @override
*/
goog.testing.fs.Blob.prototype.toString = function() {
return this.data_;
};
/**
* @return {ArrayBuffer} The string data encapsulated by the blob as an
* ArrayBuffer.
*/
goog.testing.fs.Blob.prototype.toArrayBuffer = function() {
var buf = new ArrayBuffer(this.data_.length * 2);
var arr = new Uint16Array(buf);
for (var i = 0; i < this.data_.length; i++) {
arr[i] = this.data_.charCodeAt(i);
}
return buf;
};
/**
* @return {string} The string data encapsulated by the blob as a data: URI.
*/
goog.testing.fs.Blob.prototype.toDataUrl = function() {
return 'data:' + this.type + ';base64,' +
goog.crypt.base64.encodeString(this.data_);
};
/**
* Sets the internal contents of the blob. This should only be called by other
* functions inside the {@code goog.testing.fs} namespace.
*
* @param {string} data The data for this Blob.
*/
goog.testing.fs.Blob.prototype.setDataInternal = function(data) {
this.data_ = data;
this.size = data.length;
};

View File

@@ -0,0 +1,621 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock filesystem objects. These are all in the same file to
* avoid circular dependency issues.
*
*/
goog.provide('goog.testing.fs.DirectoryEntry');
goog.provide('goog.testing.fs.Entry');
goog.provide('goog.testing.fs.FileEntry');
goog.require('goog.Timer');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.async.Deferred');
goog.require('goog.fs.DirectoryEntry');
goog.require('goog.fs.DirectoryEntryImpl');
goog.require('goog.fs.Entry');
goog.require('goog.fs.Error');
goog.require('goog.fs.FileEntry');
goog.require('goog.functions');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.testing.fs.File');
goog.require('goog.testing.fs.FileWriter');
/**
* A mock filesystem entry object.
*
* @param {!goog.testing.fs.FileSystem} fs The filesystem containing this entry.
* @param {!goog.testing.fs.DirectoryEntry} parent The directory entry directly
* containing this entry.
* @param {string} name The name of this entry.
* @constructor
* @implements {goog.fs.Entry}
*/
goog.testing.fs.Entry = function(fs, parent, name) {
/**
* This entry's filesystem.
* @type {!goog.testing.fs.FileSystem}
* @private
*/
this.fs_ = fs;
/**
* The name of this entry.
* @type {string}
* @private
*/
this.name_ = name;
/**
* The parent of this entry.
* @type {!goog.testing.fs.DirectoryEntry}
*/
this.parent = parent;
};
/**
* Whether or not this entry has been deleted.
* @type {boolean}
*/
goog.testing.fs.Entry.prototype.deleted = false;
/** @override */
goog.testing.fs.Entry.prototype.isFile = goog.abstractMethod;
/** @override */
goog.testing.fs.Entry.prototype.isDirectory = goog.abstractMethod;
/** @override */
goog.testing.fs.Entry.prototype.getName = function() {
return this.name_;
};
/** @override */
goog.testing.fs.Entry.prototype.getFullPath = function() {
if (this.getName() == '' || this.parent.getName() == '') {
// The root directory has an empty name
return '/' + this.name_;
} else {
return this.parent.getFullPath() + '/' + this.name_;
}
};
/**
* @return {!goog.testing.fs.FileSystem}
* @override
*/
goog.testing.fs.Entry.prototype.getFileSystem = function() {
return this.fs_;
};
/** @override */
goog.testing.fs.Entry.prototype.getLastModified = goog.abstractMethod;
/** @override */
goog.testing.fs.Entry.prototype.getMetadata = goog.abstractMethod;
/** @override */
goog.testing.fs.Entry.prototype.moveTo = function(parent, opt_newName) {
var msg = 'moving ' + this.getFullPath() + ' into ' + parent.getFullPath() +
(opt_newName ? ', renaming to ' + opt_newName : '');
var newFile;
return this.checkNotDeleted(msg).
addCallback(function() { return this.copyTo(parent, opt_newName); }).
addCallback(function(file) {
newFile = file;
return this.remove();
}).addCallback(function() { return newFile; });
};
/** @override */
goog.testing.fs.Entry.prototype.copyTo = function(parent, opt_newName) {
goog.asserts.assert(parent instanceof goog.testing.fs.DirectoryEntry);
var msg = 'copying ' + this.getFullPath() + ' into ' + parent.getFullPath() +
(opt_newName ? ', renaming to ' + opt_newName : '');
return this.checkNotDeleted(msg).addCallback(function() {
var name = opt_newName || this.getName();
var entry = this.clone();
parent.children[name] = entry;
parent.lastModifiedTimestamp_ = goog.now();
entry.name_ = name;
entry.parent = parent;
return entry;
});
};
/**
* @return {!goog.testing.fs.Entry} A shallow copy of this entry object.
*/
goog.testing.fs.Entry.prototype.clone = goog.abstractMethod;
/** @override */
goog.testing.fs.Entry.prototype.toUrl = function(opt_mimetype) {
return 'fakefilesystem:' + this.getFullPath();
};
/** @override */
goog.testing.fs.Entry.prototype.toUri = goog.testing.fs.Entry.prototype.toUrl;
/** @override */
goog.testing.fs.Entry.prototype.wrapEntry = goog.abstractMethod;
/** @override */
goog.testing.fs.Entry.prototype.remove = function() {
var msg = 'removing ' + this.getFullPath();
return this.checkNotDeleted(msg).addCallback(function() {
delete this.parent.children[this.getName()];
this.parent.lastModifiedTimestamp_ = goog.now();
this.deleted = true;
return;
});
};
/** @override */
goog.testing.fs.Entry.prototype.getParent = function() {
var msg = 'getting parent of ' + this.getFullPath();
return this.checkNotDeleted(msg).
addCallback(function() { return this.parent; });
};
/**
* Return a deferred that will call its errback if this entry has been deleted.
* In addition, the deferred will only run after a timeout of 0, and all its
* callbacks will run with the entry as "this".
*
* @param {string} action The name of the action being performed. For error
* reporting.
* @return {!goog.async.Deferred} The deferred that will be called after a
* timeout of 0.
* @protected
*/
goog.testing.fs.Entry.prototype.checkNotDeleted = function(action) {
var d = new goog.async.Deferred(undefined, this);
goog.Timer.callOnce(function() {
if (this.deleted) {
d.errback(new goog.fs.Error(goog.fs.Error.ErrorCode.NOT_FOUND, action));
} else {
d.callback();
}
}, 0, this);
return d;
};
/**
* A mock directory entry object.
*
* @param {!goog.testing.fs.FileSystem} fs The filesystem containing this entry.
* @param {goog.testing.fs.DirectoryEntry} parent The directory entry directly
* containing this entry. If this is null, that means this is the root
* directory and so is its own parent.
* @param {string} name The name of this entry.
* @param {!Object.<!goog.testing.fs.Entry>} children The map of child names to
* entry objects.
* @constructor
* @extends {goog.testing.fs.Entry}
* @implements {goog.fs.DirectoryEntry}
*/
goog.testing.fs.DirectoryEntry = function(fs, parent, name, children) {
goog.base(this, fs, parent || this, name);
/**
* The map of child names to entry objects.
* @type {!Object.<!goog.testing.fs.Entry>}
*/
this.children = children;
/**
* The modification time of the directory. Measured using goog.now, which may
* be overridden with mock time providers.
* @type {number}
* @private
*/
this.lastModifiedTimestamp_ = goog.now();
};
goog.inherits(goog.testing.fs.DirectoryEntry, goog.testing.fs.Entry);
/**
* Constructs and returns the metadata object for this entry.
* @return {{modificationTime: Date}} The metadata object.
* @private
*/
goog.testing.fs.DirectoryEntry.prototype.getMetadata_ = function() {
return {
'modificationTime': new Date(this.lastModifiedTimestamp_)
};
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.isFile = function() {
return false;
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.isDirectory = function() {
return true;
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.getLastModified = function() {
var msg = 'reading last modified date for ' + this.getFullPath();
return this.checkNotDeleted(msg).
addCallback(function() {return new Date(this.lastModifiedTimestamp_)});
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.getMetadata = function() {
var msg = 'reading metadata for ' + this.getFullPath();
return this.checkNotDeleted(msg).
addCallback(function() {return this.getMetadata_()});
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.clone = function() {
return new goog.testing.fs.DirectoryEntry(
this.getFileSystem(), this.parent, this.getName(), this.children);
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.remove = function() {
if (!goog.object.isEmpty(this.children)) {
var d = new goog.async.Deferred();
goog.Timer.callOnce(function() {
d.errback(new goog.fs.Error(
goog.fs.Error.ErrorCode.INVALID_MODIFICATION,
'removing ' + this.getFullPath()));
}, 0, this);
return d;
} else {
return goog.base(this, 'remove');
}
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.getFile = function(
path, opt_behavior) {
var msg = 'loading file ' + path + ' from ' + this.getFullPath();
opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
return this.checkNotDeleted(msg).addCallback(function() {
try {
return goog.async.Deferred.succeed(this.getFileSync(path, opt_behavior));
} catch (e) {
return goog.async.Deferred.fail(e);
}
});
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.getDirectory = function(
path, opt_behavior) {
var msg = 'loading directory ' + path + ' from ' + this.getFullPath();
opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
return this.checkNotDeleted(msg).addCallback(function() {
try {
return goog.async.Deferred.succeed(
this.getDirectorySync(path, opt_behavior));
} catch (e) {
return goog.async.Deferred.fail(e);
}
});
};
/**
* Get a file entry synchronously, without waiting for a Deferred to resolve.
*
* @param {string} path The path to the file, relative to this directory.
* @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
* loading the file.
* @return {!goog.testing.fs.FileEntry} The loaded file.
*/
goog.testing.fs.DirectoryEntry.prototype.getFileSync = function(
path, opt_behavior) {
opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
return (/** @type {!goog.testing.fs.FileEntry} */ (this.getEntry_(
path, opt_behavior, true /* isFile */,
goog.bind(function(parent, name) {
return new goog.testing.fs.FileEntry(
this.getFileSystem(), parent, name, '');
}, this))));
};
/**
* Creates a file synchronously. This is a shorthand for getFileSync, useful for
* setting up tests.
*
* @param {string} path The path to the file, relative to this directory.
* @return {!goog.testing.fs.FileEntry} The created file.
*/
goog.testing.fs.DirectoryEntry.prototype.createFileSync = function(path) {
return this.getFileSync(path, goog.fs.DirectoryEntry.Behavior.CREATE);
};
/**
* Get a directory synchronously, without waiting for a Deferred to resolve.
*
* @param {string} path The path to the directory, relative to this one.
* @param {goog.fs.DirectoryEntry.Behavior=} opt_behavior The behavior for
* loading the directory.
* @return {!goog.testing.fs.DirectoryEntry} The loaded directory.
*/
goog.testing.fs.DirectoryEntry.prototype.getDirectorySync = function(
path, opt_behavior) {
opt_behavior = opt_behavior || goog.fs.DirectoryEntry.Behavior.DEFAULT;
return (/** @type {!goog.testing.fs.DirectoryEntry} */ (this.getEntry_(
path, opt_behavior, false /* isFile */,
goog.bind(function(parent, name) {
return new goog.testing.fs.DirectoryEntry(
this.getFileSystem(), parent, name, {});
}, this))));
};
/**
* Creates a directory synchronously. This is a shorthand for getFileSync,
* useful for setting up tests.
*
* @param {string} path The path to the directory, relative to this directory.
* @return {!goog.testing.fs.DirectoryEntry} The created directory.
*/
goog.testing.fs.DirectoryEntry.prototype.createDirectorySync = function(path) {
return this.getDirectorySync(path, goog.fs.DirectoryEntry.Behavior.CREATE);
};
/**
* Get a file or directory entry from a path. This handles parsing the path for
* subdirectories and throwing appropriate errors should something go wrong.
*
* @param {string} path The path to the entry, relative to this directory.
* @param {goog.fs.DirectoryEntry.Behavior} behavior The behavior for loading
* the entry.
* @param {boolean} isFile Whether a file or directory is being loaded.
* @param {function(!goog.testing.fs.DirectoryEntry, string) :
* !goog.testing.fs.Entry} createFn
* The function for creating the entry if it doesn't yet exist. This is
* passed the parent entry and the name of the new entry.
* @return {!goog.testing.fs.Entry} The loaded entry.
* @private
*/
goog.testing.fs.DirectoryEntry.prototype.getEntry_ = function(
path, behavior, isFile, createFn) {
// Filter out leading, trailing, and duplicate slashes.
var components = goog.array.filter(path.split('/'), goog.functions.identity);
var basename = /** @type {string} */ (goog.array.peek(components)) || '';
var dir = goog.string.startsWith(path, '/') ?
this.getFileSystem().getRoot() : this;
goog.array.forEach(components.slice(0, -1), function(p) {
var subdir = dir.children[p];
if (!subdir) {
throw new goog.fs.Error(
goog.fs.Error.ErrorCode.NOT_FOUND,
'loading ' + path + ' from ' + this.getFullPath() + ' (directory ' +
dir.getFullPath() + '/' + p + ')');
}
dir = subdir;
}, this);
// If there is no basename, the path must resolve to the root directory.
var entry = basename ? dir.children[basename] : dir;
if (!entry) {
if (behavior == goog.fs.DirectoryEntry.Behavior.DEFAULT) {
throw new goog.fs.Error(
goog.fs.Error.ErrorCode.NOT_FOUND,
'loading ' + path + ' from ' + this.getFullPath());
} else {
goog.asserts.assert(
behavior == goog.fs.DirectoryEntry.Behavior.CREATE ||
behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE);
entry = createFn(dir, basename);
dir.children[basename] = entry;
this.lastModifiedTimestamp_ = goog.now();
return entry;
}
} else if (behavior == goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE) {
throw new goog.fs.Error(
goog.fs.Error.ErrorCode.PATH_EXISTS,
'loading ' + path + ' from ' + this.getFullPath());
} else if (entry.isFile() != isFile) {
throw new goog.fs.Error(
goog.fs.Error.ErrorCode.TYPE_MISMATCH,
'loading ' + path + ' from ' + this.getFullPath());
} else {
if (behavior == goog.fs.DirectoryEntry.Behavior.CREATE) {
this.lastModifiedTimestamp_ = goog.now();
}
return entry;
}
};
/**
* Returns whether this directory has a child with the given name.
*
* @param {string} name The name of the entry to check for.
* @return {boolean} Whether or not this has a child with the given name.
*/
goog.testing.fs.DirectoryEntry.prototype.hasChild = function(name) {
return name in this.children;
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.removeRecursively = function() {
var msg = 'removing ' + this.getFullPath() + ' recursively';
return this.checkNotDeleted(msg).addCallback(function() {
var d = goog.async.Deferred.succeed(null);
goog.object.forEach(this.children, function(child) {
d.awaitDeferred(
child.isDirectory() ? child.removeRecursively() : child.remove());
});
d.addCallback(function() { return this.remove(); }, this);
return d;
});
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.listDirectory = function() {
var msg = 'listing ' + this.getFullPath();
return this.checkNotDeleted(msg).addCallback(function() {
return goog.object.getValues(this.children);
});
};
/** @override */
goog.testing.fs.DirectoryEntry.prototype.createPath =
// This isn't really type-safe.
/** @type {!Function} */ (goog.fs.DirectoryEntryImpl.prototype.createPath);
/**
* A mock file entry object.
*
* @param {!goog.testing.fs.FileSystem} fs The filesystem containing this entry.
* @param {!goog.testing.fs.DirectoryEntry} parent The directory entry directly
* containing this entry.
* @param {string} name The name of this entry.
* @param {string} data The data initially contained in the file.
* @constructor
* @extends {goog.testing.fs.Entry}
* @implements {goog.fs.FileEntry}
*/
goog.testing.fs.FileEntry = function(fs, parent, name, data) {
goog.base(this, fs, parent, name);
/**
* The internal file blob referenced by this file entry.
* @type {!goog.testing.fs.File}
* @private
*/
this.file_ = new goog.testing.fs.File(name, new Date(goog.now()), data);
/**
* The metadata for file.
* @type {{modificationTime: Date}}
* @private
*/
this.metadata_ = {
'modificationTime': this.file_.lastModifiedDate
};
};
goog.inherits(goog.testing.fs.FileEntry, goog.testing.fs.Entry);
/** @override */
goog.testing.fs.FileEntry.prototype.isFile = function() {
return true;
};
/** @override */
goog.testing.fs.FileEntry.prototype.isDirectory = function() {
return false;
};
/** @override */
goog.testing.fs.FileEntry.prototype.clone = function() {
return new goog.testing.fs.FileEntry(
this.getFileSystem(), this.parent,
this.getName(), this.fileSync().toString());
};
/** @override */
goog.testing.fs.FileEntry.prototype.getLastModified = function() {
return this.file().addCallback(function(file) {
return file.lastModifiedDate;
});
};
/** @override */
goog.testing.fs.FileEntry.prototype.getMetadata = function() {
var msg = 'getting metadata for ' + this.getFullPath();
return this.checkNotDeleted(msg).addCallback(function() {
return this.metadata_;
});
};
/** @override */
goog.testing.fs.FileEntry.prototype.createWriter = function() {
var d = new goog.async.Deferred();
goog.Timer.callOnce(
goog.bind(d.callback, d, new goog.testing.fs.FileWriter(this)));
return d;
};
/** @override */
goog.testing.fs.FileEntry.prototype.file = function() {
var msg = 'getting file for ' + this.getFullPath();
return this.checkNotDeleted(msg).addCallback(function() {
return this.fileSync();
});
};
/**
* Get the internal file representation synchronously, without waiting for a
* Deferred to resolve.
*
* @return {!goog.testing.fs.File} The internal file blob referenced by this
* FileEntry.
*/
goog.testing.fs.FileEntry.prototype.fileSync = function() {
return this.file_;
};

View File

@@ -0,0 +1,52 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock file object.
*
*/
goog.provide('goog.testing.fs.File');
goog.require('goog.testing.fs.Blob');
/**
* A mock file object.
*
* @param {string} name The name of the file.
* @param {Date=} opt_lastModified The last modified date for this file. May be
* null if file modification dates are not supported.
* @param {string=} opt_data The string data encapsulated by the blob.
* @param {string=} opt_type The mime type of the blob.
* @constructor
* @extends {goog.testing.fs.Blob}
*/
goog.testing.fs.File = function(name, opt_lastModified, opt_data, opt_type) {
goog.base(this, opt_data, opt_type);
/**
* @see http://www.w3.org/TR/FileAPI/#dfn-name
* @type {string}
*/
this.name = name;
/**
* @see http://www.w3.org/TR/FileAPI/#dfn-lastModifiedDate
* @type {Date}
*/
this.lastModifiedDate = opt_lastModified || null;
};
goog.inherits(goog.testing.fs.File, goog.testing.fs.Blob);

View File

@@ -0,0 +1,272 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock FileReader object.
*
*/
goog.provide('goog.testing.fs.FileReader');
goog.require('goog.Timer');
goog.require('goog.events.EventTarget');
goog.require('goog.fs.Error');
goog.require('goog.fs.FileReader.EventType');
goog.require('goog.fs.FileReader.ReadyState');
goog.require('goog.testing.fs.File');
goog.require('goog.testing.fs.ProgressEvent');
/**
* A mock FileReader object. This emits the same events as
* {@link goog.fs.FileReader}.
*
* @constructor
* @extends {goog.events.EventTarget}
*/
goog.testing.fs.FileReader = function() {
goog.base(this);
/**
* The current state of the reader.
* @type {goog.fs.FileReader.ReadyState}
* @private
*/
this.readyState_ = goog.fs.FileReader.ReadyState.INIT;
};
goog.inherits(goog.testing.fs.FileReader, goog.events.EventTarget);
/**
* The most recent error experienced by this reader.
* @type {goog.fs.Error}
* @private
*/
goog.testing.fs.FileReader.prototype.error_;
/**
* Whether the current operation has been aborted.
* @type {boolean}
* @private
*/
goog.testing.fs.FileReader.prototype.aborted_ = false;
/**
* The blob this reader is reading from.
* @type {goog.testing.fs.Blob}
* @private
*/
goog.testing.fs.FileReader.prototype.blob_;
/**
* The possible return types.
* @enum {number}
*/
goog.testing.fs.FileReader.ReturnType = {
/**
* Used when reading as text.
*/
TEXT: 1,
/**
* Used when reading as binary string.
*/
BINARY_STRING: 2,
/**
* Used when reading as array buffer.
*/
ARRAY_BUFFER: 3,
/**
* Used when reading as data URL.
*/
DATA_URL: 4
};
/**
* The return type we're reading.
* @type {goog.testing.fs.FileReader.ReturnType}
* @private
*/
goog.testing.fs.FileReader.returnType_;
/**
* @see {goog.fs.FileReader#getReadyState}
* @return {goog.fs.FileReader.ReadyState} The current ready state.
*/
goog.testing.fs.FileReader.prototype.getReadyState = function() {
return this.readyState_;
};
/**
* @see {goog.fs.FileReader#getError}
* @return {goog.fs.Error} The current error.
*/
goog.testing.fs.FileReader.prototype.getError = function() {
return this.error_;
};
/**
* @see {goog.fs.FileReader#abort}
*/
goog.testing.fs.FileReader.prototype.abort = function() {
if (this.readyState_ != goog.fs.FileReader.ReadyState.LOADING) {
var msg = 'aborting read';
throw new goog.fs.Error(goog.fs.Error.ErrorCode.INVALID_STATE, msg);
}
this.aborted_ = true;
};
/**
* @see {goog.fs.FileReader#getResult}
* @return {*} The result of the file read.
*/
goog.testing.fs.FileReader.prototype.getResult = function() {
if (this.readyState_ != goog.fs.FileReader.ReadyState.DONE) {
return undefined;
}
if (this.error_) {
return undefined;
}
if (this.returnType_ == goog.testing.fs.FileReader.ReturnType.TEXT) {
return this.blob_.toString();
} else if (this.returnType_ ==
goog.testing.fs.FileReader.ReturnType.ARRAY_BUFFER) {
return this.blob_.toArrayBuffer();
} else if (this.returnType_ ==
goog.testing.fs.FileReader.ReturnType.BINARY_STRING) {
return this.blob_.toString();
} else if (this.returnType_ ==
goog.testing.fs.FileReader.ReturnType.DATA_URL) {
return this.blob_.toDataUrl();
} else {
return undefined;
}
};
/**
* Fires the read events.
* @param {!goog.testing.fs.Blob} blob The blob to read from.
* @private
*/
goog.testing.fs.FileReader.prototype.read_ = function(blob) {
this.blob_ = blob;
if (this.readyState_ == goog.fs.FileReader.ReadyState.LOADING) {
var msg = 'reading file';
throw new goog.fs.Error(goog.fs.Error.ErrorCode.INVALID_STATE, msg);
}
this.readyState_ = goog.fs.FileReader.ReadyState.LOADING;
goog.Timer.callOnce(function() {
if (this.aborted_) {
this.abort_(blob.size);
return;
}
this.progressEvent_(goog.fs.FileReader.EventType.LOAD_START, 0, blob.size);
this.progressEvent_(goog.fs.FileReader.EventType.LOAD, blob.size / 2,
blob.size);
this.progressEvent_(goog.fs.FileReader.EventType.LOAD, blob.size,
blob.size);
this.readyState_ = goog.fs.FileReader.ReadyState.DONE;
this.progressEvent_(goog.fs.FileReader.EventType.LOAD, blob.size,
blob.size);
this.progressEvent_(goog.fs.FileReader.EventType.LOAD_END, blob.size,
blob.size);
}, 0, this);
};
/**
* @see {goog.fs.FileReader#readAsBinaryString}
* @param {!goog.testing.fs.Blob} blob The blob to read.
*/
goog.testing.fs.FileReader.prototype.readAsBinaryString = function(blob) {
this.returnType_ = goog.testing.fs.FileReader.ReturnType.BINARY_STRING;
this.read_(blob);
};
/**
* @see {goog.fs.FileReader#readAsArrayBuffer}
* @param {!goog.testing.fs.Blob} blob The blob to read.
*/
goog.testing.fs.FileReader.prototype.readAsArrayBuffer = function(blob) {
this.returnType_ = goog.testing.fs.FileReader.ReturnType.ARRAY_BUFFER;
this.read_(blob);
};
/**
* @see {goog.fs.FileReader#readAsText}
* @param {!goog.testing.fs.Blob} blob The blob to read.
* @param {string=} opt_encoding The name of the encoding to use.
*/
goog.testing.fs.FileReader.prototype.readAsText = function(blob, opt_encoding) {
this.returnType_ = goog.testing.fs.FileReader.ReturnType.TEXT;
this.read_(blob);
};
/**
* @see {goog.fs.FileReader#readAsDataUrl}
* @param {!goog.testing.fs.Blob} blob The blob to read.
*/
goog.testing.fs.FileReader.prototype.readAsDataUrl = function(blob) {
this.returnType_ = goog.testing.fs.FileReader.ReturnType.DATA_URL;
this.read_(blob);
};
/**
* Abort the current action and emit appropriate events.
*
* @param {number} total The total data that was to be processed, in bytes.
* @private
*/
goog.testing.fs.FileReader.prototype.abort_ = function(total) {
this.error_ = new goog.fs.Error(
goog.fs.Error.ErrorCode.ABORT, 'reading file');
this.progressEvent_(goog.fs.FileReader.EventType.ERROR, 0, total);
this.progressEvent_(goog.fs.FileReader.EventType.ABORT, 0, total);
this.readyState_ = goog.fs.FileReader.ReadyState.DONE;
this.progressEvent_(goog.fs.FileReader.EventType.LOAD_END, 0, total);
this.aborted_ = false;
};
/**
* Dispatch a progress event.
*
* @param {goog.fs.FileReader.EventType} type The event type.
* @param {number} loaded The number of bytes processed.
* @param {number} total The total data that was to be processed, in bytes.
* @private
*/
goog.testing.fs.FileReader.prototype.progressEvent_ = function(type, loaded,
total) {
this.dispatchEvent(new goog.testing.fs.ProgressEvent(type, loaded, total));
};

View File

@@ -0,0 +1,63 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock filesystem object.
*
*/
goog.provide('goog.testing.fs.FileSystem');
goog.require('goog.fs.FileSystem');
goog.require('goog.testing.fs.DirectoryEntry');
/**
* A mock filesystem object.
*
* @param {string=} opt_name The name of the filesystem.
* @constructor
* @implements {goog.fs.FileSystem}
*/
goog.testing.fs.FileSystem = function(opt_name) {
/**
* The name of the filesystem.
* @type {string}
* @private
*/
this.name_ = opt_name || 'goog.testing.fs.FileSystem';
/**
* The root entry of the filesystem.
* @type {!goog.testing.fs.DirectoryEntry}
* @private
*/
this.root_ = new goog.testing.fs.DirectoryEntry(this, null, '', {});
};
/** @override */
goog.testing.fs.FileSystem.prototype.getName = function() {
return this.name_;
};
/**
* @override
* @return {!goog.testing.fs.DirectoryEntry}
*/
goog.testing.fs.FileSystem.prototype.getRoot = function() {
return this.root_;
};

View File

@@ -0,0 +1,261 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock FileWriter object.
*
*/
goog.provide('goog.testing.fs.FileWriter');
goog.require('goog.Timer');
goog.require('goog.events.Event');
goog.require('goog.events.EventTarget');
goog.require('goog.fs.Error');
goog.require('goog.fs.FileSaver.EventType');
goog.require('goog.fs.FileSaver.ReadyState');
goog.require('goog.string');
goog.require('goog.testing.fs.File');
goog.require('goog.testing.fs.ProgressEvent');
/**
* A mock FileWriter object. This emits the same events as
* {@link goog.fs.FileSaver} and {@link goog.fs.FileWriter}.
*
* @param {!goog.testing.fs.FileEntry} fileEntry The file entry to write to.
* @constructor
* @extends {goog.events.EventTarget}
*/
goog.testing.fs.FileWriter = function(fileEntry) {
goog.base(this);
/**
* The file entry to which to write.
* @type {!goog.testing.fs.FileEntry}
* @private
*/
this.fileEntry_ = fileEntry;
/**
* The file blob to write to.
* @type {!goog.testing.fs.File}
* @private
*/
this.file_ = fileEntry.fileSync();
/**
* The current state of the writer.
* @type {goog.fs.FileSaver.ReadyState}
* @private
*/
this.readyState_ = goog.fs.FileSaver.ReadyState.INIT;
};
goog.inherits(goog.testing.fs.FileWriter, goog.events.EventTarget);
/**
* The most recent error experienced by this writer.
* @type {goog.fs.Error}
* @private
*/
goog.testing.fs.FileWriter.prototype.error_;
/**
* Whether the current operation has been aborted.
* @type {boolean}
* @private
*/
goog.testing.fs.FileWriter.prototype.aborted_ = false;
/**
* The current position in the file.
* @type {number}
* @private
*/
goog.testing.fs.FileWriter.prototype.position_ = 0;
/**
* @see {goog.fs.FileSaver#getReadyState}
* @return {goog.fs.FileSaver.ReadyState} The ready state.
*/
goog.testing.fs.FileWriter.prototype.getReadyState = function() {
return this.readyState_;
};
/**
* @see {goog.fs.FileSaver#getError}
* @return {goog.fs.Error} The error.
*/
goog.testing.fs.FileWriter.prototype.getError = function() {
return this.error_;
};
/**
* @see {goog.fs.FileWriter#getPosition}
* @return {number} The position.
*/
goog.testing.fs.FileWriter.prototype.getPosition = function() {
return this.position_;
};
/**
* @see {goog.fs.FileWriter#getLength}
* @return {number} The length.
*/
goog.testing.fs.FileWriter.prototype.getLength = function() {
return this.file_.size;
};
/**
* @see {goog.fs.FileSaver#abort}
*/
goog.testing.fs.FileWriter.prototype.abort = function() {
if (this.readyState_ != goog.fs.FileSaver.ReadyState.WRITING) {
var msg = 'aborting save of ' + this.fileEntry_.getFullPath();
throw new goog.fs.Error(goog.fs.Error.ErrorCode.INVALID_STATE, msg);
}
this.aborted_ = true;
};
/**
* @see {goog.fs.FileWriter#write}
* @param {!goog.testing.fs.Blob} blob The blob to write.
*/
goog.testing.fs.FileWriter.prototype.write = function(blob) {
if (this.readyState_ == goog.fs.FileSaver.ReadyState.WRITING) {
var msg = 'writing to ' + this.fileEntry_.getFullPath();
throw new goog.fs.Error(goog.fs.Error.ErrorCode.INVALID_STATE, msg);
}
this.readyState_ = goog.fs.FileSaver.ReadyState.WRITING;
goog.Timer.callOnce(function() {
if (this.aborted_) {
this.abort_(blob.size);
return;
}
this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_START, 0, blob.size);
var fileString = this.file_.toString();
this.file_.setDataInternal(
fileString.substring(0, this.position_) + blob.toString() +
fileString.substring(this.position_ + blob.size, fileString.length));
this.position_ += blob.size;
this.progressEvent_(
goog.fs.FileSaver.EventType.WRITE, blob.size, blob.size);
this.readyState_ = goog.fs.FileSaver.ReadyState.DONE;
this.progressEvent_(
goog.fs.FileSaver.EventType.WRITE_END, blob.size, blob.size);
}, 0, this);
};
/**
* @see {goog.fs.FileWriter#truncate}
* @param {number} size The size to truncate to.
*/
goog.testing.fs.FileWriter.prototype.truncate = function(size) {
if (this.readyState_ == goog.fs.FileSaver.ReadyState.WRITING) {
var msg = 'truncating ' + this.fileEntry_.getFullPath();
throw new goog.fs.Error(goog.fs.Error.ErrorCode.INVALID_STATE, msg);
}
this.readyState_ = goog.fs.FileSaver.ReadyState.WRITING;
goog.Timer.callOnce(function() {
if (this.aborted_) {
this.abort_(size);
return;
}
this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_START, 0, size);
var fileString = this.file_.toString();
if (size > fileString.length) {
this.file_.setDataInternal(
fileString + goog.string.repeat('\0', size - fileString.length));
} else {
this.file_.setDataInternal(fileString.substring(0, size));
}
this.position_ = Math.min(this.position_, size);
this.progressEvent_(goog.fs.FileSaver.EventType.WRITE, size, size);
this.readyState_ = goog.fs.FileSaver.ReadyState.DONE;
this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_END, size, size);
}, 0, this);
};
/**
* @see {goog.fs.FileWriter#seek}
* @param {number} offset The offset to seek to.
*/
goog.testing.fs.FileWriter.prototype.seek = function(offset) {
if (this.readyState_ == goog.fs.FileSaver.ReadyState.WRITING) {
var msg = 'truncating ' + this.fileEntry_.getFullPath();
throw new goog.fs.Error(goog.fs.Error.ErrorCode.INVALID_STATE, msg);
}
if (offset < 0) {
this.position_ = Math.max(0, this.file_.size + offset);
} else {
this.position_ = Math.min(offset, this.file_.size);
}
};
/**
* Abort the current action and emit appropriate events.
*
* @param {number} total The total data that was to be processed, in bytes.
* @private
*/
goog.testing.fs.FileWriter.prototype.abort_ = function(total) {
this.error_ = new goog.fs.Error(
goog.fs.Error.ErrorCode.ABORT, 'saving ' + this.fileEntry_.getFullPath());
this.progressEvent_(goog.fs.FileSaver.EventType.ERROR, 0, total);
this.progressEvent_(goog.fs.FileSaver.EventType.ABORT, 0, total);
this.readyState_ = goog.fs.FileSaver.ReadyState.DONE;
this.progressEvent_(goog.fs.FileSaver.EventType.WRITE_END, 0, total);
this.aborted_ = false;
};
/**
* Dispatch a progress event.
*
* @param {goog.fs.FileSaver.EventType} type The type of the event.
* @param {number} loaded The number of bytes processed.
* @param {number} total The total data that was to be processed, in bytes.
* @private
*/
goog.testing.fs.FileWriter.prototype.progressEvent_ = function(
type, loaded, total) {
// On write, update the last modified date to the current (real or mock) time.
if (type == goog.fs.FileSaver.EventType.WRITE) {
this.file_.lastModifiedDate = new Date(goog.now());
}
this.dispatchEvent(new goog.testing.fs.ProgressEvent(type, loaded, total));
};

View File

@@ -0,0 +1,147 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock implementations of the Closure HTML5 FileSystem wrapper
* classes. These implementations are designed to be usable in any browser, so
* they use none of the native FileSystem-related objects.
*
*/
goog.provide('goog.testing.fs');
goog.require('goog.Timer');
goog.require('goog.array');
goog.require('goog.async.Deferred');
goog.require('goog.fs');
goog.require('goog.testing.fs.Blob');
goog.require('goog.testing.fs.FileSystem');
/**
* Get a filesystem object. Since these are mocks, there's no difference between
* temporary and persistent filesystems.
*
* @param {number} size Ignored.
* @return {!goog.async.Deferred} The deferred
* {@link goog.testing.fs.FileSystem}.
*/
goog.testing.fs.getTemporary = function(size) {
var d = new goog.async.Deferred();
goog.Timer.callOnce(
goog.bind(d.callback, d, new goog.testing.fs.FileSystem()));
return d;
};
/**
* Get a filesystem object. Since these are mocks, there's no difference between
* temporary and persistent filesystems.
*
* @param {number} size Ignored.
* @return {!goog.async.Deferred} The deferred
* {@link goog.testing.fs.FileSystem}.
*/
goog.testing.fs.getPersistent = function(size) {
return goog.testing.fs.getTemporary(size);
};
/**
* Which object URLs have been granted for fake blobs.
* @type {!Object.<boolean>}
* @private
*/
goog.testing.fs.objectUrls_ = {};
/**
* Create a fake object URL for a given fake blob. This can be used as a real
* URL, and it can be created and revoked normally.
*
* @param {!goog.testing.fs.Blob} blob The blob for which to create the URL.
* @return {string} The URL.
*/
goog.testing.fs.createObjectUrl = function(blob) {
var url = blob.toDataUrl();
goog.testing.fs.objectUrls_[url] = true;
return url;
};
/**
* Remove a URL that was created for a fake blob.
*
* @param {string} url The URL to revoke.
*/
goog.testing.fs.revokeObjectUrl = function(url) {
delete goog.testing.fs.objectUrls_[url];
};
/**
* Return whether or not a URL has been granted for the given blob.
*
* @param {!goog.testing.fs.Blob} blob The blob to check.
* @return {boolean} Whether a URL has been granted.
*/
goog.testing.fs.isObjectUrlGranted = function(blob) {
return (blob.toDataUrl()) in goog.testing.fs.objectUrls_;
};
/**
* Concatenates one or more values together and converts them to a fake blob.
*
* @param {...(string|!goog.testing.fs.Blob)} var_args The values that will make
* up the resulting blob.
* @return {!goog.testing.fs.Blob} The blob.
*/
goog.testing.fs.getBlob = function(var_args) {
return new goog.testing.fs.Blob(goog.array.map(arguments, String).join(''));
};
/**
* Returns the string value of a fake blob.
*
* @param {!goog.testing.fs.Blob} blob The blob to convert to a string.
* @param {string=} opt_encoding Ignored.
* @return {!goog.async.Deferred} The deferred string value of the blob.
*/
goog.testing.fs.blobToString = function(blob, opt_encoding) {
var d = new goog.async.Deferred();
goog.Timer.callOnce(goog.bind(d.callback, d, blob.toString()));
return d;
};
/**
* Installs goog.testing.fs in place of the standard goog.fs. After calling
* this, code that uses goog.fs should work without issue using goog.testing.fs.
*
* @param {!goog.testing.PropertyReplacer} stubs The property replacer for
* stubbing out the original goog.fs functions.
*/
goog.testing.fs.install = function(stubs) {
// Prevent warnings that goog.fs may get optimized away. It's true this is
// unsafe in compiled code, but it's only meant for tests.
var fs = goog.getObjectByName('goog.fs');
stubs.replace(fs, 'getTemporary', goog.testing.fs.getTemporary);
stubs.replace(fs, 'getPersistent', goog.testing.fs.getPersistent);
stubs.replace(fs, 'createObjectUrl', goog.testing.fs.createObjectUrl);
stubs.replace(fs, 'revokeObjectUrl', goog.testing.fs.revokeObjectUrl);
stubs.replace(fs, 'getBlob', goog.testing.fs.getBlob);
stubs.replace(fs, 'blobToString', goog.testing.fs.blobToString);
};

View File

@@ -0,0 +1,81 @@
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Mock ProgressEvent object.
*
*/
goog.provide('goog.testing.fs.ProgressEvent');
goog.require('goog.events.Event');
/**
* A mock progress event.
*
* @param {!goog.fs.FileSaver.EventType|!goog.fs.FileReader.EventType} type
* Event type.
* @param {number} loaded The number of bytes processed.
* @param {number} total The total data that was to be processed, in bytes.
* @constructor
* @extends {goog.events.Event}
*/
goog.testing.fs.ProgressEvent = function(type, loaded, total) {
goog.base(this, type);
/**
* The number of bytes processed.
* @type {number}
* @private
*/
this.loaded_ = loaded;
/**
* The total data that was to be procesed, in bytes.
* @type {number}
* @private
*/
this.total_ = total;
};
goog.inherits(goog.testing.fs.ProgressEvent, goog.events.Event);
/**
* @see {goog.fs.ProgressEvent#isLengthComputable}
* @return {boolean} True if the length is known.
*/
goog.testing.fs.ProgressEvent.prototype.isLengthComputable = function() {
return true;
};
/**
* @see {goog.fs.ProgressEvent#getLoaded}
* @return {number} The number of bytes loaded or written.
*/
goog.testing.fs.ProgressEvent.prototype.getLoaded = function() {
return this.loaded_;
};
/**
* @see {goog.fs.ProgressEvent#getTotal}
* @return {number} The total bytes to load or write.
*/
goog.testing.fs.ProgressEvent.prototype.getTotal = function() {
return this.total_;
};