blob: c9c24f1bee22ecde26bede139d3d1c3cf0e165c1 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* Mock chrome APIs.
* @type {Object}
*/
const mockChrome = {};
mockChrome.runtime = {
lastError: null
};
mockChrome.power = {
requestKeepAwake: function() {
mockChrome.power.keepAwakeRequested = true;
},
releaseKeepAwake: function() {
mockChrome.power.keepAwakeRequested = false;
},
keepAwakeRequested: false
};
mockChrome.fileManagerPrivate = {
onCopyProgress: {
addListener: function(callback) {
mockChrome.fileManagerPrivate.onCopyProgress.listener_ = callback;
},
removeListener: function() {
mockChrome.fileManagerPrivate.onCopyProgress.listener_ = null;
},
listener_: null
}
};
/**
* Logs copy-progress events from a file operation manager.
* @param {!FileOperationManager} fileOperationManager The target file
* operation manager.
* @constructor
* @struct
*/
function EventLogger(fileOperationManager) {
this.events = [];
this.numberOfBeginEvents = 0;
this.numberOfErrorEvents = 0;
this.numberOfSuccessEvents = 0;
fileOperationManager.addEventListener(
'copy-progress', this.onCopyProgress_.bind(this));
}
/**
* Log file operation manager copy-progress event details.
* @param {Event} event An event.
* @private
*/
EventLogger.prototype.onCopyProgress_ = function(event) {
event = /** @type {FileOperationProgressEvent} */ (event);
if (event.reason === 'BEGIN') {
this.events.push(event);
this.numberOfBeginEvents++;
}
if (event.reason === 'ERROR') {
this.events.push(event);
this.numberOfErrorEvents++;
}
if (event.reason === 'SUCCESS') {
this.events.push(event);
this.numberOfSuccessEvents++;
}
};
/**
* Provides fake implementation of chrome.fileManagerPrivate.startCopy.
* @param {string} blockedDestination Destination url of an entry whose request
* should be blocked.
* @param {!Entry} sourceEntry Source entry. Single source entry is supported.
* @param {!Array<!MockFileSystem>} fileSystems File systems array.
* @constructor
* @struct
*/
function BlockableFakeStartCopy(blockedDestination, sourceEntry, fileSystems) {
this.resolveBlockedOperationCallback = null;
this.blockedDestination_ = blockedDestination;
this.sourceEntry_ = sourceEntry;
this.fileSystems_ = fileSystems;
this.startCopyId_ = 0;
}
/**
* Fake implementation of startCopy function.
* @param {!Entry} source
* @param {!Entry} destination
* @param {string} newName
* @param {function(number)} callback
*/
BlockableFakeStartCopy.prototype.startCopyFunc = function(
source, destination, newName, callback) {
const makeStatus = type => {
return {
type: type,
sourceUrl: source.toURL(),
destinationUrl: destination.toURL()
};
};
const completeCopyOperation = copyId => {
const newPath = joinPath('/', newName);
const fileSystem =
getFileSystemForURL(this.fileSystems_, destination.toURL());
const mockEntry = /** @type {!MockEntry} */ (this.sourceEntry_);
fileSystem.entries[newPath] =
/** @type {!MockEntry} */ (mockEntry.clone(newPath));
listener(copyId, makeStatus('end_copy_entry'));
listener(copyId, makeStatus('success'));
};
this.startCopyId_++;
callback(this.startCopyId_);
var listener = mockChrome.fileManagerPrivate.onCopyProgress.listener_;
listener(this.startCopyId_, makeStatus('begin_copy_entry'));
listener(this.startCopyId_, makeStatus('progress'));
if (destination.toURL() === this.blockedDestination_) {
this.resolveBlockedOperationCallback =
completeCopyOperation.bind(this, this.startCopyId_);
} else {
completeCopyOperation(this.startCopyId_);
}
};
/**
* Fake volume manager.
* @constructor
* @struct
*/
function FakeVolumeManager() {}
/**
* Returns fake volume info.
* @param {!Entry} entry
* @return {!Object}
*/
FakeVolumeManager.prototype.getVolumeInfo = function(entry) {
return {volumeId: entry.filesystem.name};
};
/**
* Returns file system of the url.
* @param {!Array<!MockFileSystem>} fileSystems
* @param {string} url
* @return {!MockFileSystem}
*/
function getFileSystemForURL(fileSystems, url) {
for (let i = 0; i < fileSystems.length; i++) {
if (new RegExp('^filesystem:' + fileSystems[i].name + '/').test(url)) {
return fileSystems[i];
}
}
throw new Error('Unexpected url: ' + url);
}
/**
* Size of directory.
* @type {number}
* @const
*/
const DIRECTORY_SIZE = -1;
/**
* Creates test file system.
* @param {string} id File system Id.
* @param {Object<number>} entries Map of entry paths and their size.
* If the entry size is DIRECTORY_SIZE, the entry is a directory.
* @return {!MockFileSystem}
*/
function createTestFileSystem(id, entries) {
const fileSystem = new MockFileSystem(id, 'filesystem:' + id);
for (const path in entries) {
if (entries[path] === DIRECTORY_SIZE) {
fileSystem.entries[path] = new MockDirectoryEntry(fileSystem, path);
} else {
const metadata = /** @type {!Metadata} */ ({size: entries[path]});
fileSystem.entries[path] = new MockFileEntry(fileSystem, path, metadata);
}
}
return fileSystem;
}
/**
* Resolves URL on the file system.
* @param {!MockFileSystem} fileSystem File system.
* @param {string} url URL.
* @param {function(!Entry)} success Success callback.
* @param {function(!FileError)=} opt_failure Failure callback.
*/
function resolveTestFileSystemURL(fileSystem, url, success, opt_failure) {
for (const name in fileSystem.entries) {
const entry = fileSystem.entries[name];
if (entry.toURL() == url) {
success(entry);
return;
}
}
if (opt_failure) {
opt_failure(new FileError());
}
}
/**
* Waits for events until 'success'.
* @param {FileOperationManager} fileOperationManager File operation manager.
* @return {Promise} Promise to be fulfilled with an event list.
*/
function waitForEvents(fileOperationManager) {
return new Promise(fulfill => {
const events = [];
fileOperationManager.addEventListener('copy-progress', event => {
event = /** @type {FileOperationProgressEvent} */ (event);
events.push(event);
if (event.reason === 'SUCCESS') {
fulfill(events);
}
});
fileOperationManager.addEventListener('entries-changed', event => {
event = /** @type {FileOperationProgressEvent} */ (event);
events.push(event);
});
fileOperationManager.addEventListener('delete', event => {
event = /** @type {FileOperationProgressEvent} */ (event);
events.push(event);
if (event.reason === 'SUCCESS') {
fulfill(events);
}
});
});
}
/**
* Placeholder for mocked volume manager.
* @type {(FakeVolumeManager|{getVolumeInfo: function()}?)}
*/
let volumeManager;
var volumeManagerFactory = volumeManagerFactory || {};
/**
* Provide VolumeManager.getInstance() for FileOperationManager using mocked
* volume manager instance.
* @return {Promise}
*/
volumeManagerFactory.getInstance = () => {
return Promise.resolve(volumeManager);
};
/**
* Test target.
* @type {FileOperationManagerImpl}
*/
let fileOperationManager;
/**
* Initializes the test environment.
*/
function setUp() {
// Install mock chrome APIs.
installMockChrome(mockChrome);
}
/**
* Tests the fileOperationUtil.resolvePath function.
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testResolvePath(callback) {
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/file': 10,
'/directory': DIRECTORY_SIZE,
});
const root = fileSystem.root;
const rootPromise = fileOperationUtil.resolvePath(root, '/');
const filePromise = fileOperationUtil.resolvePath(root, '/file');
const directoryPromise = fileOperationUtil.resolvePath(root, '/directory');
const errorPromise =
fileOperationUtil.resolvePath(root, '/not_found')
.then(
() => {
assertTrue(false, 'The NOT_FOUND error is not reported.');
},
error => {
return error.name;
});
reportPromise(
Promise
.all([
rootPromise,
filePromise,
directoryPromise,
errorPromise,
])
.then(results => {
assertArrayEquals(
[
fileSystem.entries['/'],
fileSystem.entries['/file'],
fileSystem.entries['/directory'],
'NotFoundError',
],
results);
}),
callback);
}
/**
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testFindEntriesRecursively(callback) {
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/file.txt': 10,
'/file (1).txt': 10,
'/file (2).txt': 10,
'/file (3).txt': 10,
'/file (4).txt': 10,
'/file (5).txt': 10,
'/DCIM/': DIRECTORY_SIZE,
'/DCIM/IMG_1232.txt': 10,
'/DCIM/IMG_1233 (7).txt': 10,
'/DCIM/IMG_1234 (8).txt': 10,
'/DCIM/IMG_1235 (9).txt': 10,
});
const foundFiles = [];
fileOperationUtil
.findEntriesRecursively(
fileSystem.root,
fileEntry => {
foundFiles.push(fileEntry);
})
.then(() => {
assertEquals(12, foundFiles.length);
callback(false);
})
.catch(() => {
const error = true;
callback(error);
});
}
/**
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testFindFilesRecursively(callback) {
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/file.txt': 10,
'/file (1).txt': 10,
'/file (2).txt': 10,
'/file (3).txt': 10,
'/file (4).txt': 10,
'/file (5).txt': 10,
'/DCIM/': DIRECTORY_SIZE,
'/DCIM/IMG_1232.txt': 10,
'/DCIM/IMG_1233 (7).txt': 10,
'/DCIM/IMG_1234 (8).txt': 10,
'/DCIM/IMG_1235 (9).txt': 10,
});
const foundFiles = [];
fileOperationUtil
.findFilesRecursively(
fileSystem.root,
fileEntry => {
foundFiles.push(fileEntry);
})
.then(() => {
assertEquals(10, foundFiles.length);
foundFiles.forEach(entry => {
assertTrue(entry.isFile);
});
callback(false);
})
.catch(() => {
const error = true;
callback(error);
});
}
/**
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testGatherEntriesRecursively(callback) {
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/file.txt': 10,
'/file (1).txt': 10,
'/file (2).txt': 10,
'/file (3).txt': 10,
'/file (4).txt': 10,
'/file (5).txt': 10,
'/DCIM/': DIRECTORY_SIZE,
'/DCIM/IMG_1232.txt': 10,
'/DCIM/IMG_1233 (7).txt': 10,
'/DCIM/IMG_1234 (8).txt': 10,
'/DCIM/IMG_1235 (9).txt': 10,
});
fileOperationUtil.gatherEntriesRecursively(fileSystem.root)
.then(gatheredFiles => {
assertEquals(12, gatheredFiles.length);
callback(false);
})
.catch(() => {
const error = true;
callback(error);
});
}
/**
* Tests the fileOperationUtil.deduplicatePath
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testDeduplicatePath(callback) {
const fileSystem1 = createTestFileSystem('testVolume', {'/': DIRECTORY_SIZE});
const fileSystem2 = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/file.txt': 10,
});
const fileSystem3 = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/file.txt': 10,
'/file (1).txt': 10,
'/file (2).txt': 10,
'/file (3).txt': 10,
'/file (4).txt': 10,
'/file (5).txt': 10,
'/file (6).txt': 10,
'/file (7).txt': 10,
'/file (8).txt': 10,
'/file (9).txt': 10,
});
const nonExistingPromise =
fileOperationUtil.deduplicatePath(fileSystem1.root, 'file.txt')
.then(path => {
assertEquals('file.txt', path);
});
const existingPathPromise =
fileOperationUtil.deduplicatePath(fileSystem2.root, 'file.txt')
.then(path => {
assertEquals('file (1).txt', path);
});
const moreExistingPathPromise =
fileOperationUtil.deduplicatePath(fileSystem3.root, 'file.txt')
.then(path => {
assertEquals('file (10).txt', path);
});
const testPromise = Promise.all([
nonExistingPromise,
existingPathPromise,
moreExistingPathPromise,
]);
reportPromise(testPromise, callback);
}
/**
* Tests fileOperationManager copy.
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testCopy(callback) {
// Prepare entries and their resolver.
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/test.txt': 10,
});
window.webkitResolveLocalFileSystemURL = (url, success, failure) => {
resolveTestFileSystemURL(fileSystem, url, success, failure);
};
mockChrome.fileManagerPrivate.startCopy =
(source, destination, newName, callback) => {
const makeStatus = type => {
return {
type: type,
sourceUrl: source.toURL(),
destinationUrl: destination.toURL()
};
};
callback(1);
const listener = mockChrome.fileManagerPrivate.onCopyProgress.listener_;
listener(1, makeStatus('begin_copy_entry'));
listener(1, makeStatus('progress'));
const newPath = joinPath('/', newName);
const entry = /** @type {!MockEntry} */
(fileSystem.entries['/test.txt']);
fileSystem.entries[newPath] =
/** @type {!MockEntry} */ (entry.clone(newPath));
listener(1, makeStatus('end_copy_entry'));
listener(1, makeStatus('success'));
};
volumeManager = new FakeVolumeManager();
fileOperationManager = new FileOperationManagerImpl();
// Observe the file operation manager's events.
const eventsPromise = waitForEvents(fileOperationManager);
// Verify the events.
reportPromise(
eventsPromise.then(events => {
const firstEvent = events[0];
assertEquals('BEGIN', firstEvent.reason);
assertEquals(1, firstEvent.status.numRemainingItems);
assertEquals(0, firstEvent.status.processedBytes);
assertEquals(1, firstEvent.status.totalBytes);
const lastEvent = events[events.length - 1];
assertEquals('SUCCESS', lastEvent.reason);
assertEquals(0, lastEvent.status.numRemainingItems);
assertEquals(10, lastEvent.status.processedBytes);
assertEquals(10, lastEvent.status.totalBytes);
assertTrue(events.some(event => {
return event.type === 'entries-changed' &&
event.kind === util.EntryChangedKind.CREATED &&
event.entries[0].fullPath === '/test (1).txt';
}));
assertFalse(events.some(event => {
return event.type === 'delete';
}));
}),
callback);
fileOperationManager.paste(
[fileSystem.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystem.entries['/']), false);
}
/**
* Tests copying files when the destination volumes are same: the copy
* operations should be run sequentially.
*/
function testCopyInSequential(callback) {
// Prepare entries and their resolver.
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/dest': DIRECTORY_SIZE,
'/test.txt': 10,
});
window.webkitResolveLocalFileSystemURL = (url, success, failure) => {
resolveTestFileSystemURL(fileSystem, url, success, failure);
};
const blockableFakeStartCopy = new BlockableFakeStartCopy(
'filesystem:testVolume/dest', fileSystem.entries['/test.txt'],
[fileSystem]);
mockChrome.fileManagerPrivate.startCopy =
blockableFakeStartCopy.startCopyFunc.bind(blockableFakeStartCopy);
volumeManager = new FakeVolumeManager();
fileOperationManager = new FileOperationManagerImpl();
// Observe the file operation manager's events.
const eventLogger = new EventLogger(fileOperationManager);
// Copy test.txt to /dest. This operation should be blocked.
fileOperationManager.paste(
[fileSystem.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystem.entries['/dest']), false);
let firstOperationTaskId;
reportPromise(
waitUntil(() => {
// Wait until the first operation is blocked.
return blockableFakeStartCopy.resolveBlockedOperationCallback !== null;
})
.then(() => {
assertEquals(1, eventLogger.events.length);
assertEquals('BEGIN', eventLogger.events[0].reason);
firstOperationTaskId = eventLogger.events[0].taskId;
// Copy test.txt to /. This operation should be blocked.
fileOperationManager.paste(
[fileSystem.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystem.entries['/']),
false);
return waitUntil(() => {
return fileOperationManager.getPendingCopyTasksForTesting()
.length === 1;
});
})
.then(() => {
// Asserts that the second operation is added to pending copy tasks.
// Current implementation run tasks synchronusly after adding it to
// pending tasks.
// TODO(yawano) This check deeply depends on the implementation.
// Find a
// better way to test this.
const pendingTask =
fileOperationManager.getPendingCopyTasksForTesting()[0];
assertEquals(fileSystem.entries['/'], pendingTask.targetDirEntry);
blockableFakeStartCopy.resolveBlockedOperationCallback();
return waitUntil(() => {
return eventLogger.numberOfSuccessEvents === 2;
});
})
.then(() => {
// Events should be the following.
// BEGIN: first operation
// BEGIN: second operation
// SUCCESS: first operation
// SUCCESS: second operation
const events = eventLogger.events;
assertEquals(4, events.length);
assertEquals('BEGIN', events[0].reason);
assertEquals(firstOperationTaskId, events[0].taskId);
assertEquals('BEGIN', events[1].reason);
assertTrue(events[1].taskId !== firstOperationTaskId);
assertEquals('SUCCESS', events[2].reason);
assertEquals(firstOperationTaskId, events[2].taskId);
assertEquals('SUCCESS', events[3].reason);
assertEquals(events[1].taskId, events[3].taskId);
}),
callback);
}
/**
* Tests copying files when the destination volumes are different: the copy
* operations should be run in parallel.
*/
function testCopyInParallel(callback) {
// Prepare entries and their resolver.
const fileSystemA = createTestFileSystem('volumeA', {
'/': DIRECTORY_SIZE,
'/test.txt': 10,
});
const fileSystemB = createTestFileSystem('volumeB', {
'/': DIRECTORY_SIZE,
});
const fileSystems = [fileSystemA, fileSystemB];
window.webkitResolveLocalFileSystemURL = (url, success, failure) => {
const system = getFileSystemForURL(fileSystems, url);
resolveTestFileSystemURL(system, url, success, failure);
};
const blockableFakeStartCopy = new BlockableFakeStartCopy(
'filesystem:volumeB/', fileSystemA.entries['/test.txt'], fileSystems);
mockChrome.fileManagerPrivate.startCopy =
blockableFakeStartCopy.startCopyFunc.bind(blockableFakeStartCopy);
volumeManager = new FakeVolumeManager();
fileOperationManager = new FileOperationManagerImpl();
// Observe the file operation manager's events.
const eventLogger = new EventLogger(fileOperationManager);
// Copy test.txt from volume A to volume B.
fileOperationManager.paste(
[fileSystemA.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystemB.entries['/']), false);
let firstOperationTaskId;
reportPromise(
waitUntil(() => {
return blockableFakeStartCopy.resolveBlockedOperationCallback !== null;
})
.then(() => {
assertEquals(1, eventLogger.events.length);
assertEquals('BEGIN', eventLogger.events[0].reason);
firstOperationTaskId = eventLogger.events[0].taskId;
// Copy test.txt from volume A to volume A. This should not be
// blocked by the previous operation.
fileOperationManager.paste(
[fileSystemA.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystemA.entries['/']),
false);
// Wait until the second operation is completed.
return waitUntil(() => {
return eventLogger.numberOfSuccessEvents === 1;
});
})
.then(() => {
// Resolve the blocked operation.
blockableFakeStartCopy.resolveBlockedOperationCallback();
// Wait until the blocked operation is completed.
return waitUntil(() => {
return eventLogger.numberOfSuccessEvents === 2;
});
})
.then(() => {
// Events should be following.
// BEGIN: first operation
// BEGIN: second operation
// SUCCESS: second operation
// SUCCESS: first operation
const events = eventLogger.events;
assertEquals(4, events.length);
assertEquals('BEGIN', events[0].reason);
assertEquals(firstOperationTaskId, events[0].taskId);
assertEquals('BEGIN', events[1].reason);
assertTrue(firstOperationTaskId !== events[1].taskId);
assertEquals('SUCCESS', events[2].reason);
assertEquals(events[1].taskId, events[2].taskId);
assertEquals('SUCCESS', events[3].reason);
assertEquals(firstOperationTaskId, events[3].taskId);
}),
callback);
}
/**
* Tests that copy operations fail when the destination volume is not
* available.
*/
function testCopyFails(callback) {
// Prepare entries.
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/test.txt': 10,
});
volumeManager = {
/* Mocking volume manager. */
getVolumeInfo: function() {
// Returns null to indicate that the volume is not available.
return null;
}
};
fileOperationManager = new FileOperationManagerImpl();
// Observe the file operation manager's events.
const eventLogger = new EventLogger(fileOperationManager);
// Copy test.txt to /, which should fail.
fileOperationManager.paste(
[fileSystem.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystem.entries['/']), false);
reportPromise(
waitUntil(() => {
return eventLogger.numberOfErrorEvents === 1;
}).then(() => {
// Since the task fails with an error, pending copy tasks should be
// empty.
assertEquals(
0, fileOperationManager.getPendingCopyTasksForTesting().length);
// Check events.
const events = eventLogger.events;
assertEquals(2, events.length);
assertEquals('BEGIN', events[0].reason);
assertEquals('ERROR', events[1].reason);
assertEquals(events[0].taskId, events[1].taskId);
}),
callback);
}
/**
* Tests the fileOperationUtil.paste for move.
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testMove(callback) {
// Prepare entries and their resolver.
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/directory': DIRECTORY_SIZE,
'/test.txt': 10,
});
window.webkitResolveLocalFileSystemURL = (url, success, failure) => {
resolveTestFileSystemURL(fileSystem, url, success, failure);
};
volumeManager = new FakeVolumeManager();
fileOperationManager = new FileOperationManagerImpl();
// Observe the file operation manager's events.
const eventsPromise = waitForEvents(fileOperationManager);
// Verify the events.
reportPromise(
eventsPromise.then(events => {
const firstEvent = events[0];
assertEquals('BEGIN', firstEvent.reason);
assertEquals(1, firstEvent.status.numRemainingItems);
assertEquals(0, firstEvent.status.processedBytes);
assertEquals(1, firstEvent.status.totalBytes);
const lastEvent = events[events.length - 1];
assertEquals('SUCCESS', lastEvent.reason);
assertEquals(0, lastEvent.status.numRemainingItems);
assertEquals(1, lastEvent.status.processedBytes);
assertEquals(1, lastEvent.status.totalBytes);
assertTrue(events.some(event => {
return event.type === 'entries-changed' &&
event.kind === util.EntryChangedKind.DELETED &&
event.entries[0].fullPath === '/test.txt';
}));
assertTrue(events.some(event => {
return event.type === 'entries-changed' &&
event.kind === util.EntryChangedKind.CREATED &&
event.entries[0].fullPath === '/directory/test.txt';
}));
assertFalse(events.some(event => {
return event.type === 'delete';
}));
}),
callback);
fileOperationManager.paste(
[fileSystem.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystem.entries['/directory']), true);
}
/**
* Tests fileOperationManager.deleteEntries.
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testDelete(callback) {
// Prepare entries and their resolver.
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/test.txt': 10,
});
window.webkitResolveLocalFileSystemURL = (url, success, failure) => {
resolveTestFileSystemURL(fileSystem, url, success, failure);
};
// Observing manager's events.
reportPromise(
waitForEvents(fileOperationManager).then(events => {
assertEquals('delete', events[0].type);
assertEquals('BEGIN', events[0].reason);
assertEquals(10, events[0].totalBytes);
assertEquals(0, events[0].processedBytes);
const lastEvent = events[events.length - 1];
assertEquals('delete', lastEvent.type);
assertEquals('SUCCESS', lastEvent.reason);
assertEquals(10, lastEvent.totalBytes);
assertEquals(10, lastEvent.processedBytes);
assertFalse(events.some(event => {
return event.type === 'copy-progress';
}));
}),
callback);
fileOperationManager.deleteEntries([fileSystem.entries['/test.txt']]);
}
/**
* Tests fileOperationManager.zipSelection.
* @param {function(boolean)} callback Callback to be passed true on error.
*/
function testZip(callback) {
// Prepare entries and their resolver.
const fileSystem = createTestFileSystem('testVolume', {
'/': DIRECTORY_SIZE,
'/test.txt': 10,
});
window.webkitResolveLocalFileSystemURL = function(url, success, failure) {
resolveTestFileSystemURL(fileSystem, url, success, failure);
};
mockChrome.fileManagerPrivate.zipSelection = function(
sources, parent, newName, success, error) {
const newPath = joinPath('/', newName);
const newEntry = new MockFileEntry(
fileSystem, newPath, /** @type {!Metadata} */ ({size: 10}));
fileSystem.entries[newPath] = newEntry;
success(newEntry);
};
volumeManager = new FakeVolumeManager();
fileOperationManager = new FileOperationManagerImpl();
// Observing manager's events.
reportPromise(
waitForEvents(fileOperationManager).then(events => {
assertEquals('copy-progress', events[0].type);
assertEquals('BEGIN', events[0].reason);
assertEquals(1, events[0].status.totalBytes);
assertEquals(0, events[0].status.processedBytes);
const lastEvent = events[events.length - 1];
assertEquals('copy-progress', lastEvent.type);
assertEquals('SUCCESS', lastEvent.reason);
assertEquals(10, lastEvent.status.totalBytes);
assertEquals(10, lastEvent.status.processedBytes);
assertFalse(events.some(event => {
return event.type === 'delete';
}));
assertTrue(events.some(event => {
return event.type === 'entries-changed' &&
event.entries[0].fullPath === '/test.zip';
}));
}),
callback);
fileOperationManager.zipSelection(
[fileSystem.entries['/test.txt']],
/** @type {!DirectoryEntry} */ (fileSystem.entries['/']));
}