toolkit/components/osfile/tests/mochi/worker_test_osfile_front.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 }

mercurial