Adding mapbox-gl branch
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
// 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;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a blob with bytes of a blob ranging from the optional start
|
||||
* parameter up to but not including the optional end parameter, and with a type
|
||||
* attribute that is the value of the optional contentType parameter.
|
||||
* @see http://www.w3.org/TR/FileAPI/#dfn-slice
|
||||
* @param {number=} opt_start The start byte offset.
|
||||
* @param {number=} opt_end The end point of a slice.
|
||||
* @param {string=} opt_contentType The type of the resulting Blob.
|
||||
* @return {!goog.testing.fs.Blob} The result blob of the slice operation.
|
||||
*/
|
||||
goog.testing.fs.Blob.prototype.slice = function(
|
||||
opt_start, opt_end, opt_contentType) {
|
||||
var relativeStart;
|
||||
if (goog.isNumber(opt_start)) {
|
||||
relativeStart = (opt_start < 0) ?
|
||||
Math.max(this.data_.length + opt_start, 0) :
|
||||
Math.min(opt_start, this.data_.length);
|
||||
} else {
|
||||
relativeStart = 0;
|
||||
}
|
||||
var relativeEnd;
|
||||
if (goog.isNumber(opt_end)) {
|
||||
relativeEnd = (opt_end < 0) ?
|
||||
Math.max(this.data_.length + opt_end, 0) :
|
||||
Math.min(opt_end, this.data_.length);
|
||||
} else {
|
||||
relativeEnd = this.data_.length;
|
||||
}
|
||||
var span = Math.max(relativeEnd - relativeStart, 0);
|
||||
return new goog.testing.fs.Blob(
|
||||
this.data_.substr(relativeStart, span),
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs.Blob
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fs.BlobTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.BlobTest');
|
||||
goog.setTestOnly('goog.testing.fs.BlobTest');
|
||||
|
||||
goog.require('goog.testing.fs.Blob');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
function testAttributes() {
|
||||
var blob = new goog.testing.fs.Blob();
|
||||
assertEquals(0, blob.size);
|
||||
assertEquals('', blob.type);
|
||||
|
||||
blob = new goog.testing.fs.Blob('foo bar baz');
|
||||
assertEquals(11, blob.size);
|
||||
assertEquals('', blob.type);
|
||||
|
||||
blob = new goog.testing.fs.Blob('foo bar baz', 'text/plain');
|
||||
assertEquals(11, blob.size);
|
||||
assertEquals('text/plain', blob.type);
|
||||
}
|
||||
|
||||
function testToString() {
|
||||
assertEquals('', new goog.testing.fs.Blob().toString());
|
||||
assertEquals('foo bar', new goog.testing.fs.Blob('foo bar').toString());
|
||||
}
|
||||
|
||||
function testSlice() {
|
||||
var blob = new goog.testing.fs.Blob('abcdef');
|
||||
assertEquals('bc', blob.slice(1, 3).toString());
|
||||
assertEquals('def', blob.slice(3, 10).toString());
|
||||
assertEquals('abcd', blob.slice(0, -2).toString());
|
||||
assertEquals('', blob.slice(10, 1).toString());
|
||||
assertEquals('b', blob.slice(-5, 2).toString());
|
||||
|
||||
assertEquals('abcdef', blob.slice().toString());
|
||||
assertEquals('abc', blob.slice(/* opt_start */ undefined, 3).toString());
|
||||
assertEquals('def', blob.slice(3).toString());
|
||||
|
||||
assertEquals('text/plain', blob.slice(1, 2, 'text/plain').type);
|
||||
}
|
||||
|
||||
function testSetDataInternal() {
|
||||
var blob = new goog.testing.fs.Blob();
|
||||
|
||||
blob.setDataInternal('asdf');
|
||||
assertEquals('asdf', blob.toString());
|
||||
assertEquals(4, blob.size);
|
||||
|
||||
blob.setDataInternal('');
|
||||
assertEquals('', blob.toString());
|
||||
assertEquals(0, blob.size);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs.DirectoryEntry
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fs.DirectoryEntryTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,319 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.DirectoryEntryTest');
|
||||
goog.setTestOnly('goog.testing.fs.DirectoryEntryTest');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.fs.DirectoryEntry');
|
||||
goog.require('goog.fs.Error');
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.fs.FileSystem');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
var fs, dir, mockClock;
|
||||
|
||||
function setUp() {
|
||||
mockClock = new goog.testing.MockClock(true);
|
||||
|
||||
fs = new goog.testing.fs.FileSystem();
|
||||
dir = fs.getRoot().createDirectorySync('foo');
|
||||
dir.createDirectorySync('subdir').createFileSync('subfile');
|
||||
dir.createFileSync('file');
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
mockClock.uninstall();
|
||||
}
|
||||
|
||||
function testIsFile() {
|
||||
assertFalse(dir.isFile());
|
||||
}
|
||||
|
||||
function testIsDirectory() {
|
||||
assertTrue(dir.isDirectory());
|
||||
}
|
||||
|
||||
function testRemoveWithChildren() {
|
||||
dir.getFileSync('bar', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
expectError(dir.remove(), goog.fs.Error.ErrorCode.INVALID_MODIFICATION);
|
||||
}
|
||||
|
||||
function testRemoveWithoutChildren() {
|
||||
var emptyDir = dir.getDirectorySync(
|
||||
'empty', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
emptyDir.remove().
|
||||
addCallback(function() {
|
||||
assertTrue(emptyDir.deleted);
|
||||
assertFalse(fs.getRoot().hasChild('empty'));
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file removal');
|
||||
}
|
||||
|
||||
function testRemoveRootRecursively() {
|
||||
var root = fs.getRoot();
|
||||
root.removeRecursively().addCallback(function() {
|
||||
assertTrue(dir.deleted);
|
||||
assertFalse(fs.getRoot().deleted);
|
||||
})
|
||||
.addBoth(continueTesting);
|
||||
waitForAsync('waiting for testRemoveRoot');
|
||||
}
|
||||
|
||||
function testGetFile() {
|
||||
// Advance the clock by an arbitrary but known amount.
|
||||
mockClock.tick(41);
|
||||
dir.getFile('file').
|
||||
addCallback(function(file) {
|
||||
assertEquals(dir.getFileSync('file'), file);
|
||||
assertEquals('file', file.getName());
|
||||
assertEquals('/foo/file', file.getFullPath());
|
||||
assertTrue(file.isFile());
|
||||
|
||||
return dir.getLastModified();
|
||||
}).
|
||||
addCallback(function(date) {
|
||||
assertEquals('Reading a file should not update the modification date.',
|
||||
0, date.getTime());
|
||||
return dir.getMetadata();
|
||||
}).
|
||||
addCallback(function(metadata) {
|
||||
assertEquals('Reading a file should not update the metadata.',
|
||||
0, metadata.modificationTime.getTime());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file');
|
||||
}
|
||||
|
||||
function testGetFileFromSubdir() {
|
||||
dir.getFile('subdir/subfile').addCallback(function(file) {
|
||||
assertEquals(dir.getDirectorySync('subdir').getFileSync('subfile'), file);
|
||||
assertEquals('subfile', file.getName());
|
||||
assertEquals('/foo/subdir/subfile', file.getFullPath());
|
||||
assertTrue(file.isFile());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file');
|
||||
}
|
||||
|
||||
function testGetAbsolutePaths() {
|
||||
fs.getRoot().getFile('/foo/subdir/subfile').
|
||||
addCallback(function(subfile) {
|
||||
assertEquals('/foo/subdir/subfile', subfile.getFullPath());
|
||||
return fs.getRoot().getDirectory('//foo////');
|
||||
}).
|
||||
addCallback(function(foo) {
|
||||
assertEquals('/foo', foo.getFullPath());
|
||||
return foo.getDirectory('/');
|
||||
}).
|
||||
addCallback(function(root) {
|
||||
assertEquals('/', root.getFullPath());
|
||||
return root.getDirectory('/////');
|
||||
}).
|
||||
addCallback(function(root) {
|
||||
assertEquals('/', root.getFullPath());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testGetAbsolutePaths');
|
||||
}
|
||||
|
||||
function testCreateFile() {
|
||||
mockClock.tick(43);
|
||||
dir.getLastModified().
|
||||
addCallback(function(date) { assertEquals(0, date.getTime()); }).
|
||||
addCallback(function() {
|
||||
return dir.getFile('bar', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
}).
|
||||
addCallback(function(file) {
|
||||
mockClock.tick();
|
||||
assertEquals('bar', file.getName());
|
||||
assertEquals('/foo/bar', file.getFullPath());
|
||||
assertEquals(dir, file.parent);
|
||||
assertTrue(file.isFile());
|
||||
|
||||
return dir.getLastModified();
|
||||
}).
|
||||
addCallback(function(date) {
|
||||
assertEquals(43, date.getTime());
|
||||
return dir.getMetadata();
|
||||
}).
|
||||
addCallback(function(metadata) {
|
||||
assertEquals(43, metadata.modificationTime.getTime());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file creation');
|
||||
}
|
||||
|
||||
function testCreateFileThatAlreadyExists() {
|
||||
mockClock.tick(47);
|
||||
var existingFile = dir.getFileSync('file');
|
||||
dir.getFile('file', goog.fs.DirectoryEntry.Behavior.CREATE).
|
||||
addCallback(function(file) {
|
||||
mockClock.tick();
|
||||
assertEquals('file', file.getName());
|
||||
assertEquals('/foo/file', file.getFullPath());
|
||||
assertEquals(dir, file.parent);
|
||||
assertEquals(existingFile, file);
|
||||
assertTrue(file.isFile());
|
||||
|
||||
return dir.getLastModified();
|
||||
}).
|
||||
addCallback(function(date) {
|
||||
assertEquals(47, date.getTime());
|
||||
return dir.getMetadata();
|
||||
}).
|
||||
addCallback(function(metadata) {
|
||||
assertEquals(47, metadata.modificationTime.getTime());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file creation');
|
||||
}
|
||||
|
||||
function testCreateFileInSubdir() {
|
||||
dir.getFile('subdir/bar', goog.fs.DirectoryEntry.Behavior.CREATE).
|
||||
addCallback(function(file) {
|
||||
assertEquals('bar', file.getName());
|
||||
assertEquals('/foo/subdir/bar', file.getFullPath());
|
||||
assertEquals(dir.getDirectorySync('subdir'), file.parent);
|
||||
assertTrue(file.isFile());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file creation');
|
||||
}
|
||||
|
||||
function testCreateFileExclusive() {
|
||||
dir.getFile('bar', goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE).
|
||||
addCallback(function(file) {
|
||||
assertEquals('bar', file.getName());
|
||||
assertEquals('/foo/bar', file.getFullPath());
|
||||
assertEquals(dir, file.parent);
|
||||
assertTrue(file.isFile());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('waiting for file creation');
|
||||
}
|
||||
|
||||
function testGetNonExistentFile() {
|
||||
expectError(dir.getFile('bar'), goog.fs.Error.ErrorCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
function testGetNonExistentFileInSubdir() {
|
||||
expectError(dir.getFile('subdir/bar'), goog.fs.Error.ErrorCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
function testGetFileInNonExistentSubdir() {
|
||||
expectError(dir.getFile('bar/subfile'), goog.fs.Error.ErrorCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
function testGetFileThatsActuallyADirectory() {
|
||||
expectError(dir.getFile('subdir'), goog.fs.Error.ErrorCode.TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
function testCreateFileInNonExistentSubdir() {
|
||||
expectError(
|
||||
dir.getFile('bar/newfile', goog.fs.DirectoryEntry.Behavior.CREATE),
|
||||
goog.fs.Error.ErrorCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
function testCreateFileThatsActuallyADirectory() {
|
||||
expectError(
|
||||
dir.getFile('subdir', goog.fs.DirectoryEntry.Behavior.CREATE),
|
||||
goog.fs.Error.ErrorCode.TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
function testCreateExclusiveExistingFile() {
|
||||
expectError(
|
||||
dir.getFile('file', goog.fs.DirectoryEntry.Behavior.CREATE_EXCLUSIVE),
|
||||
goog.fs.Error.ErrorCode.INVALID_MODIFICATION);
|
||||
}
|
||||
|
||||
function testListEmptyDirectory() {
|
||||
var emptyDir = fs.getRoot().
|
||||
getDirectorySync('empty', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
|
||||
emptyDir.listDirectory().
|
||||
addCallback(function(entryList) {
|
||||
assertSameElements([], entryList);
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testListEmptyDirectory');
|
||||
}
|
||||
|
||||
function testListDirectory() {
|
||||
var root = fs.getRoot();
|
||||
root.getDirectorySync('dir1', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
root.getDirectorySync('dir2', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
root.getFileSync('file1', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
root.getFileSync('file2', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
|
||||
fs.getRoot().listDirectory().
|
||||
addCallback(function(entryList) {
|
||||
assertSameElements([
|
||||
'dir1',
|
||||
'dir2',
|
||||
'file1',
|
||||
'file2',
|
||||
'foo'
|
||||
],
|
||||
goog.array.map(entryList, function(entry) {
|
||||
return entry.getName();
|
||||
}));
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testListDirectory');
|
||||
}
|
||||
|
||||
function testCreatePath() {
|
||||
dir.createPath('baz/bat').
|
||||
addCallback(function(batDir) {
|
||||
assertEquals('/foo/baz/bat', batDir.getFullPath());
|
||||
return batDir.createPath('../zazzle');
|
||||
}).
|
||||
addCallback(function(zazzleDir) {
|
||||
assertEquals('/foo/baz/zazzle', zazzleDir.getFullPath());
|
||||
return zazzleDir.createPath('/elements/actinides/neptunium/');
|
||||
}).
|
||||
addCallback(function(elDir) {
|
||||
assertEquals('/elements/actinides/neptunium', elDir.getFullPath());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testCreatePath');
|
||||
}
|
||||
|
||||
|
||||
function continueTesting(result) {
|
||||
asyncTestCase.continueTesting();
|
||||
if (result instanceof Error) {
|
||||
throw result;
|
||||
}
|
||||
mockClock.tick();
|
||||
}
|
||||
|
||||
function expectError(deferred, code) {
|
||||
deferred.
|
||||
addCallback(function() { fail('Expected an error'); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(code, err.code);
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for error');
|
||||
}
|
||||
|
||||
function waitForAsync(msg) {
|
||||
asyncTestCase.waitForAsync(msg);
|
||||
mockClock.tick();
|
||||
}
|
||||
@@ -0,0 +1,637 @@
|
||||
// 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 : '');
|
||||
var self = this;
|
||||
return this.checkNotDeleted(msg).addCallback(function() {
|
||||
var name = opt_newName || self.getName();
|
||||
var entry = self.clone();
|
||||
parent.children[name] = entry;
|
||||
parent.lastModifiedTimestamp_ = goog.now();
|
||||
entry.name_ = name;
|
||||
entry.parent = /** @type {!goog.testing.fs.DirectoryEntry} */ (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();
|
||||
var self = this;
|
||||
return this.checkNotDeleted(msg).addCallback(function() {
|
||||
delete this.parent.children[self.getName()];
|
||||
self.parent.lastModifiedTimestamp_ = goog.now();
|
||||
self.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) {
|
||||
var err = new goog.fs.Error(
|
||||
/** @type {!FileError} */ ({'name': 'NotFoundError'}),
|
||||
action);
|
||||
d.errback(err);
|
||||
} 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}
|
||||
* @final
|
||||
*/
|
||||
goog.testing.fs.DirectoryEntry = function(fs, parent, name, children) {
|
||||
goog.testing.fs.DirectoryEntry.base(
|
||||
this, 'constructor', 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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidModificationError'}),
|
||||
'removing ' + this.getFullPath()));
|
||||
}, 0, this);
|
||||
return d;
|
||||
} else if (this != this.getFileSystem().getRoot()) {
|
||||
return goog.testing.fs.DirectoryEntry.base(this, 'remove');
|
||||
} else {
|
||||
// Root directory, do nothing.
|
||||
return goog.async.Deferred.succeed();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @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.
|
||||
* @param {string=} opt_data The string data encapsulated by the blob.
|
||||
* @param {string=} opt_type The mime type of the blob.
|
||||
* @return {!goog.testing.fs.FileEntry} The loaded file.
|
||||
*/
|
||||
goog.testing.fs.DirectoryEntry.prototype.getFileSync = function(
|
||||
path, opt_behavior, opt_data, opt_type) {
|
||||
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,
|
||||
goog.isDef(opt_data) ? opt_data : '', opt_type);
|
||||
}, 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(
|
||||
/** @type {!FileError} */ ({'name': 'NotFoundError'}),
|
||||
'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(
|
||||
/** @type {!FileError} */ ({'name': 'NotFoundError'}),
|
||||
'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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidModificationError'}),
|
||||
'loading ' + path + ' from ' + this.getFullPath());
|
||||
} else if (entry.isFile() != isFile) {
|
||||
throw new goog.fs.Error(
|
||||
/** @type {!FileError} */ ({'name': 'TypeMismatchError'}),
|
||||
'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.
|
||||
* @param {string=} opt_type The mime type of the blob.
|
||||
* @constructor
|
||||
* @extends {goog.testing.fs.Entry}
|
||||
* @implements {goog.fs.FileEntry}
|
||||
* @final
|
||||
*/
|
||||
goog.testing.fs.FileEntry = function(fs, parent, name, data, opt_type) {
|
||||
goog.testing.fs.FileEntry.base(this, 'constructor', 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, opt_type);
|
||||
|
||||
/**
|
||||
* 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_;
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs.Entry
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fs.EntryTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,222 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.EntryTest');
|
||||
goog.setTestOnly('goog.testing.fs.EntryTest');
|
||||
|
||||
goog.require('goog.fs.DirectoryEntry');
|
||||
goog.require('goog.fs.Error');
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.fs.FileSystem');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
var fs, file, mockClock;
|
||||
|
||||
function setUp() {
|
||||
mockClock = new goog.testing.MockClock(true);
|
||||
|
||||
fs = new goog.testing.fs.FileSystem();
|
||||
file = fs.getRoot().
|
||||
getDirectorySync('foo', goog.fs.DirectoryEntry.Behavior.CREATE).
|
||||
getFileSync('bar', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
mockClock.uninstall();
|
||||
}
|
||||
|
||||
function testGetName() {
|
||||
assertEquals('bar', file.getName());
|
||||
}
|
||||
|
||||
function testGetFullPath() {
|
||||
assertEquals('/foo/bar', file.getFullPath());
|
||||
assertEquals('/', fs.getRoot().getFullPath());
|
||||
}
|
||||
|
||||
function testGetFileSystem() {
|
||||
assertEquals(fs, file.getFileSystem());
|
||||
}
|
||||
|
||||
function testMoveTo() {
|
||||
file.moveTo(fs.getRoot()).addCallback(function(newFile) {
|
||||
assertTrue(file.deleted);
|
||||
assertFalse(newFile.deleted);
|
||||
assertEquals('/bar', newFile.getFullPath());
|
||||
assertEquals(fs.getRoot(), newFile.parent);
|
||||
assertEquals(newFile, fs.getRoot().getFileSync('bar'));
|
||||
assertFalse(fs.getRoot().getDirectorySync('foo').hasChild('bar'));
|
||||
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file move');
|
||||
}
|
||||
|
||||
function testMoveToNewName() {
|
||||
// Advance the clock to an arbitrary, known time.
|
||||
mockClock.tick(71);
|
||||
file.moveTo(fs.getRoot(), 'baz').
|
||||
addCallback(function(newFile) {
|
||||
mockClock.tick();
|
||||
assertTrue(file.deleted);
|
||||
assertFalse(newFile.deleted);
|
||||
assertEquals('/baz', newFile.getFullPath());
|
||||
assertEquals(fs.getRoot(), newFile.parent);
|
||||
assertEquals(newFile, fs.getRoot().getFileSync('baz'));
|
||||
|
||||
var oldParentDir = fs.getRoot().getDirectorySync('foo');
|
||||
assertFalse(oldParentDir.hasChild('bar'));
|
||||
assertFalse(oldParentDir.hasChild('baz'));
|
||||
|
||||
return oldParentDir.getLastModified();
|
||||
}).
|
||||
addCallback(function(lastModifiedDate) {
|
||||
assertEquals(71, lastModifiedDate.getTime());
|
||||
var oldParentDir = fs.getRoot().getDirectorySync('foo');
|
||||
return oldParentDir.getMetadata();
|
||||
}).
|
||||
addCallback(function(metadata) {
|
||||
assertEquals(71, metadata.modificationTime.getTime());
|
||||
return fs.getRoot().getLastModified();
|
||||
}).
|
||||
addCallback(function(rootLastModifiedDate) {
|
||||
assertEquals(71, rootLastModifiedDate.getTime());
|
||||
return fs.getRoot().getMetadata();
|
||||
}).
|
||||
addCallback(function(rootMetadata) {
|
||||
assertEquals(71, rootMetadata.modificationTime.getTime());
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file move');
|
||||
}
|
||||
|
||||
function testMoveDeletedFile() {
|
||||
assertFailsWhenDeleted(function() { return file.moveTo(fs.getRoot()); });
|
||||
}
|
||||
|
||||
function testCopyTo() {
|
||||
mockClock.tick(61);
|
||||
file.copyTo(fs.getRoot()).
|
||||
addCallback(function(newFile) {
|
||||
assertFalse(file.deleted);
|
||||
assertFalse(newFile.deleted);
|
||||
assertEquals('/bar', newFile.getFullPath());
|
||||
assertEquals(fs.getRoot(), newFile.parent);
|
||||
assertEquals(newFile, fs.getRoot().getFileSync('bar'));
|
||||
|
||||
var oldParentDir = fs.getRoot().getDirectorySync('foo');
|
||||
assertEquals(file, oldParentDir.getFileSync('bar'));
|
||||
return oldParentDir.getLastModified();
|
||||
}).
|
||||
addCallback(function(lastModifiedDate) {
|
||||
assertEquals('The original parent directory was not modified.',
|
||||
0, lastModifiedDate.getTime());
|
||||
var oldParentDir = fs.getRoot().getDirectorySync('foo');
|
||||
return oldParentDir.getMetadata();
|
||||
}).
|
||||
addCallback(function(metadata) {
|
||||
assertEquals('The original parent directory was not modified.',
|
||||
0, metadata.modificationTime.getTime());
|
||||
return fs.getRoot().getLastModified();
|
||||
}).
|
||||
addCallback(function(rootLastModifiedDate) {
|
||||
assertEquals(61, rootLastModifiedDate.getTime());
|
||||
return fs.getRoot().getMetadata();
|
||||
}).
|
||||
addCallback(function(rootMetadata) {
|
||||
assertEquals(61, rootMetadata.modificationTime.getTime());
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file copy');
|
||||
}
|
||||
|
||||
function testCopyToNewName() {
|
||||
file.copyTo(fs.getRoot(), 'baz').addCallback(function(newFile) {
|
||||
assertFalse(file.deleted);
|
||||
assertFalse(newFile.deleted);
|
||||
assertEquals('/baz', newFile.getFullPath());
|
||||
assertEquals(fs.getRoot(), newFile.parent);
|
||||
assertEquals(newFile, fs.getRoot().getFileSync('baz'));
|
||||
assertEquals(file, fs.getRoot().getDirectorySync('foo').getFileSync('bar'));
|
||||
assertFalse(fs.getRoot().getDirectorySync('foo').hasChild('baz'));
|
||||
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file copy');
|
||||
}
|
||||
|
||||
function testCopyDeletedFile() {
|
||||
assertFailsWhenDeleted(function() { return file.copyTo(fs.getRoot()); });
|
||||
}
|
||||
|
||||
function testRemove() {
|
||||
mockClock.tick(57);
|
||||
file.remove().
|
||||
addCallback(function() {
|
||||
mockClock.tick();
|
||||
var parentDir = fs.getRoot().getDirectorySync('foo');
|
||||
|
||||
assertTrue(file.deleted);
|
||||
assertFalse(parentDir.hasChild('bar'));
|
||||
|
||||
return parentDir.getLastModified();
|
||||
}).
|
||||
addCallback(function(date) {
|
||||
assertEquals(57, date.getTime());
|
||||
var parentDir = fs.getRoot().getDirectorySync('foo');
|
||||
return parentDir.getMetadata();
|
||||
}).
|
||||
addCallback(function(metadata) {
|
||||
assertEquals(57, metadata.modificationTime.getTime());
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file removal');
|
||||
}
|
||||
|
||||
function testRemoveDeletedFile() {
|
||||
assertFailsWhenDeleted(function() { return file.remove(); });
|
||||
}
|
||||
|
||||
function testGetParent() {
|
||||
file.getParent().addCallback(function(p) {
|
||||
assertEquals(file.parent, p);
|
||||
assertEquals(fs.getRoot().getDirectorySync('foo'), p);
|
||||
assertEquals('/foo', p.getFullPath());
|
||||
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file parent');
|
||||
}
|
||||
|
||||
function testGetDeletedFileParent() {
|
||||
assertFailsWhenDeleted(function() { return file.getParent(); });
|
||||
}
|
||||
|
||||
|
||||
function assertFailsWhenDeleted(fn) {
|
||||
file.remove().addCallback(fn).
|
||||
addCallback(function() { fail('Expected an error'); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.NOT_FOUND, err.code);
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('waiting for file operation');
|
||||
}
|
||||
|
||||
function waitForAsync(msg) {
|
||||
asyncTestCase.waitForAsync(msg);
|
||||
mockClock.tick();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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}
|
||||
* @final
|
||||
*/
|
||||
goog.testing.fs.File = function(name, opt_lastModified, opt_data, opt_type) {
|
||||
goog.testing.fs.File.base(this, 'constructor', 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);
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs.FileEntry
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fs.FileEntryTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,88 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.FileEntryTest');
|
||||
goog.setTestOnly('goog.testing.fs.FileEntryTest');
|
||||
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.fs.FileEntry');
|
||||
goog.require('goog.testing.fs.FileSystem');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
var fs, file, fileEntry, mockClock, currentTime;
|
||||
|
||||
function setUp() {
|
||||
mockClock = new goog.testing.MockClock(true);
|
||||
|
||||
fs = new goog.testing.fs.FileSystem();
|
||||
fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar');
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
mockClock.uninstall();
|
||||
}
|
||||
|
||||
function testIsFile() {
|
||||
assertTrue(fileEntry.isFile());
|
||||
}
|
||||
|
||||
function testIsDirectory() {
|
||||
assertFalse(fileEntry.isDirectory());
|
||||
}
|
||||
|
||||
function testFile() {
|
||||
var testFile = new goog.testing.fs.FileEntry(fs, fs.getRoot(),
|
||||
'test', 'hello world');
|
||||
testFile.file().addCallback(function(f) {
|
||||
assertEquals('test', f.name);
|
||||
assertEquals('hello world', f.toString());
|
||||
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('testFile');
|
||||
}
|
||||
|
||||
function testGetLastModified() {
|
||||
// Advance the clock to a known time.
|
||||
mockClock.tick(53);
|
||||
var testFile = new goog.testing.fs.FileEntry(fs, fs.getRoot(),
|
||||
'timeTest', 'hello world');
|
||||
mockClock.tick();
|
||||
testFile.getLastModified().addCallback(function(date) {
|
||||
assertEquals(53, date.getTime());
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('testGetLastModified');
|
||||
}
|
||||
|
||||
function testGetMetadata() {
|
||||
// Advance the clock to a known time.
|
||||
mockClock.tick(54);
|
||||
var testFile = new goog.testing.fs.FileEntry(fs, fs.getRoot(),
|
||||
'timeTest', 'hello world');
|
||||
mockClock.tick();
|
||||
testFile.getMetadata().addCallback(function(metadata) {
|
||||
assertEquals(54, metadata.modificationTime.getTime());
|
||||
asyncTestCase.continueTesting();
|
||||
});
|
||||
waitForAsync('testGetMetadata');
|
||||
}
|
||||
|
||||
|
||||
function waitForAsync(msg) {
|
||||
asyncTestCase.waitForAsync(msg);
|
||||
mockClock.tick();
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
// 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');
|
||||
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.testing.fs.FileReader.base(this, 'constructor');
|
||||
|
||||
/**
|
||||
* 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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidStateError'}),
|
||||
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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidStateError'}),
|
||||
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(
|
||||
/** @type {!FileError} */ ({'name': 'AbortError'}),
|
||||
'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));
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs.FileReader
|
||||
</title>
|
||||
<script type="text/javascript" src="../../base.js">
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
goog.require('goog.testing.fs.FileReaderTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,234 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.FileReaderTest');
|
||||
goog.setTestOnly('goog.testing.fs.FileReaderTest');
|
||||
|
||||
goog.require('goog.Timer');
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.fs.Error');
|
||||
goog.require('goog.fs.FileReader');
|
||||
goog.require('goog.fs.FileSaver');
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.fs.FileReader');
|
||||
goog.require('goog.testing.fs.FileSystem');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
var file, deferredReader;
|
||||
var hasArrayBuffer = goog.isDef(goog.global.ArrayBuffer);
|
||||
|
||||
function setUp() {
|
||||
var fs = new goog.testing.fs.FileSystem();
|
||||
var fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar');
|
||||
file = fileEntry.fileSync();
|
||||
file.setDataInternal('test content');
|
||||
|
||||
deferredReader = new goog.async.Deferred();
|
||||
goog.Timer.callOnce(
|
||||
goog.bind(deferredReader.callback, deferredReader,
|
||||
new goog.testing.fs.FileReader()));
|
||||
}
|
||||
|
||||
function testRead() {
|
||||
deferredReader.
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.INIT)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(readAsText)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.LOADING)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_START)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_END)).
|
||||
addCallback(goog.partial(checkResult, file.toString())).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.DONE)).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testRead');
|
||||
}
|
||||
|
||||
function testReadAsArrayBuffer() {
|
||||
if (!hasArrayBuffer) {
|
||||
// Skip if array buffer is not supported
|
||||
return;
|
||||
}
|
||||
deferredReader.
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.INIT)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(readAsArrayBuffer)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.LOADING)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_START)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_END)).
|
||||
addCallback(goog.partial(checkResult, file.toArrayBuffer())).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.DONE)).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testReadAsArrayBuffer');
|
||||
}
|
||||
|
||||
function testReadAsDataUrl() {
|
||||
deferredReader.
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.INIT)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(readAsDataUrl)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.LOADING)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_START)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_END)).
|
||||
addCallback(goog.partial(checkResult, file.toDataUrl())).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.DONE)).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testReadAsDataUrl');
|
||||
}
|
||||
|
||||
function testAbort() {
|
||||
deferredReader.
|
||||
addCallback(goog.partial(readAsText)).
|
||||
addCallback(function(reader) { reader.abort(); }).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.LOADING)).
|
||||
addCallback(goog.partial(waitForError, goog.fs.Error.ErrorCode.ABORT)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.LOADING)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.ABORT)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.LOADING)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileReader.EventType.LOAD_END)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileReader.ReadyState.DONE)).
|
||||
addCallback(goog.partial(checkResult, undefined)).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testAbort');
|
||||
}
|
||||
|
||||
function testAbortBeforeRead() {
|
||||
deferredReader.
|
||||
addCallback(function(reader) { reader.abort(); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(function(calledErrback) {
|
||||
assertTrue(calledErrback);
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testAbortBeforeRead');
|
||||
}
|
||||
|
||||
function testReadDuringRead() {
|
||||
deferredReader.
|
||||
addCallback(goog.partial(readAsText)).
|
||||
addCallback(goog.partial(readAsText)).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(assertTrue).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testReadDuringRead');
|
||||
}
|
||||
|
||||
function continueTesting(result) {
|
||||
asyncTestCase.continueTesting();
|
||||
if (result instanceof Error) {
|
||||
throw result;
|
||||
}
|
||||
}
|
||||
|
||||
function waitForAsync(msg) {
|
||||
asyncTestCase.waitForAsync(msg);
|
||||
}
|
||||
|
||||
function waitForEvent(type, target) {
|
||||
var d = new goog.async.Deferred();
|
||||
goog.events.listenOnce(target, type, goog.bind(d.callback, d, target));
|
||||
return d;
|
||||
}
|
||||
|
||||
function waitForError(type, target) {
|
||||
var d = new goog.async.Deferred();
|
||||
goog.events.listenOnce(
|
||||
target, goog.fs.FileReader.EventType.ERROR, function(e) {
|
||||
assertEquals(type, target.getError().code);
|
||||
d.callback(target);
|
||||
});
|
||||
return d;
|
||||
}
|
||||
|
||||
function readAsText(reader) {
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
function readAsArrayBuffer(reader) {
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
function readAsDataUrl(reader) {
|
||||
reader.readAsDataUrl(file);
|
||||
}
|
||||
|
||||
function readAndWait(reader) {
|
||||
readAsText(reader);
|
||||
return waitForEvent(goog.fs.FileSaver.EventType.LOAD_END, reader);
|
||||
}
|
||||
|
||||
function checkResult(expectedResult, reader) {
|
||||
checkEquals(expectedResult, reader.getResult());
|
||||
}
|
||||
|
||||
function checkEquals(a, b) {
|
||||
if (hasArrayBuffer &&
|
||||
a instanceof ArrayBuffer && b instanceof ArrayBuffer) {
|
||||
assertEquals(a.byteLength, b.byteLength);
|
||||
var viewA = new Uint8Array(a);
|
||||
var viewB = new Uint8Array(b);
|
||||
for (var i = 0; i < a.byteLength; i++) {
|
||||
assertEquals(viewA[i], viewB[i]);
|
||||
}
|
||||
} else {
|
||||
assertEquals(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
function checkReadyState(expectedState, reader) {
|
||||
assertEquals(expectedState, reader.getReadyState());
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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}
|
||||
* @final
|
||||
*/
|
||||
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_;
|
||||
};
|
||||
@@ -0,0 +1,268 @@
|
||||
// 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.EventTarget');
|
||||
goog.require('goog.fs.Error');
|
||||
goog.require('goog.fs.FileSaver');
|
||||
goog.require('goog.string');
|
||||
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}
|
||||
* @final
|
||||
*/
|
||||
goog.testing.fs.FileWriter = function(fileEntry) {
|
||||
goog.testing.fs.FileWriter.base(this, 'constructor');
|
||||
|
||||
/**
|
||||
* 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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidStateError'}),
|
||||
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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidStateError'}),
|
||||
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(
|
||||
/** @type {!FileError} */ ({'name': 'InvalidStateError'}),
|
||||
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(
|
||||
/** @type {!FileError} */ ({name: 'InvalidStateError'}),
|
||||
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(
|
||||
/** @type {!FileError} */ ({'name': 'AbortError'}),
|
||||
'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));
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs.FileWriter
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fs.FileWriterTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,322 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.FileWriterTest');
|
||||
goog.setTestOnly('goog.testing.fs.FileWriterTest');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.fs.Error');
|
||||
goog.require('goog.fs.FileSaver');
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.MockClock');
|
||||
goog.require('goog.testing.fs.Blob');
|
||||
goog.require('goog.testing.fs.FileSystem');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
var file, deferredWriter, mockClock;
|
||||
|
||||
function setUp() {
|
||||
mockClock = new goog.testing.MockClock(true);
|
||||
|
||||
var fs = new goog.testing.fs.FileSystem();
|
||||
var fileEntry = fs.getRoot().createDirectorySync('foo').createFileSync('bar');
|
||||
|
||||
deferredWriter = fileEntry.createWriter();
|
||||
file = fileEntry.fileSync();
|
||||
file.setDataInternal('');
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
mockClock.uninstall();
|
||||
}
|
||||
|
||||
function testWrite() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.INIT)).
|
||||
addCallback(goog.partial(checkPositionAndLength, 0, 0)).
|
||||
addCallback(goog.partial(checkLastModified, 0)).
|
||||
addCallback(goog.partial(tick, 3)).
|
||||
addCallback(goog.partial(writeString, 'hello')).
|
||||
addCallback(goog.partial(checkPositionAndLength, 0, 0)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(checkLastModified, 0)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE_START)).
|
||||
addCallback(goog.partial(checkLastModified, 0)).
|
||||
addCallback(goog.partial(checkPositionAndLength, 0, 0)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE)).
|
||||
addCallback(function() { assertEquals('hello', file.toString()); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 5, 5)).
|
||||
addCallback(goog.partial(checkLastModified, 3)).
|
||||
addCallback(tick).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(checkLastModified, 3)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE_END)).
|
||||
addCallback(goog.partial(checkLastModified, 3)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.DONE)).
|
||||
addCallback(goog.partial(checkLastModified, 3)).
|
||||
addCallback(goog.partial(writeString, ' world')).
|
||||
addCallback(goog.partial(checkPositionAndLength, 5, 5)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE)).
|
||||
addCallback(function() { assertEquals('hello world', file.toString()); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 11, 11)).
|
||||
addCallback(goog.partial(checkLastModified, 4)).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testWrite');
|
||||
}
|
||||
|
||||
function testSeek() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(tick, 17)).
|
||||
addCallback(goog.partial(writeAndWait, 'hello world')).
|
||||
addCallback(tick).
|
||||
addCallback(goog.partial(checkPositionAndLength, 11, 11)).
|
||||
|
||||
addCallback(function(writer) { writer.seek(6); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 6, 11)).
|
||||
addCallback(goog.partial(checkLastModified, 17)).
|
||||
addCallback(goog.partial(writeAndWait, 'universe')).
|
||||
addCallback(tick).
|
||||
addCallback(function() {
|
||||
assertEquals('hello universe', file.toString());
|
||||
}).
|
||||
addCallback(goog.partial(checkPositionAndLength, 14, 14)).
|
||||
|
||||
addCallback(function(writer) { writer.seek(500); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 14, 14)).
|
||||
addCallback(goog.partial(writeAndWait, '!')).
|
||||
addCallback(tick).
|
||||
addCallback(function() {
|
||||
assertEquals('hello universe!', file.toString());
|
||||
}).
|
||||
addCallback(goog.partial(checkPositionAndLength, 15, 15)).
|
||||
|
||||
addCallback(function(writer) { writer.seek(-9); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 6, 15)).
|
||||
addCallback(goog.partial(writeAndWait, 'foo')).
|
||||
addCallback(tick).
|
||||
addCallback(function() {
|
||||
assertEquals('hello fooverse!', file.toString());
|
||||
}).
|
||||
addCallback(goog.partial(checkPositionAndLength, 9, 15)).
|
||||
|
||||
addCallback(function(writer) { writer.seek(-500); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 0, 15)).
|
||||
addCallback(goog.partial(writeAndWait, 'bye-o')).
|
||||
addCallback(tick).
|
||||
addCallback(function() {
|
||||
assertEquals('bye-o fooverse!', file.toString());
|
||||
}).
|
||||
addCallback(goog.partial(checkPositionAndLength, 5, 15)).
|
||||
addCallback(goog.partial(checkLastModified, 21)).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testSeek');
|
||||
}
|
||||
|
||||
function testAbort() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(tick, 13)).
|
||||
addCallback(goog.partial(writeString, 'hello world')).
|
||||
addCallback(function(writer) { writer.abort(); }).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(waitForError, goog.fs.Error.ErrorCode.ABORT)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.ABORT)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE_END)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.DONE)).
|
||||
addCallback(goog.partial(checkPositionAndLength, 0, 0)).
|
||||
addCallback(goog.partial(checkLastModified, 0)).
|
||||
addCallback(function() { assertEquals('', file.toString()); }).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testAbort');
|
||||
}
|
||||
|
||||
function testTruncate() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(writeAndWait, 'hello world')).
|
||||
addCallback(goog.partial(checkPositionAndLength, 11, 11)).
|
||||
addCallback(function(writer) { writer.truncate(5); }).
|
||||
addCallback(goog.partial(checkPositionAndLength, 11, 11)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE_START)).
|
||||
addCallback(goog.partial(tick, 7)).
|
||||
addCallback(goog.partial(checkPositionAndLength, 11, 11)).
|
||||
addCallback(goog.partial(checkLastModified, 0)).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE)).
|
||||
addCallback(goog.partial(checkLastModified, 7)).
|
||||
addCallback(tick).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(goog.partial(checkPositionAndLength, 5, 5)).
|
||||
addCallback(function() { assertEquals('hello', file.toString()); }).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE_END)).
|
||||
addCallback(goog.partial(checkReadyState,
|
||||
goog.fs.FileSaver.ReadyState.DONE)).
|
||||
|
||||
addCallback(function(writer) { writer.truncate(10); }).
|
||||
addCallback(goog.partial(waitForEvent,
|
||||
goog.fs.FileSaver.EventType.WRITE_END)).
|
||||
addCallback(goog.partial(checkPositionAndLength, 5, 10)).
|
||||
addCallback(goog.partial(checkLastModified, 8)).
|
||||
addCallback(function() {
|
||||
assertEquals('hello\0\0\0\0\0', file.toString());
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testTruncate');
|
||||
}
|
||||
|
||||
function testAbortBeforeWrite() {
|
||||
deferredWriter.
|
||||
addCallback(function(writer) { writer.abort(); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(function(calledErrback) {
|
||||
assertTrue(calledErrback);
|
||||
}).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testAbortBeforeWrite');
|
||||
}
|
||||
|
||||
function testAbortAfterWrite() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(writeAndWait, 'hello world')).
|
||||
addCallback(function(writer) { writer.abort(); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(assertTrue).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testAbortAfterWrite');
|
||||
}
|
||||
|
||||
function testWriteDuringWrite() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(writeString, 'hello world')).
|
||||
addCallback(goog.partial(writeString, 'hello world')).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(assertTrue).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testWriteDuringWrite');
|
||||
}
|
||||
|
||||
function testSeekDuringWrite() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(writeString, 'hello world')).
|
||||
addCallback(function(writer) { writer.seek(5); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(assertTrue).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testSeekDuringWrite');
|
||||
}
|
||||
|
||||
function testTruncateDuringWrite() {
|
||||
deferredWriter.
|
||||
addCallback(goog.partial(writeString, 'hello world')).
|
||||
addCallback(function(writer) { writer.truncate(5); }).
|
||||
addErrback(function(err) {
|
||||
assertEquals(goog.fs.Error.ErrorCode.INVALID_STATE, err.code);
|
||||
return true;
|
||||
}).
|
||||
addCallback(assertTrue).
|
||||
addBoth(continueTesting);
|
||||
waitForAsync('testTruncateDuringWrite');
|
||||
}
|
||||
|
||||
|
||||
function tick(opt_tickCount) {
|
||||
mockClock.tick(opt_tickCount);
|
||||
}
|
||||
|
||||
function continueTesting(result) {
|
||||
asyncTestCase.continueTesting();
|
||||
if (result instanceof Error) {
|
||||
throw result;
|
||||
}
|
||||
mockClock.tick();
|
||||
}
|
||||
|
||||
function waitForAsync(msg) {
|
||||
asyncTestCase.waitForAsync(msg);
|
||||
|
||||
// The mock clock must be advanced far enough that all timeouts added during
|
||||
// callbacks will be triggered. 1000ms is much more than enough.
|
||||
mockClock.tick(1000);
|
||||
}
|
||||
|
||||
function waitForEvent(type, target) {
|
||||
var d = new goog.async.Deferred();
|
||||
goog.events.listenOnce(target, type, goog.bind(d.callback, d, target));
|
||||
return d;
|
||||
}
|
||||
|
||||
function waitForError(type, target) {
|
||||
var d = new goog.async.Deferred();
|
||||
goog.events.listenOnce(
|
||||
target, goog.fs.FileSaver.EventType.ERROR, function(e) {
|
||||
assertEquals(type, target.getError().code);
|
||||
d.callback(target);
|
||||
});
|
||||
return d;
|
||||
}
|
||||
|
||||
function checkReadyState(expectedState, writer) {
|
||||
assertEquals(expectedState, writer.getReadyState());
|
||||
}
|
||||
|
||||
function checkPositionAndLength(expectedPosition, expectedLength, writer) {
|
||||
assertEquals(expectedPosition, writer.getPosition());
|
||||
assertEquals(expectedLength, writer.getLength());
|
||||
}
|
||||
|
||||
function checkLastModified(expectedTime) {
|
||||
assertEquals(expectedTime, file.lastModifiedDate.getTime());
|
||||
}
|
||||
|
||||
function writeString(str, writer) {
|
||||
writer.write(new goog.testing.fs.Blob(str));
|
||||
}
|
||||
|
||||
function writeAndWait(str, writer) {
|
||||
writeString(str, writer);
|
||||
return waitForEvent(goog.fs.FileSaver.EventType.WRITE_END, writer);
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
// 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');
|
||||
/** @suppress {extraRequire} */
|
||||
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(''));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a blob with the given properties.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/Blob for more details.
|
||||
*
|
||||
* @param {Array<string|!goog.testing.fs.Blob>} parts
|
||||
* The values that will make up the resulting blob.
|
||||
* @param {string=} opt_type The MIME type of the Blob.
|
||||
* @param {string=} opt_endings Specifies how strings containing newlines are to
|
||||
* be written out.
|
||||
* @return {!goog.testing.fs.Blob} The blob.
|
||||
*/
|
||||
goog.testing.fs.getBlobWithProperties = function(parts, opt_type, opt_endings) {
|
||||
return new goog.testing.fs.Blob(goog.array.map(parts, String).join(''),
|
||||
opt_type);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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, 'getBlobWithProperties',
|
||||
goog.testing.fs.getBlobWithProperties);
|
||||
stubs.replace(fs, 'blobToString', goog.testing.fs.blobToString);
|
||||
stubs.replace(fs, 'browserSupportsObjectUrls',
|
||||
function() { return true; });
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Unit Tests - goog.testing.fs
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fsTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,55 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fsTest');
|
||||
goog.setTestOnly('goog.testing.fsTest');
|
||||
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.fs');
|
||||
goog.require('goog.testing.fs.Blob');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
|
||||
function testObjectUrls() {
|
||||
var blob = goog.testing.fs.getBlob('foo');
|
||||
var url = goog.testing.fs.createObjectUrl(blob);
|
||||
assertTrue(goog.testing.fs.isObjectUrlGranted(blob));
|
||||
goog.testing.fs.revokeObjectUrl(url);
|
||||
assertFalse(goog.testing.fs.isObjectUrlGranted(blob));
|
||||
}
|
||||
|
||||
function testGetBlob() {
|
||||
assertEquals(
|
||||
new goog.testing.fs.Blob('foobarbaz').toString(),
|
||||
goog.testing.fs.getBlob('foo', 'bar', 'baz').toString());
|
||||
assertEquals(
|
||||
new goog.testing.fs.Blob('foobarbaz').toString(),
|
||||
goog.testing.fs.getBlob('foo', new goog.testing.fs.Blob('bar'), 'baz').
|
||||
toString());
|
||||
}
|
||||
|
||||
function testBlobToString() {
|
||||
goog.testing.fs.blobToString(new goog.testing.fs.Blob('foobarbaz')).
|
||||
addCallback(goog.partial(assertEquals, 'foobarbaz')).
|
||||
addCallback(goog.bind(asyncTestCase.continueTesting, asyncTestCase));
|
||||
asyncTestCase.waitForAsync('testBlobToString');
|
||||
}
|
||||
|
||||
function testGetBlobWithProperties() {
|
||||
assertEquals(
|
||||
'data:spam/eggs;base64,Zm9vYmFy',
|
||||
new goog.testing.fs.getBlobWithProperties(
|
||||
['foo', new goog.testing.fs.Blob('bar')], 'spam/eggs').toDataUrl());
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
-->
|
||||
<head>
|
||||
<title>
|
||||
Closure Integration Tests - goog.testing.fs
|
||||
</title>
|
||||
<script src="../../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.testing.fs.integrationTest');
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="closureTestRunnerLog">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,221 @@
|
||||
// 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.
|
||||
|
||||
goog.provide('goog.testing.fs.integrationTest');
|
||||
goog.setTestOnly('goog.testing.fs.integrationTest');
|
||||
|
||||
goog.require('goog.async.Deferred');
|
||||
goog.require('goog.async.DeferredList');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.fs');
|
||||
goog.require('goog.fs.DirectoryEntry');
|
||||
goog.require('goog.fs.Error');
|
||||
goog.require('goog.fs.FileSaver');
|
||||
goog.require('goog.testing.AsyncTestCase');
|
||||
goog.require('goog.testing.PropertyReplacer');
|
||||
goog.require('goog.testing.fs');
|
||||
goog.require('goog.testing.jsunit');
|
||||
|
||||
var TEST_DIR = 'goog-fs-test-dir';
|
||||
|
||||
var deferredFs = goog.testing.fs.getTemporary();
|
||||
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall();
|
||||
|
||||
function setUpPage() {
|
||||
goog.testing.fs.install(new goog.testing.PropertyReplacer());
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
loadTestDir().
|
||||
addCallback(function(dir) { return dir.removeRecursively(); }).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('removing filesystem');
|
||||
}
|
||||
|
||||
function testWriteFile() {
|
||||
loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
|
||||
addCallback(goog.partial(writeToFile, 'test content')).
|
||||
addCallback(goog.partial(checkFileContent, 'test content')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testWriteFile');
|
||||
}
|
||||
|
||||
function testRemoveFile() {
|
||||
loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
|
||||
addCallback(goog.partial(writeToFile, 'test content')).
|
||||
addCallback(function(fileEntry) { return fileEntry.remove(); }).
|
||||
addCallback(goog.partial(checkFileRemoved, 'test')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testRemoveFile');
|
||||
}
|
||||
|
||||
function testMoveFile() {
|
||||
var deferredSubdir = loadDirectory(
|
||||
'subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
var deferredWrittenFile =
|
||||
loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE).
|
||||
addCallback(goog.partial(writeToFile, 'test content'));
|
||||
goog.async.DeferredList.gatherResults([deferredSubdir, deferredWrittenFile]).
|
||||
addCallback(splitArgs(function(dir, fileEntry) {
|
||||
return fileEntry.moveTo(dir);
|
||||
})).
|
||||
addCallback(goog.partial(checkFileContent, 'test content')).
|
||||
addCallback(goog.partial(checkFileRemoved, 'test')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testMoveFile');
|
||||
}
|
||||
|
||||
function testCopyFile() {
|
||||
var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
var deferredSubdir = loadDirectory(
|
||||
'subdir', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
var deferredWrittenFile = deferredFile.branch().
|
||||
addCallback(goog.partial(writeToFile, 'test content'));
|
||||
goog.async.DeferredList.gatherResults([deferredSubdir, deferredWrittenFile]).
|
||||
addCallback(splitArgs(function(dir, fileEntry) {
|
||||
return fileEntry.copyTo(dir);
|
||||
})).
|
||||
addCallback(goog.partial(checkFileContent, 'test content')).
|
||||
awaitDeferred(deferredFile).
|
||||
addCallback(goog.partial(checkFileContent, 'test content')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testCopyFile');
|
||||
}
|
||||
|
||||
function testAbortWrite() {
|
||||
var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
deferredFile.branch().
|
||||
addCallback(goog.partial(startWrite, 'test content')).
|
||||
addCallback(function(writer) { writer.abort(); }).
|
||||
addCallback(
|
||||
goog.partial(waitForEvent, goog.fs.FileSaver.EventType.ABORT)).
|
||||
awaitDeferred(deferredFile).
|
||||
addCallback(goog.partial(checkFileContent, '')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testAbortWrite');
|
||||
}
|
||||
|
||||
function testSeek() {
|
||||
var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
deferredFile.branch().
|
||||
addCallback(goog.partial(writeToFile, 'test content')).
|
||||
addCallback(function(fileEntry) { return fileEntry.createWriter(); }).
|
||||
addCallback(
|
||||
goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
|
||||
addCallback(function(writer) {
|
||||
writer.seek(5);
|
||||
writer.write(goog.fs.getBlob('stuff and things'));
|
||||
}).
|
||||
addCallback(
|
||||
goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(
|
||||
goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
|
||||
awaitDeferred(deferredFile).
|
||||
addCallback(goog.partial(checkFileContent, 'test stuff and things')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testSeek');
|
||||
}
|
||||
|
||||
function testTruncate() {
|
||||
var deferredFile = loadFile('test', goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
deferredFile.branch().
|
||||
addCallback(goog.partial(writeToFile, 'test content')).
|
||||
addCallback(function(fileEntry) { return fileEntry.createWriter(); }).
|
||||
addCallback(
|
||||
goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
|
||||
addCallback(function(writer) { writer.truncate(4); }).
|
||||
addCallback(
|
||||
goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING)).
|
||||
addCallback(
|
||||
goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
|
||||
awaitDeferred(deferredFile).
|
||||
addCallback(goog.partial(checkFileContent, 'test')).
|
||||
addBoth(continueTesting);
|
||||
asyncTestCase.waitForAsync('testTruncate');
|
||||
}
|
||||
|
||||
|
||||
function continueTesting(result) {
|
||||
asyncTestCase.continueTesting();
|
||||
if (result instanceof Error) {
|
||||
throw result;
|
||||
}
|
||||
}
|
||||
|
||||
function loadTestDir() {
|
||||
return deferredFs.branch().addCallback(function(fs) {
|
||||
return fs.getRoot().getDirectory(
|
||||
TEST_DIR, goog.fs.DirectoryEntry.Behavior.CREATE);
|
||||
});
|
||||
}
|
||||
|
||||
function loadFile(filename, behavior) {
|
||||
return loadTestDir().addCallback(function(dir) {
|
||||
return dir.getFile(filename, behavior);
|
||||
});
|
||||
}
|
||||
|
||||
function loadDirectory(filename, behavior) {
|
||||
return loadTestDir().addCallback(function(dir) {
|
||||
return dir.getDirectory(filename, behavior);
|
||||
});
|
||||
}
|
||||
|
||||
function startWrite(content, fileEntry) {
|
||||
return fileEntry.createWriter().
|
||||
addCallback(
|
||||
goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.INIT)).
|
||||
addCallback(function(writer) {
|
||||
writer.write(goog.fs.getBlob(content));
|
||||
return writer;
|
||||
}).
|
||||
addCallback(
|
||||
goog.partial(checkReadyState, goog.fs.FileSaver.ReadyState.WRITING));
|
||||
}
|
||||
|
||||
function waitForEvent(type, target) {
|
||||
var d = new goog.async.Deferred();
|
||||
goog.events.listenOnce(target, type, d.callback, false, d);
|
||||
return d;
|
||||
}
|
||||
|
||||
function writeToFile(content, fileEntry) {
|
||||
return startWrite(content, fileEntry).
|
||||
addCallback(
|
||||
goog.partial(waitForEvent, goog.fs.FileSaver.EventType.WRITE)).
|
||||
addCallback(function() { return fileEntry; });
|
||||
}
|
||||
|
||||
function checkFileContent(content, fileEntry) {
|
||||
return fileEntry.file().
|
||||
addCallback(function(blob) { return goog.fs.blobToString(blob); }).
|
||||
addCallback(goog.partial(assertEquals, content));
|
||||
}
|
||||
|
||||
function checkFileRemoved(filename) {
|
||||
return loadFile(filename).
|
||||
addCallback(goog.partial(fail, 'expected file to be removed')).
|
||||
addErrback(function(err) {
|
||||
assertEquals(err.code, goog.fs.Error.ErrorCode.NOT_FOUND);
|
||||
return true; // Go back to callback path
|
||||
});
|
||||
}
|
||||
|
||||
function checkReadyState(expectedState, writer) {
|
||||
assertEquals(expectedState, writer.getReadyState());
|
||||
}
|
||||
|
||||
function splitArgs(fn) {
|
||||
return function(args) { return fn(args[0], args[1]); };
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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}
|
||||
* @final
|
||||
*/
|
||||
goog.testing.fs.ProgressEvent = function(type, loaded, total) {
|
||||
goog.testing.fs.ProgressEvent.base(this, 'constructor', 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_;
|
||||
};
|
||||
Reference in New Issue
Block a user