Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* Any copyright is dedicated to the Public Domain.
2 * http://creativecommons.org/publicdomain/zero/1.0/ */
4 importScripts('worker_test_osfile_shared.js');
5 importScripts("resource://gre/modules/workers/require.js");
7 let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
8 SharedAll.Config.DEBUG = true;
10 function should_throw(f) {
11 try {
12 f();
13 } catch (x) {
14 return x;
15 }
16 return null;
17 }
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 };
47 function test_init() {
48 info("Starting test_init");
49 importScripts("resource://gre/modules/osfile.jsm");
50 }
52 function test_offsetby() {
53 info("Starting test_offsetby");
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 }
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 }
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 }
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");
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*");
100 info("test_offsetby: complete");
101 }
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 }
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 }
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 }
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 }
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");
196 // read, ArrayBuffer
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;
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");
206 dest.write(buf);
208 info("test_readall_writeall_file: copy complete (manual allocation)");
209 source.close();
210 dest.close();
212 compare_files("test_readall_writeall_file (manual allocation)", src_file_name, tmp_file_name);
213 OS.File.remove(tmp_file_name);
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)");
223 dest.write(ptr, {bytes: size});
225 info("test_readall_writeall_file: copy complete (C buffer)");
226 source.close();
227 dest.close();
229 compare_files("test_readall_writeall_file (C buffer)", src_file_name, tmp_file_name);
230 OS.File.remove(tmp_file_name);
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");
240 source.close();
241 dest.close();
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});
251 readResult = source.readTo(offset_view);
252 is(readResult, LEFT, "test_readall_writeall_file: read the right number of bytes (with offset)");
254 dest.write(offset_view);
255 is(dest.stat().size, LEFT, "test_readall_writeall_file: wrote the right number of bytes (with offset)");
257 info("test_readall_writeall_file: copy complete (with offset)");
258 source.close();
259 dest.close();
261 compare_files("test_readall_writeall_file (with offset)", src_file_name, tmp_file_name, LEFT);
262 OS.File.remove(tmp_file_name);
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});
269 readResult = source.read();
270 is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (auto allocation)");
272 dest.write(readResult);
274 info("test_readall_writeall_file: copy complete (auto allocation)");
275 source.close();
276 dest.close();
278 compare_files("test_readall_writeall_file (auto allocation)", src_file_name, tmp_file_name);
279 OS.File.remove(tmp_file_name);
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)");
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");
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();
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);
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);
333 // Ensure that File.writeAtomic fails if no temporary file name is provided
334 // (FIXME: Remove this test as part of bug 793660)
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");
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");
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");
367 // Cleanup.
368 OS.File.remove(tmp_file_name);
369 }
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);
383 info("test_copy_existing: Copy complete");
384 compare_files("test_copy_existing", src_file_name, tmp_file_name);
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();
393 OS.File.copy(src_file_name, tmp_file_name);
395 compare_files("test_copy_existing 2", src_file_name, tmp_file_name);
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");
406 info("test_copy_existing: Cleaning up");
407 OS.File.remove(tmp_file_name);
408 }
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);
424 info("test_move_file: Copy complete");
426 // 2. Move
427 OS.File.move(tmp_file_name, tmp2_file_name);
429 info("test_move_file: Move complete");
431 // 3. Check that destination exists
432 compare_files("test_move_file", src_file_name, tmp2_file_name);
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");
443 info("test_move_file: Cleaning up");
444 OS.File.remove(tmp2_file_name);
445 }
447 function test_iter_dir()
448 {
449 info("test_iter_dir: Starting");
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();
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);
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 }
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");
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");
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");
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 }
500 }
501 ok(encountered_tmp_file, "test_iter_dir: We have found the temporary file");
503 info("test_iter_dir: Cleaning up");
504 iterator.close();
506 // Testing nextBatch()
507 iterator = new OS.File.DirectoryIterator(parent);
508 let allentries = [x for(x in iterator)];
509 iterator.close();
511 ok(allentries.length >= 14, "test_iter_dir: Meta-check: the test directory should contain at least 14 items");
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();
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");
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();
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();
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);
568 let dir_file = iterator.unixAsFile();// return |File|
569 let stat0 = dir_file.stat();
570 let stat1 = OS.File.stat(path);
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 };
576 let s0_string = unix_info_to_string(stat0);
577 let s1_string = unix_info_to_string(stat1);
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 }
587 function test_position() {
588 info("test_position: Starting");
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");
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");
599 let file = OS.File.open(src_file_name);
600 is(file.getPosition(), 0, "test_position: Initial position is 0");
602 let size = 0 + file.stat().size; // Hack: We can remove this 0 + once 776259 has landed
604 file.setPosition(ARBITRARY_POSITION, OS.File.POS_START);
605 is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position from start");
607 file.setPosition(0, OS.File.POS_START);
608 is(file.getPosition(), 0, "test_position: Setting position from start back to 0");
610 file.setPosition(ARBITRARY_POSITION);
611 is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position without argument");
613 file.setPosition(-ARBITRARY_POSITION, OS.File.POS_END);
614 is(file.getPosition(), size - ARBITRARY_POSITION, "test_position: Setting position from end");
616 file.setPosition(ARBITRARY_POSITION, OS.File.POS_CURRENT);
617 is(file.getPosition(), size, "test_position: Setting position from current");
619 file.close();
620 info("test_position: Complete");
621 }
623 function test_info() {
624 info("test_info: Starting");
626 let filename = "test_info.tmp";
627 let size = 261;// An arbitrary file length
628 let start = new Date();
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 }
641 let file = OS.File.open(filename, {trunc: true});
642 let buf = new ArrayBuffer(size);
643 file._write(buf, size);
644 file.close();
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");
653 let stop = new Date();
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 +" ]");
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 });
686 let change = stat.lastModificationDate;
687 info("Testing lastModificationDate: " + change);
688 ok(change.getTime() >= startMs && change.getTime() <= stopMs,
689 "test_info: lastModificationDate is consistent");
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 }
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");
704 stop = new Date();
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 +" ]");
711 let access = stat.lastAccessDate;
712 info("Testing lastAccessDate: " + access);
713 ok(access.getTime() >= startMs && access.getTime() <= stopMs,
714 "test_info: lastAccessDate is consistent");
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");
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");
726 info("test_info: Complete");
727 }
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");
737 let abc = OS.Path.join("a", "b", "c");
738 is(OS.Path.dirname(abcd), abc, "dirname of a/b/c/d");
740 let abdotsc = OS.Path.join("a", "b", "..", "c");
741 is(OS.Path.normalize(abdotsc), OS.Path.join("a", "c"), "normalize a/b/../c");
743 let adotsdotsdots = OS.Path.join("a", "..", "..", "..");
744 is(OS.Path.normalize(adotsdotsdots), OS.Path.join("..", ".."), "normalize a/../../..");
746 info("test_path: Complete");
747 }
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)");
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");
765 info("test_exists_file: complete");
766 }
768 /**
769 * Test the file |remove| method.
770 */
771 function test_remove_file()
772 {
773 let absent_file_name = "test_osfile_front_absent.tmp";
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");
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");
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 }