|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 importScripts('worker_test_osfile_shared.js'); |
|
5 importScripts("resource://gre/modules/workers/require.js"); |
|
6 |
|
7 let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); |
|
8 SharedAll.Config.DEBUG = true; |
|
9 |
|
10 function should_throw(f) { |
|
11 try { |
|
12 f(); |
|
13 } catch (x) { |
|
14 return x; |
|
15 } |
|
16 return null; |
|
17 } |
|
18 |
|
19 self.onmessage = function onmessage_start(msg) { |
|
20 self.onmessage = function onmessage_ignored(msg) { |
|
21 log("ignored message " + JSON.stringify(msg.data)); |
|
22 }; |
|
23 try { |
|
24 test_init(); |
|
25 test_offsetby(); |
|
26 test_open_existing_file(); |
|
27 test_open_non_existing_file(); |
|
28 test_flush_open_file(); |
|
29 test_copy_existing_file(); |
|
30 test_readall_writeall_file(); |
|
31 test_position(); |
|
32 test_move_file(); |
|
33 test_iter_dir(); |
|
34 test_info(); |
|
35 test_path(); |
|
36 test_exists_file(); |
|
37 test_remove_file(); |
|
38 } catch (x) { |
|
39 log("Catching error: " + x); |
|
40 log("Stack: " + x.stack); |
|
41 log("Source: " + x.toSource()); |
|
42 ok(false, x.toString() + "\n" + x.stack); |
|
43 } |
|
44 finish(); |
|
45 }; |
|
46 |
|
47 function test_init() { |
|
48 info("Starting test_init"); |
|
49 importScripts("resource://gre/modules/osfile.jsm"); |
|
50 } |
|
51 |
|
52 function test_offsetby() { |
|
53 info("Starting test_offsetby"); |
|
54 |
|
55 // Initialize one array |
|
56 let LENGTH = 1024; |
|
57 let buf = new ArrayBuffer(LENGTH); |
|
58 let view = new Uint8Array(buf); |
|
59 let i; |
|
60 for (i = 0; i < LENGTH; ++i) { |
|
61 view[i] = i; |
|
62 } |
|
63 |
|
64 // Walk through the array with offsetBy by 8 bits |
|
65 let uint8 = SharedAll.Type.uint8_t.in_ptr.implementation(buf); |
|
66 for (i = 0; i < LENGTH; ++i) { |
|
67 let value = SharedAll.offsetBy(uint8, i).contents; |
|
68 if (value != i%256) { |
|
69 is(value, i % 256, "test_offsetby: Walking through array with offsetBy (8 bits)"); |
|
70 break; |
|
71 } |
|
72 } |
|
73 |
|
74 // Walk again by 16 bits |
|
75 let uint16 = SharedAll.Type.uint16_t.in_ptr.implementation(buf); |
|
76 let view2 = new Uint16Array(buf); |
|
77 for (i = 0; i < LENGTH/2; ++i) { |
|
78 let value = SharedAll.offsetBy(uint16, i).contents; |
|
79 if (value != view2[i]) { |
|
80 is(value, view2[i], "test_offsetby: Walking through array with offsetBy (16 bits)"); |
|
81 break; |
|
82 } |
|
83 } |
|
84 |
|
85 // Ensure that offsetBy(..., 0) is idempotent |
|
86 let startptr = SharedAll.offsetBy(uint8, 0); |
|
87 let startptr2 = SharedAll.offsetBy(startptr, 0); |
|
88 is(startptr.toString(), startptr2.toString(), "test_offsetby: offsetBy(..., 0) is idmpotent"); |
|
89 |
|
90 // Ensure that offsetBy(ptr, ...) does not work if ptr is a void* |
|
91 let ptr = ctypes.voidptr_t(0); |
|
92 let exn; |
|
93 try { |
|
94 SharedAll.offsetBy(ptr, 1); |
|
95 } catch (x) { |
|
96 exn = x; |
|
97 } |
|
98 ok(!!exn, "test_offsetby: rejected offsetBy with void*"); |
|
99 |
|
100 info("test_offsetby: complete"); |
|
101 } |
|
102 |
|
103 |
|
104 /** |
|
105 * Test that we can open an existing file. |
|
106 */ |
|
107 function test_open_existing_file() |
|
108 { |
|
109 info("Starting test_open_existing"); |
|
110 let file = OS.File.open("chrome/toolkit/components/osfile/tests/mochi/worker_test_osfile_unix.js"); |
|
111 file.close(); |
|
112 } |
|
113 |
|
114 /** |
|
115 * Test that opening a file that does not exist fails with the right error. |
|
116 */ |
|
117 function test_open_non_existing_file() |
|
118 { |
|
119 info("Starting test_open_non_existing"); |
|
120 let exn; |
|
121 try { |
|
122 let file = OS.File.open("/I do not exist"); |
|
123 } catch (x) { |
|
124 exn = x; |
|
125 info("test_open_non_existing_file: Exception detail " + exn); |
|
126 } |
|
127 ok(!!exn, "test_open_non_existing_file: Exception was raised "); |
|
128 ok(exn instanceof OS.File.Error, "test_open_non_existing_file: Exception was a OS.File.Error"); |
|
129 ok(exn.becauseNoSuchFile, "test_open_non_existing_file: Exception confirms that the file does not exist"); |
|
130 } |
|
131 |
|
132 /** |
|
133 * Test that to ensure that |foo.flush()| does not |
|
134 * cause an error, where |foo| is an open file. |
|
135 */ |
|
136 function test_flush_open_file() |
|
137 { |
|
138 info("Starting test_flush_open_file"); |
|
139 let tmp = "test_flush.tmp"; |
|
140 let file = OS.File.open(tmp, {create: true, write: true}); |
|
141 file.flush(); |
|
142 file.close(); |
|
143 OS.File.remove(tmp); |
|
144 } |
|
145 |
|
146 /** |
|
147 * Utility function for comparing two files (or a prefix of two files). |
|
148 * |
|
149 * This function returns nothing but fails of both files (or prefixes) |
|
150 * are not identical. |
|
151 * |
|
152 * @param {string} test The name of the test (used for logging). |
|
153 * @param {string} sourcePath The name of the first file. |
|
154 * @param {string} destPath The name of the second file. |
|
155 * @param {number=} prefix If specified, only compare the |prefix| |
|
156 * first bytes of |sourcePath| and |destPath|. |
|
157 */ |
|
158 function compare_files(test, sourcePath, destPath, prefix) |
|
159 { |
|
160 info(test + ": Comparing " + sourcePath + " and " + destPath); |
|
161 let source = OS.File.open(sourcePath); |
|
162 let dest = OS.File.open(destPath); |
|
163 info("Files are open"); |
|
164 let sourceResult, destResult; |
|
165 try { |
|
166 if (prefix != undefined) { |
|
167 sourceResult = source.read(prefix); |
|
168 destResult = dest.read(prefix); |
|
169 } else { |
|
170 sourceResult = source.read(); |
|
171 destResult = dest.read(); |
|
172 } |
|
173 is(sourceResult.length, destResult.length, test + ": Both files have the same size"); |
|
174 for (let i = 0; i < sourceResult.length; ++i) { |
|
175 if (sourceResult[i] != destResult[i]) { |
|
176 is(sourceResult[i] != destResult[i], test + ": Comparing char " + i); |
|
177 break; |
|
178 } |
|
179 } |
|
180 } finally { |
|
181 source.close(); |
|
182 dest.close(); |
|
183 } |
|
184 info(test + ": Comparison complete"); |
|
185 } |
|
186 |
|
187 function test_readall_writeall_file() |
|
188 { |
|
189 let src_file_name = |
|
190 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", |
|
191 "worker_test_osfile_front.js"); |
|
192 let tmp_file_name = |
|
193 OS.Path.join(OS.Constants.Path.tmpDir, "test_osfile_front.tmp"); |
|
194 info("Starting test_readall_writeall_file"); |
|
195 |
|
196 // read, ArrayBuffer |
|
197 |
|
198 let source = OS.File.open(src_file_name); |
|
199 let dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
200 let size = source.stat().size; |
|
201 |
|
202 let buf = new Uint8Array(size); |
|
203 let readResult = source.readTo(buf); |
|
204 is(readResult, size, "test_readall_writeall_file: read the right number of bytes"); |
|
205 |
|
206 dest.write(buf); |
|
207 |
|
208 info("test_readall_writeall_file: copy complete (manual allocation)"); |
|
209 source.close(); |
|
210 dest.close(); |
|
211 |
|
212 compare_files("test_readall_writeall_file (manual allocation)", src_file_name, tmp_file_name); |
|
213 OS.File.remove(tmp_file_name); |
|
214 |
|
215 // read, C buffer |
|
216 source = OS.File.open(src_file_name); |
|
217 dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
218 buf = new ArrayBuffer(size); |
|
219 let ptr = OS.Shared.Type.voidptr_t.implementation(buf); |
|
220 readResult = source.readTo(ptr, {bytes: size}); |
|
221 is(readResult, size, "test_readall_writeall_file: read the right number of bytes (C buffer)"); |
|
222 |
|
223 dest.write(ptr, {bytes: size}); |
|
224 |
|
225 info("test_readall_writeall_file: copy complete (C buffer)"); |
|
226 source.close(); |
|
227 dest.close(); |
|
228 |
|
229 compare_files("test_readall_writeall_file (C buffer)", src_file_name, tmp_file_name); |
|
230 OS.File.remove(tmp_file_name); |
|
231 |
|
232 // read/write, C buffer, missing |bytes| option |
|
233 source = OS.File.open(src_file_name); |
|
234 dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
235 let exn = should_throw(function() { source.readTo(ptr); }); |
|
236 ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: read with C pointer and without bytes fails with the correct error"); |
|
237 exn = should_throw(function() { dest.write(ptr); }); |
|
238 ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: write with C pointer and without bytes fails with the correct error"); |
|
239 |
|
240 source.close(); |
|
241 dest.close(); |
|
242 |
|
243 // readTo, ArrayBuffer + offset |
|
244 let OFFSET = 12; |
|
245 let LEFT = size - OFFSET; |
|
246 buf = new ArrayBuffer(size); |
|
247 let offset_view = new Uint8Array(buf, OFFSET); |
|
248 source = OS.File.open(src_file_name); |
|
249 dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
250 |
|
251 readResult = source.readTo(offset_view); |
|
252 is(readResult, LEFT, "test_readall_writeall_file: read the right number of bytes (with offset)"); |
|
253 |
|
254 dest.write(offset_view); |
|
255 is(dest.stat().size, LEFT, "test_readall_writeall_file: wrote the right number of bytes (with offset)"); |
|
256 |
|
257 info("test_readall_writeall_file: copy complete (with offset)"); |
|
258 source.close(); |
|
259 dest.close(); |
|
260 |
|
261 compare_files("test_readall_writeall_file (with offset)", src_file_name, tmp_file_name, LEFT); |
|
262 OS.File.remove(tmp_file_name); |
|
263 |
|
264 // read |
|
265 buf = new Uint8Array(size); |
|
266 source = OS.File.open(src_file_name); |
|
267 dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
268 |
|
269 readResult = source.read(); |
|
270 is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (auto allocation)"); |
|
271 |
|
272 dest.write(readResult); |
|
273 |
|
274 info("test_readall_writeall_file: copy complete (auto allocation)"); |
|
275 source.close(); |
|
276 dest.close(); |
|
277 |
|
278 compare_files("test_readall_writeall_file (auto allocation)", src_file_name, tmp_file_name); |
|
279 OS.File.remove(tmp_file_name); |
|
280 |
|
281 // File.readAll |
|
282 readResult = OS.File.read(src_file_name); |
|
283 is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (OS.File.readAll)"); |
|
284 |
|
285 // File.writeAtomic on top of nothing |
|
286 OS.File.writeAtomic(tmp_file_name, readResult, |
|
287 {tmpPath: tmp_file_name + ".tmp"}); |
|
288 try { |
|
289 let stat = OS.File.stat(tmp_file_name); |
|
290 info("readAll + writeAtomic created a file"); |
|
291 is(stat.size, size, "readAll + writeAtomic created a file of the right size"); |
|
292 } catch (x) { |
|
293 ok(false, "readAll + writeAtomic somehow failed"); |
|
294 if(x.becauseNoSuchFile) { |
|
295 ok(false, "readAll + writeAtomic did not create file"); |
|
296 } |
|
297 } |
|
298 compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic)", |
|
299 src_file_name, tmp_file_name); |
|
300 exn = null; |
|
301 try { |
|
302 let stat = OS.File.stat(tmp_file_name + ".tmp"); |
|
303 } catch (x) { |
|
304 exn = x; |
|
305 } |
|
306 ok(!!exn, "readAll + writeAtomic cleaned up after itself"); |
|
307 |
|
308 // File.writeAtomic on top of existing file |
|
309 // Remove content and set arbitrary size, to avoid potential false negatives |
|
310 dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
311 dest.setPosition(1234); |
|
312 dest.close(); |
|
313 |
|
314 OS.File.writeAtomic(tmp_file_name, readResult, |
|
315 {tmpPath: tmp_file_name + ".tmp"}); |
|
316 compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic 2)", |
|
317 src_file_name, tmp_file_name); |
|
318 |
|
319 // File.writeAtomic on top of existing file but without overwritten the file |
|
320 exn = null; |
|
321 try { |
|
322 let view = new Uint8Array(readResult.buffer, 10, 200); |
|
323 OS.File.writeAtomic(tmp_file_name, view, |
|
324 { tmpPath: tmp_file_name + ".tmp", noOverwrite: true}); |
|
325 } catch (x) { |
|
326 exn = x; |
|
327 } |
|
328 ok(exn && exn instanceof OS.File.Error && exn.becauseExists, "writeAtomic fails if file already exists with noOverwrite option"); |
|
329 // Check file was not overwritten. |
|
330 compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic check file was not overwritten)", |
|
331 src_file_name, tmp_file_name); |
|
332 |
|
333 // Ensure that File.writeAtomic fails if no temporary file name is provided |
|
334 // (FIXME: Remove this test as part of bug 793660) |
|
335 |
|
336 exn = null; |
|
337 try { |
|
338 OS.File.writeAtomic(tmp_file_name, readResult.buffer, |
|
339 {bytes: readResult.length}); |
|
340 } catch (x) { |
|
341 exn = x; |
|
342 } |
|
343 ok(!!exn && exn instanceof TypeError, "writeAtomic fails if tmpPath is not provided"); |
|
344 |
|
345 // Check that writeAtomic fails when destination path is undefined |
|
346 exn = null; |
|
347 try { |
|
348 let path = undefined; |
|
349 let options = {tmpPath: tmp_file_name}; |
|
350 OS.File.writeAtomic(path, readResult.buffer, options); |
|
351 } catch (x) { |
|
352 exn = x; |
|
353 } |
|
354 ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is undefined"); |
|
355 |
|
356 // Check that writeAtomic fails when destination path is an empty string |
|
357 exn = null; |
|
358 try { |
|
359 let path = ""; |
|
360 let options = {tmpPath: tmp_file_name}; |
|
361 OS.File.writeAtomic(path, readResult.buffer, options); |
|
362 } catch (x) { |
|
363 exn = x; |
|
364 } |
|
365 ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is an empty string"); |
|
366 |
|
367 // Cleanup. |
|
368 OS.File.remove(tmp_file_name); |
|
369 } |
|
370 |
|
371 /** |
|
372 * Test that copying a file using |copy| works. |
|
373 */ |
|
374 function test_copy_existing_file() |
|
375 { |
|
376 let src_file_name = |
|
377 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", |
|
378 "worker_test_osfile_front.js"); |
|
379 let tmp_file_name = "test_osfile_front.tmp"; |
|
380 info("Starting test_copy_existing"); |
|
381 OS.File.copy(src_file_name, tmp_file_name); |
|
382 |
|
383 info("test_copy_existing: Copy complete"); |
|
384 compare_files("test_copy_existing", src_file_name, tmp_file_name); |
|
385 |
|
386 // Create a bogus file with arbitrary content, then attempt to overwrite |
|
387 // it with |copy|. |
|
388 let dest = OS.File.open(tmp_file_name, {trunc: true}); |
|
389 let buf = new Uint8Array(50); |
|
390 dest.write(buf); |
|
391 dest.close(); |
|
392 |
|
393 OS.File.copy(src_file_name, tmp_file_name); |
|
394 |
|
395 compare_files("test_copy_existing 2", src_file_name, tmp_file_name); |
|
396 |
|
397 // Attempt to overwrite with noOverwrite |
|
398 let exn; |
|
399 try { |
|
400 OS.File.copy(src_file_name, tmp_file_name, {noOverwrite: true}); |
|
401 } catch(x) { |
|
402 exn = x; |
|
403 } |
|
404 ok(!!exn, "test_copy_existing: noOverwrite prevents overwriting existing files"); |
|
405 |
|
406 info("test_copy_existing: Cleaning up"); |
|
407 OS.File.remove(tmp_file_name); |
|
408 } |
|
409 |
|
410 /** |
|
411 * Test that moving a file works. |
|
412 */ |
|
413 function test_move_file() |
|
414 { |
|
415 info("test_move_file: Starting"); |
|
416 // 1. Copy file into a temporary file |
|
417 let src_file_name = |
|
418 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", |
|
419 "worker_test_osfile_front.js"); |
|
420 let tmp_file_name = "test_osfile_front.tmp"; |
|
421 let tmp2_file_name = "test_osfile_front.tmp2"; |
|
422 OS.File.copy(src_file_name, tmp_file_name); |
|
423 |
|
424 info("test_move_file: Copy complete"); |
|
425 |
|
426 // 2. Move |
|
427 OS.File.move(tmp_file_name, tmp2_file_name); |
|
428 |
|
429 info("test_move_file: Move complete"); |
|
430 |
|
431 // 3. Check that destination exists |
|
432 compare_files("test_move_file", src_file_name, tmp2_file_name); |
|
433 |
|
434 // 4. Check that original file does not exist anymore |
|
435 let exn; |
|
436 try { |
|
437 OS.File.open(tmp_file_name); |
|
438 } catch (x) { |
|
439 exn = x; |
|
440 } |
|
441 ok(!!exn, "test_move_file: Original file has been removed"); |
|
442 |
|
443 info("test_move_file: Cleaning up"); |
|
444 OS.File.remove(tmp2_file_name); |
|
445 } |
|
446 |
|
447 function test_iter_dir() |
|
448 { |
|
449 info("test_iter_dir: Starting"); |
|
450 |
|
451 // Create a file, to be sure that it exists |
|
452 let tmp_file_name = "test_osfile_front.tmp"; |
|
453 let tmp_file = OS.File.open(tmp_file_name, {write: true, trunc:true}); |
|
454 tmp_file.close(); |
|
455 |
|
456 let parent = OS.File.getCurrentDirectory(); |
|
457 info("test_iter_dir: directory " + parent); |
|
458 let iterator = new OS.File.DirectoryIterator(parent); |
|
459 info("test_iter_dir: iterator created"); |
|
460 let encountered_tmp_file = false; |
|
461 for (let entry in iterator) { |
|
462 // Checking that |name| can be decoded properly |
|
463 info("test_iter_dir: encountering entry " + entry.name); |
|
464 |
|
465 if (entry.name == tmp_file_name) { |
|
466 encountered_tmp_file = true; |
|
467 isnot(entry.isDir, "test_iter_dir: The temporary file is not a directory"); |
|
468 isnot(entry.isSymLink, "test_iter_dir: The temporary file is not a link"); |
|
469 } |
|
470 |
|
471 let file; |
|
472 let success = true; |
|
473 try { |
|
474 file = OS.File.open(entry.path); |
|
475 } catch (x) { |
|
476 if (x.becauseNoSuchFile) { |
|
477 success = false; |
|
478 } |
|
479 } |
|
480 if (file) { |
|
481 file.close(); |
|
482 } |
|
483 ok(success, "test_iter_dir: Entry " + entry.path + " exists"); |
|
484 |
|
485 if (OS.Win) { |
|
486 let year = new Date().getFullYear(); |
|
487 let creation = entry.winCreationDate; |
|
488 ok(creation, "test_iter_dir: Windows creation date exists: " + creation); |
|
489 ok(creation.getFullYear() >= year - 1 && creation.getFullYear() <= year, "test_iter_dir: consistent creation date"); |
|
490 |
|
491 let lastWrite = entry.winLastWriteDate; |
|
492 ok(lastWrite, "test_iter_dir: Windows lastWrite date exists: " + lastWrite); |
|
493 ok(lastWrite.getFullYear() >= year - 1 && lastWrite.getFullYear() <= year, "test_iter_dir: consistent lastWrite date"); |
|
494 |
|
495 let lastAccess = entry.winLastAccessDate; |
|
496 ok(lastAccess, "test_iter_dir: Windows lastAccess date exists: " + lastAccess); |
|
497 ok(lastAccess.getFullYear() >= year - 1 && lastAccess.getFullYear() <= year, "test_iter_dir: consistent lastAccess date"); |
|
498 } |
|
499 |
|
500 } |
|
501 ok(encountered_tmp_file, "test_iter_dir: We have found the temporary file"); |
|
502 |
|
503 info("test_iter_dir: Cleaning up"); |
|
504 iterator.close(); |
|
505 |
|
506 // Testing nextBatch() |
|
507 iterator = new OS.File.DirectoryIterator(parent); |
|
508 let allentries = [x for(x in iterator)]; |
|
509 iterator.close(); |
|
510 |
|
511 ok(allentries.length >= 14, "test_iter_dir: Meta-check: the test directory should contain at least 14 items"); |
|
512 |
|
513 iterator = new OS.File.DirectoryIterator(parent); |
|
514 let firstten = iterator.nextBatch(10); |
|
515 is(firstten.length, 10, "test_iter_dir: nextBatch(10) returns 10 items"); |
|
516 for (let i = 0; i < firstten.length; ++i) { |
|
517 is(allentries[i].path, firstten[i].path, "test_iter_dir: Checking that batch returns the correct entries"); |
|
518 } |
|
519 let nextthree = iterator.nextBatch(3); |
|
520 is(nextthree.length, 3, "test_iter_dir: nextBatch(3) returns 3 items"); |
|
521 for (let i = 0; i < nextthree.length; ++i) { |
|
522 is(allentries[i + firstten.length].path, nextthree[i].path, "test_iter_dir: Checking that batch 2 returns the correct entries"); |
|
523 } |
|
524 let everythingelse = iterator.nextBatch(); |
|
525 ok(everythingelse.length >= 1, "test_iter_dir: nextBatch() returns at least one item"); |
|
526 for (let i = 0; i < everythingelse.length; ++i) { |
|
527 is(allentries[i + firstten.length + nextthree.length].path, everythingelse[i].path, "test_iter_dir: Checking that batch 3 returns the correct entries"); |
|
528 } |
|
529 is(iterator.nextBatch().length, 0, "test_iter_dir: Once there is nothing left, nextBatch returns an empty array"); |
|
530 iterator.close(); |
|
531 |
|
532 iterator = new OS.File.DirectoryIterator(parent); |
|
533 iterator.close(); |
|
534 is(iterator.nextBatch().length, 0, "test_iter_dir: nextBatch on closed iterator returns an empty array"); |
|
535 |
|
536 iterator = new OS.File.DirectoryIterator(parent); |
|
537 let allentries2 = iterator.nextBatch(); |
|
538 is(allentries.length, allentries2.length, "test_iter_dir: Checking that getBatch(null) returns the right number of entries"); |
|
539 for (let i = 0; i < allentries.length; ++i) { |
|
540 is(allentries[i].path, allentries2[i].path, "test_iter_dir: Checking that getBatch(null) returns everything in the right order"); |
|
541 } |
|
542 iterator.close(); |
|
543 |
|
544 // Test forEach |
|
545 iterator = new OS.File.DirectoryIterator(parent); |
|
546 let index = 0; |
|
547 iterator.forEach( |
|
548 function cb(entry, aIndex, aIterator) { |
|
549 is(index, aIndex, "test_iter_dir: Checking that forEach index is correct"); |
|
550 ok(iterator == aIterator, "test_iter_dir: Checking that right iterator is passed"); |
|
551 if (index < 10) { |
|
552 is(allentries[index].path, entry.path, "test_iter_dir: Checking that forEach entry is correct"); |
|
553 } else if (index == 10) { |
|
554 iterator.close(); |
|
555 } else { |
|
556 ok(false, "test_iter_dir: Checking that forEach can be stopped early"); |
|
557 } |
|
558 ++index; |
|
559 }); |
|
560 iterator.close(); |
|
561 |
|
562 //test for prototype |OS.File.DirectoryIterator.unixAsFile| |
|
563 if ("unixAsFile" in OS.File.DirectoryIterator.prototype) { |
|
564 info("testing property unixAsFile"); |
|
565 let path = OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi"); |
|
566 iterator = new OS.File.DirectoryIterator(path); |
|
567 |
|
568 let dir_file = iterator.unixAsFile();// return |File| |
|
569 let stat0 = dir_file.stat(); |
|
570 let stat1 = OS.File.stat(path); |
|
571 |
|
572 let unix_info_to_string = function unix_info_to_string(info) { |
|
573 return "| " + info.unixMode + " | " + info.unixOwner + " | " + info.unixGroup + " | " + info.creationDate + " | " + info.lastModificationDate + " | " + info.lastAccessDate + " | " + info.size + " |"; |
|
574 }; |
|
575 |
|
576 let s0_string = unix_info_to_string(stat0); |
|
577 let s1_string = unix_info_to_string(stat1); |
|
578 |
|
579 ok(stat0.isDir, "unixAsFile returned a directory"); |
|
580 is(s0_string, s1_string, "unixAsFile returned the correct file"); |
|
581 dir_file.close(); |
|
582 iterator.close(); |
|
583 } |
|
584 info("test_iter_dir: Complete"); |
|
585 } |
|
586 |
|
587 function test_position() { |
|
588 info("test_position: Starting"); |
|
589 |
|
590 ok("POS_START" in OS.File, "test_position: POS_START exists"); |
|
591 ok("POS_CURRENT" in OS.File, "test_position: POS_CURRENT exists"); |
|
592 ok("POS_END" in OS.File, "test_position: POS_END exists"); |
|
593 |
|
594 let ARBITRARY_POSITION = 321; |
|
595 let src_file_name = |
|
596 OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", |
|
597 "worker_test_osfile_front.js"); |
|
598 |
|
599 let file = OS.File.open(src_file_name); |
|
600 is(file.getPosition(), 0, "test_position: Initial position is 0"); |
|
601 |
|
602 let size = 0 + file.stat().size; // Hack: We can remove this 0 + once 776259 has landed |
|
603 |
|
604 file.setPosition(ARBITRARY_POSITION, OS.File.POS_START); |
|
605 is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position from start"); |
|
606 |
|
607 file.setPosition(0, OS.File.POS_START); |
|
608 is(file.getPosition(), 0, "test_position: Setting position from start back to 0"); |
|
609 |
|
610 file.setPosition(ARBITRARY_POSITION); |
|
611 is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position without argument"); |
|
612 |
|
613 file.setPosition(-ARBITRARY_POSITION, OS.File.POS_END); |
|
614 is(file.getPosition(), size - ARBITRARY_POSITION, "test_position: Setting position from end"); |
|
615 |
|
616 file.setPosition(ARBITRARY_POSITION, OS.File.POS_CURRENT); |
|
617 is(file.getPosition(), size, "test_position: Setting position from current"); |
|
618 |
|
619 file.close(); |
|
620 info("test_position: Complete"); |
|
621 } |
|
622 |
|
623 function test_info() { |
|
624 info("test_info: Starting"); |
|
625 |
|
626 let filename = "test_info.tmp"; |
|
627 let size = 261;// An arbitrary file length |
|
628 let start = new Date(); |
|
629 |
|
630 // Cleanup any leftover from previous tests |
|
631 try { |
|
632 OS.File.remove(filename); |
|
633 info("test_info: Cleaned up previous garbage"); |
|
634 } catch (x) { |
|
635 if (!x.becauseNoSuchFile) { |
|
636 throw x; |
|
637 } |
|
638 info("test_info: No previous garbage"); |
|
639 } |
|
640 |
|
641 let file = OS.File.open(filename, {trunc: true}); |
|
642 let buf = new ArrayBuffer(size); |
|
643 file._write(buf, size); |
|
644 file.close(); |
|
645 |
|
646 // Test OS.File.stat on new file |
|
647 let stat = OS.File.stat(filename); |
|
648 ok(!!stat, "test_info: info acquired"); |
|
649 ok(!stat.isDir, "test_info: file is not a directory"); |
|
650 is(stat.isSymLink, false, "test_info: file is not a link"); |
|
651 is(stat.size.toString(), size, "test_info: correct size"); |
|
652 |
|
653 let stop = new Date(); |
|
654 |
|
655 // We round down/up by 1s as file system precision is lower than |
|
656 // Date precision (no clear specifications about that, but it seems |
|
657 // that this can be a little over 1 second under ext3 and 2 seconds |
|
658 // under FAT). |
|
659 let SLOPPY_FILE_SYSTEM_ADJUSTMENT = 3000; |
|
660 let startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT; |
|
661 let stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT; |
|
662 info("Testing stat with bounds [ " + startMs + ", " + stopMs +" ]"); |
|
663 |
|
664 (function() { |
|
665 let birth; |
|
666 if ("winBirthDate" in stat) { |
|
667 birth = stat.winBirthDate; |
|
668 } else if ("macBirthDate" in stat) { |
|
669 birth = stat.macBirthDate; |
|
670 } else { |
|
671 ok(true, "Skipping birthdate test"); |
|
672 return; |
|
673 } |
|
674 ok(birth.getTime() <= stopMs, |
|
675 "test_info: platformBirthDate is consistent"); |
|
676 // Note: Previous versions of this test checked whether the file |
|
677 // has been created after the start of the test. Unfortunately, |
|
678 // this sometimes failed under Windows, in specific circumstances: |
|
679 // if the file has been removed at the start of the test and |
|
680 // recreated immediately, the Windows file system detects this and |
|
681 // decides that the file was actually truncated rather than |
|
682 // recreated, hence that it should keep its previous creation |
|
683 // date. Debugging hilarity ensues. |
|
684 }); |
|
685 |
|
686 let change = stat.lastModificationDate; |
|
687 info("Testing lastModificationDate: " + change); |
|
688 ok(change.getTime() >= startMs && change.getTime() <= stopMs, |
|
689 "test_info: lastModificationDate is consistent"); |
|
690 |
|
691 // Test OS.File.prototype.stat on new file |
|
692 file = OS.File.open(filename); |
|
693 try { |
|
694 stat = file.stat(); |
|
695 } finally { |
|
696 file.close(); |
|
697 } |
|
698 |
|
699 ok(!!stat, "test_info: info acquired 2"); |
|
700 ok(!stat.isDir, "test_info: file is not a directory 2"); |
|
701 ok(!stat.isSymLink, "test_info: file is not a link 2"); |
|
702 is(stat.size.toString(), size, "test_info: correct size 2"); |
|
703 |
|
704 stop = new Date(); |
|
705 |
|
706 // Round up/down as above |
|
707 startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT; |
|
708 stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT; |
|
709 info("Testing stat 2 with bounds [ " + startMs + ", " + stopMs +" ]"); |
|
710 |
|
711 let access = stat.lastAccessDate; |
|
712 info("Testing lastAccessDate: " + access); |
|
713 ok(access.getTime() >= startMs && access.getTime() <= stopMs, |
|
714 "test_info: lastAccessDate is consistent"); |
|
715 |
|
716 change = stat.lastModificationDate; |
|
717 info("Testing lastModificationDate 2: " + change); |
|
718 ok(change.getTime() >= startMs && change.getTime() <= stopMs, |
|
719 "test_info: lastModificationDate 2 is consistent"); |
|
720 |
|
721 // Test OS.File.stat on directory |
|
722 stat = OS.File.stat(OS.File.getCurrentDirectory()); |
|
723 ok(!!stat, "test_info: info on directory acquired"); |
|
724 ok(stat.isDir, "test_info: directory is a directory"); |
|
725 |
|
726 info("test_info: Complete"); |
|
727 } |
|
728 |
|
729 // Note that most of the features of path are tested in |
|
730 // worker_test_osfile_{unix, win}.js |
|
731 function test_path() |
|
732 { |
|
733 info("test_path: starting"); |
|
734 let abcd = OS.Path.join("a", "b", "c", "d"); |
|
735 is(OS.Path.basename(abcd), "d", "basename of a/b/c/d"); |
|
736 |
|
737 let abc = OS.Path.join("a", "b", "c"); |
|
738 is(OS.Path.dirname(abcd), abc, "dirname of a/b/c/d"); |
|
739 |
|
740 let abdotsc = OS.Path.join("a", "b", "..", "c"); |
|
741 is(OS.Path.normalize(abdotsc), OS.Path.join("a", "c"), "normalize a/b/../c"); |
|
742 |
|
743 let adotsdotsdots = OS.Path.join("a", "..", "..", ".."); |
|
744 is(OS.Path.normalize(adotsdotsdots), OS.Path.join("..", ".."), "normalize a/../../.."); |
|
745 |
|
746 info("test_path: Complete"); |
|
747 } |
|
748 |
|
749 /** |
|
750 * Test the file |exists| method. |
|
751 */ |
|
752 function test_exists_file() |
|
753 { |
|
754 let file_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile", |
|
755 "tests", "mochi", "test_osfile_front.xul"); |
|
756 info("test_exists_file: starting"); |
|
757 ok(OS.File.exists(file_name), "test_exists_file: file exists (OS.File.exists)"); |
|
758 ok(!OS.File.exists(file_name + ".tmp"), "test_exists_file: file does not exists (OS.File.exists)"); |
|
759 |
|
760 let dir_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile", |
|
761 "tests", "mochi"); |
|
762 ok(OS.File.exists(dir_name), "test_exists_file: directory exists"); |
|
763 ok(!OS.File.exists(dir_name) + ".tmp", "test_exists_file: directory does not exist"); |
|
764 |
|
765 info("test_exists_file: complete"); |
|
766 } |
|
767 |
|
768 /** |
|
769 * Test the file |remove| method. |
|
770 */ |
|
771 function test_remove_file() |
|
772 { |
|
773 let absent_file_name = "test_osfile_front_absent.tmp"; |
|
774 |
|
775 // Check that removing absent files is handled correctly |
|
776 let exn = should_throw(function() { |
|
777 OS.File.remove(absent_file_name, {ignoreAbsent: false}); |
|
778 }); |
|
779 ok(!!exn, "test_remove_file: throws if there is no such file"); |
|
780 |
|
781 exn = should_throw(function() { |
|
782 OS.File.remove(absent_file_name, {ignoreAbsent: true}); |
|
783 OS.File.remove(absent_file_name); |
|
784 }); |
|
785 ok(!exn, "test_remove_file: ignoreAbsent works"); |
|
786 |
|
787 if (OS.Win) { |
|
788 let file_name = "test_osfile_front_file_to_remove.tmp"; |
|
789 let file = OS.File.open(file_name, {write: true}); |
|
790 file.close(); |
|
791 ok(OS.File.exists(file_name), "test_remove_file: test file exists"); |
|
792 OS.Win.File.SetFileAttributes(file_name, |
|
793 OS.Constants.Win.FILE_ATTRIBUTE_READONLY); |
|
794 OS.File.remove(file_name); |
|
795 ok(!OS.File.exists(file_name), |
|
796 "test_remove_file: test file has been removed"); |
|
797 } |
|
798 } |