1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * This extension provides two file browser handlers: 'ReadOnly' and
7 * 'ReadWrite'. 'ReadOnly' handler handles .xul files and has read-only file
8 * access. 'ReadWrite' handler handles .tiff files and has read-write file
11 * The extension waits until both handlers are executed and then runs tests for
12 * them. The tests verify that the extension is able to read/write the handled
13 * files as defined by the handlers' file access permissions. If there is an
14 * error before the tests are run, chrome.test.notifyFail will be called, and
15 * further onExecute events will be ignored.
17 * The handlers are executed by 'file_browser/handler_test_runner' extension.
18 * Each of 'ReadOnly' and 'ReadWrite' handlers should be executed once, and each
19 * should carry exactly one handled file.
22 // Initial content of handled files. The content is set in
23 // external_filesystem_apitest.cc.
24 var kInitialTestFileContent = 'This is some test content.';
25 // Content written by write test.
26 var kTextToWrite = ' Yay!';
29 * Asserts that |value| equals |expectedValue|. If the assert fails, current
30 * test fails with |errorMessage|. Otherwise, |callback()| is called.
32 function assertEqAndRunCallback(expectedValue, value, errorMessage, callback) {
33 chrome.test.assertEq(expectedValue, value, errorMessage);
38 * Attempts to read file and asserts that the read success and file content are
39 * as expected (|expectSuccess|, |expectedContent|). On success |callback| is
40 * called, otherwise current test is failed.
42 * @param {FileEntry} entry Entry to be read.
43 * @param {boolean} expectSuccess Whether the read should succeed.
44 * @param {string} expectedContent If the read succeeds, the expected content to
45 * be read from file. If the read fails, it is ignored.
46 * @param {function()} callback Function called if the read ends as defined by
47 * |expectSuccess| and |expectedContent|.
49 function readAndExpectContent(entry, expectSuccess, expectedContent, callback) {
50 var error = 'Reading file \'' + entry.fullPath + '\'.';
51 var reader = new FileReader();
53 reader.onload = function() {
54 chrome.test.assertTrue(expectSuccess, error);
55 assertEqAndRunCallback(expectedContent, reader.result, error, callback);
58 entry.file(reader.readAsText.bind(reader),
59 assertEqAndRunCallback.bind(null,
60 false, expectSuccess, error, callback));
64 * Attempts to write |content| to the end of the |entry| and verifies that the
65 * operation success is as expected. On success |callback| is called, else the
66 * current test is failed.
68 * @param {FileEntry} entry File entry to be read.
69 * @param {string} content String content to be appended to the file.
70 * @param {boolean} expectSuccess Whether the write should succeed.
71 * @param {function()} callback Function called if write ends as defined by
74 function write(entry, content, expectSuccess, callback) {
75 var error = 'Writing to: \'' + entry.fullPath + '\'.';
77 entry.createWriter(function(writer) {
78 writer.onerror = assertEqAndRunCallback.bind(null, expectSuccess, false,
80 writer.onwrite = assertEqAndRunCallback.bind(null, expectSuccess, true,
83 writer.seek(kInitialTestFileContent.length);
84 var blob = new Blob([kTextToWrite], {type: 'text/plain'});
87 assertEqAndRunCallback.bind(null, expectSuccess, false,
88 'Getting writer for: \'' + entry.fullPath + '\'.', callback));
94 * @params {FileEntry} entry File entry for which the test should be run.
95 * @params {boolean} expectSuccess Whether the read should succeed.
97 function readTest(entry, expectSuccess) {
98 readAndExpectContent(entry, expectSuccess, kInitialTestFileContent,
103 * Runs test for a file that is not executed for any handler. Test tries to get
104 * an existing file entry from the |entry|'s filesystem. The file path is
105 * constructed by appending '.foo' to the |entry|'s path (the Chrome part of the
106 * test should ensure that the file exists). The get operation is expected to
109 function getSiblingTest(entry) {
110 var error = 'Got file (\'' + entry.fullPath.concat('.foo') + '\') for which' +
111 'file access was not granted.';
112 entry.filesystem.root.getFile(
113 entry.fullPath.concat('.foo'), {},
114 chrome.test.fail.bind(null, error),
115 chrome.test.succeed);
120 * Attempts to write to the entry. If the write operation ends as expected, the
121 * test verifies new content of the file.
123 * @param {FileEntry} entry Entry to be written.
124 * @param {boolean} expectSuccess Whether the test should succeed.
126 function writeTest(entry, expectSuccess) {
127 var verifyFileContent = function() {
128 var expectedContent = kInitialTestFileContent;
129 // The test file content should change only if the write operatino
132 expectedContent = expectedContent.concat(kTextToWrite);
134 readAndExpectContent(entry, true, expectedContent, chrome.test.succeed);
137 write(entry, kTextToWrite, expectSuccess, verifyFileContent);
141 * Object that follows the extensions's status before chrome.test.runTests is
142 * called (i.e. while it's waiting for onExecute events).
144 var testPreRunStatus = {
145 // Whether the 'ReadOnly' handler has been executed.
146 gotReadOnlyAction: false,
147 // Whether the 'ReadWrite' handler has been executed.
148 gotReadWriteAction: false,
149 // |done| is set either when the runTests is called, or an error is detected.
150 // After |done| is set, all other onExecute events will be ignored.
155 * List of tests to be run for the handlers.
157 * @type {Array.<function()>}
159 var handlerTests = [];
162 * Called if an error is detected before chrome.test.runTests. It sends failure
163 * notification and cancels further testing.
165 * @param {string} message The error message to be reported.
167 function onError(message) {
168 testPreRunStatus.done = true;
169 chrome.test.notifyFail(message);
173 * Listens for onExecute events, and runs tests once all expected events are
176 function onExecuteListener(id, details) {
177 if (testPreRunStatus.done)
180 var fileEntries = details.entries;
181 if (!fileEntries || fileEntries.length != 1) {
182 onError('Unexpected file entries size.');
186 if ((id == 'ReadOnly' && testPreRunStatus.gotReadOnlyAction) ||
187 (id == 'ReadWrite' && testPreRunStatus.gotReadWriteAction)) {
188 onError('Action \'' + id + '\' executed more than once.');
192 if (id == 'ReadOnly') {
193 var entry = fileEntries[0];
195 // Add tests for read-only handler.
196 handlerTests.push(function readReadOnly() { readTest(entry, true); });
198 function getSiblingReadOnly() { getSiblingTest(entry); });
199 handlerTests.push(function writeReadOnly() { writeTest(entry, false); });
201 testPreRunStatus.gotReadOnlyAction = true;
202 } else if (id == 'ReadWrite') {
203 var entry = fileEntries[0];
205 // Add tests for read-write handler.
206 handlerTests.push(function readReadWrite() { readTest(entry, true); });
208 function getSilblingReadWrite() { getSiblingTest(entry); });
209 handlerTests.push(function writeReadWrite() { writeTest(entry, true); });
211 testPreRunStatus.gotReadWriteAction = true;
213 onError('Unexpected action id: ' + id);
217 if (testPreRunStatus.gotReadOnlyAction &&
218 testPreRunStatus.gotReadWriteAction) {
219 testPreRunStatus.done = true;
220 chrome.test.runTests(handlerTests);
224 chrome.fileBrowserHandler.onExecute.addListener(onExecuteListener);