michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: importScripts('worker_test_osfile_shared.js'); michael@0: importScripts("resource://gre/modules/workers/require.js"); michael@0: michael@0: let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); michael@0: SharedAll.Config.DEBUG = true; michael@0: michael@0: function should_throw(f) { michael@0: try { michael@0: f(); michael@0: } catch (x) { michael@0: return x; michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: self.onmessage = function onmessage_start(msg) { michael@0: self.onmessage = function onmessage_ignored(msg) { michael@0: log("ignored message " + JSON.stringify(msg.data)); michael@0: }; michael@0: try { michael@0: test_init(); michael@0: test_offsetby(); michael@0: test_open_existing_file(); michael@0: test_open_non_existing_file(); michael@0: test_flush_open_file(); michael@0: test_copy_existing_file(); michael@0: test_readall_writeall_file(); michael@0: test_position(); michael@0: test_move_file(); michael@0: test_iter_dir(); michael@0: test_info(); michael@0: test_path(); michael@0: test_exists_file(); michael@0: test_remove_file(); michael@0: } catch (x) { michael@0: log("Catching error: " + x); michael@0: log("Stack: " + x.stack); michael@0: log("Source: " + x.toSource()); michael@0: ok(false, x.toString() + "\n" + x.stack); michael@0: } michael@0: finish(); michael@0: }; michael@0: michael@0: function test_init() { michael@0: info("Starting test_init"); michael@0: importScripts("resource://gre/modules/osfile.jsm"); michael@0: } michael@0: michael@0: function test_offsetby() { michael@0: info("Starting test_offsetby"); michael@0: michael@0: // Initialize one array michael@0: let LENGTH = 1024; michael@0: let buf = new ArrayBuffer(LENGTH); michael@0: let view = new Uint8Array(buf); michael@0: let i; michael@0: for (i = 0; i < LENGTH; ++i) { michael@0: view[i] = i; michael@0: } michael@0: michael@0: // Walk through the array with offsetBy by 8 bits michael@0: let uint8 = SharedAll.Type.uint8_t.in_ptr.implementation(buf); michael@0: for (i = 0; i < LENGTH; ++i) { michael@0: let value = SharedAll.offsetBy(uint8, i).contents; michael@0: if (value != i%256) { michael@0: is(value, i % 256, "test_offsetby: Walking through array with offsetBy (8 bits)"); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // Walk again by 16 bits michael@0: let uint16 = SharedAll.Type.uint16_t.in_ptr.implementation(buf); michael@0: let view2 = new Uint16Array(buf); michael@0: for (i = 0; i < LENGTH/2; ++i) { michael@0: let value = SharedAll.offsetBy(uint16, i).contents; michael@0: if (value != view2[i]) { michael@0: is(value, view2[i], "test_offsetby: Walking through array with offsetBy (16 bits)"); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // Ensure that offsetBy(..., 0) is idempotent michael@0: let startptr = SharedAll.offsetBy(uint8, 0); michael@0: let startptr2 = SharedAll.offsetBy(startptr, 0); michael@0: is(startptr.toString(), startptr2.toString(), "test_offsetby: offsetBy(..., 0) is idmpotent"); michael@0: michael@0: // Ensure that offsetBy(ptr, ...) does not work if ptr is a void* michael@0: let ptr = ctypes.voidptr_t(0); michael@0: let exn; michael@0: try { michael@0: SharedAll.offsetBy(ptr, 1); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn, "test_offsetby: rejected offsetBy with void*"); michael@0: michael@0: info("test_offsetby: complete"); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Test that we can open an existing file. michael@0: */ michael@0: function test_open_existing_file() michael@0: { michael@0: info("Starting test_open_existing"); michael@0: let file = OS.File.open("chrome/toolkit/components/osfile/tests/mochi/worker_test_osfile_unix.js"); michael@0: file.close(); michael@0: } michael@0: michael@0: /** michael@0: * Test that opening a file that does not exist fails with the right error. michael@0: */ michael@0: function test_open_non_existing_file() michael@0: { michael@0: info("Starting test_open_non_existing"); michael@0: let exn; michael@0: try { michael@0: let file = OS.File.open("/I do not exist"); michael@0: } catch (x) { michael@0: exn = x; michael@0: info("test_open_non_existing_file: Exception detail " + exn); michael@0: } michael@0: ok(!!exn, "test_open_non_existing_file: Exception was raised "); michael@0: ok(exn instanceof OS.File.Error, "test_open_non_existing_file: Exception was a OS.File.Error"); michael@0: ok(exn.becauseNoSuchFile, "test_open_non_existing_file: Exception confirms that the file does not exist"); michael@0: } michael@0: michael@0: /** michael@0: * Test that to ensure that |foo.flush()| does not michael@0: * cause an error, where |foo| is an open file. michael@0: */ michael@0: function test_flush_open_file() michael@0: { michael@0: info("Starting test_flush_open_file"); michael@0: let tmp = "test_flush.tmp"; michael@0: let file = OS.File.open(tmp, {create: true, write: true}); michael@0: file.flush(); michael@0: file.close(); michael@0: OS.File.remove(tmp); michael@0: } michael@0: michael@0: /** michael@0: * Utility function for comparing two files (or a prefix of two files). michael@0: * michael@0: * This function returns nothing but fails of both files (or prefixes) michael@0: * are not identical. michael@0: * michael@0: * @param {string} test The name of the test (used for logging). michael@0: * @param {string} sourcePath The name of the first file. michael@0: * @param {string} destPath The name of the second file. michael@0: * @param {number=} prefix If specified, only compare the |prefix| michael@0: * first bytes of |sourcePath| and |destPath|. michael@0: */ michael@0: function compare_files(test, sourcePath, destPath, prefix) michael@0: { michael@0: info(test + ": Comparing " + sourcePath + " and " + destPath); michael@0: let source = OS.File.open(sourcePath); michael@0: let dest = OS.File.open(destPath); michael@0: info("Files are open"); michael@0: let sourceResult, destResult; michael@0: try { michael@0: if (prefix != undefined) { michael@0: sourceResult = source.read(prefix); michael@0: destResult = dest.read(prefix); michael@0: } else { michael@0: sourceResult = source.read(); michael@0: destResult = dest.read(); michael@0: } michael@0: is(sourceResult.length, destResult.length, test + ": Both files have the same size"); michael@0: for (let i = 0; i < sourceResult.length; ++i) { michael@0: if (sourceResult[i] != destResult[i]) { michael@0: is(sourceResult[i] != destResult[i], test + ": Comparing char " + i); michael@0: break; michael@0: } michael@0: } michael@0: } finally { michael@0: source.close(); michael@0: dest.close(); michael@0: } michael@0: info(test + ": Comparison complete"); michael@0: } michael@0: michael@0: function test_readall_writeall_file() michael@0: { michael@0: let src_file_name = michael@0: OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", michael@0: "worker_test_osfile_front.js"); michael@0: let tmp_file_name = michael@0: OS.Path.join(OS.Constants.Path.tmpDir, "test_osfile_front.tmp"); michael@0: info("Starting test_readall_writeall_file"); michael@0: michael@0: // read, ArrayBuffer michael@0: michael@0: let source = OS.File.open(src_file_name); michael@0: let dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: let size = source.stat().size; michael@0: michael@0: let buf = new Uint8Array(size); michael@0: let readResult = source.readTo(buf); michael@0: is(readResult, size, "test_readall_writeall_file: read the right number of bytes"); michael@0: michael@0: dest.write(buf); michael@0: michael@0: info("test_readall_writeall_file: copy complete (manual allocation)"); michael@0: source.close(); michael@0: dest.close(); michael@0: michael@0: compare_files("test_readall_writeall_file (manual allocation)", src_file_name, tmp_file_name); michael@0: OS.File.remove(tmp_file_name); michael@0: michael@0: // read, C buffer michael@0: source = OS.File.open(src_file_name); michael@0: dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: buf = new ArrayBuffer(size); michael@0: let ptr = OS.Shared.Type.voidptr_t.implementation(buf); michael@0: readResult = source.readTo(ptr, {bytes: size}); michael@0: is(readResult, size, "test_readall_writeall_file: read the right number of bytes (C buffer)"); michael@0: michael@0: dest.write(ptr, {bytes: size}); michael@0: michael@0: info("test_readall_writeall_file: copy complete (C buffer)"); michael@0: source.close(); michael@0: dest.close(); michael@0: michael@0: compare_files("test_readall_writeall_file (C buffer)", src_file_name, tmp_file_name); michael@0: OS.File.remove(tmp_file_name); michael@0: michael@0: // read/write, C buffer, missing |bytes| option michael@0: source = OS.File.open(src_file_name); michael@0: dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: let exn = should_throw(function() { source.readTo(ptr); }); michael@0: ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: read with C pointer and without bytes fails with the correct error"); michael@0: exn = should_throw(function() { dest.write(ptr); }); michael@0: ok(exn != null && exn instanceof TypeError, "test_readall_writeall_file: write with C pointer and without bytes fails with the correct error"); michael@0: michael@0: source.close(); michael@0: dest.close(); michael@0: michael@0: // readTo, ArrayBuffer + offset michael@0: let OFFSET = 12; michael@0: let LEFT = size - OFFSET; michael@0: buf = new ArrayBuffer(size); michael@0: let offset_view = new Uint8Array(buf, OFFSET); michael@0: source = OS.File.open(src_file_name); michael@0: dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: michael@0: readResult = source.readTo(offset_view); michael@0: is(readResult, LEFT, "test_readall_writeall_file: read the right number of bytes (with offset)"); michael@0: michael@0: dest.write(offset_view); michael@0: is(dest.stat().size, LEFT, "test_readall_writeall_file: wrote the right number of bytes (with offset)"); michael@0: michael@0: info("test_readall_writeall_file: copy complete (with offset)"); michael@0: source.close(); michael@0: dest.close(); michael@0: michael@0: compare_files("test_readall_writeall_file (with offset)", src_file_name, tmp_file_name, LEFT); michael@0: OS.File.remove(tmp_file_name); michael@0: michael@0: // read michael@0: buf = new Uint8Array(size); michael@0: source = OS.File.open(src_file_name); michael@0: dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: michael@0: readResult = source.read(); michael@0: is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (auto allocation)"); michael@0: michael@0: dest.write(readResult); michael@0: michael@0: info("test_readall_writeall_file: copy complete (auto allocation)"); michael@0: source.close(); michael@0: dest.close(); michael@0: michael@0: compare_files("test_readall_writeall_file (auto allocation)", src_file_name, tmp_file_name); michael@0: OS.File.remove(tmp_file_name); michael@0: michael@0: // File.readAll michael@0: readResult = OS.File.read(src_file_name); michael@0: is(readResult.length, size, "test_readall_writeall_file: read the right number of bytes (OS.File.readAll)"); michael@0: michael@0: // File.writeAtomic on top of nothing michael@0: OS.File.writeAtomic(tmp_file_name, readResult, michael@0: {tmpPath: tmp_file_name + ".tmp"}); michael@0: try { michael@0: let stat = OS.File.stat(tmp_file_name); michael@0: info("readAll + writeAtomic created a file"); michael@0: is(stat.size, size, "readAll + writeAtomic created a file of the right size"); michael@0: } catch (x) { michael@0: ok(false, "readAll + writeAtomic somehow failed"); michael@0: if(x.becauseNoSuchFile) { michael@0: ok(false, "readAll + writeAtomic did not create file"); michael@0: } michael@0: } michael@0: compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic)", michael@0: src_file_name, tmp_file_name); michael@0: exn = null; michael@0: try { michael@0: let stat = OS.File.stat(tmp_file_name + ".tmp"); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn, "readAll + writeAtomic cleaned up after itself"); michael@0: michael@0: // File.writeAtomic on top of existing file michael@0: // Remove content and set arbitrary size, to avoid potential false negatives michael@0: dest = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: dest.setPosition(1234); michael@0: dest.close(); michael@0: michael@0: OS.File.writeAtomic(tmp_file_name, readResult, michael@0: {tmpPath: tmp_file_name + ".tmp"}); michael@0: compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic 2)", michael@0: src_file_name, tmp_file_name); michael@0: michael@0: // File.writeAtomic on top of existing file but without overwritten the file michael@0: exn = null; michael@0: try { michael@0: let view = new Uint8Array(readResult.buffer, 10, 200); michael@0: OS.File.writeAtomic(tmp_file_name, view, michael@0: { tmpPath: tmp_file_name + ".tmp", noOverwrite: true}); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(exn && exn instanceof OS.File.Error && exn.becauseExists, "writeAtomic fails if file already exists with noOverwrite option"); michael@0: // Check file was not overwritten. michael@0: compare_files("test_readall_writeall_file (OS.File.readAll + writeAtomic check file was not overwritten)", michael@0: src_file_name, tmp_file_name); michael@0: michael@0: // Ensure that File.writeAtomic fails if no temporary file name is provided michael@0: // (FIXME: Remove this test as part of bug 793660) michael@0: michael@0: exn = null; michael@0: try { michael@0: OS.File.writeAtomic(tmp_file_name, readResult.buffer, michael@0: {bytes: readResult.length}); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn && exn instanceof TypeError, "writeAtomic fails if tmpPath is not provided"); michael@0: michael@0: // Check that writeAtomic fails when destination path is undefined michael@0: exn = null; michael@0: try { michael@0: let path = undefined; michael@0: let options = {tmpPath: tmp_file_name}; michael@0: OS.File.writeAtomic(path, readResult.buffer, options); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is undefined"); michael@0: michael@0: // Check that writeAtomic fails when destination path is an empty string michael@0: exn = null; michael@0: try { michael@0: let path = ""; michael@0: let options = {tmpPath: tmp_file_name}; michael@0: OS.File.writeAtomic(path, readResult.buffer, options); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn && exn instanceof TypeError, "writeAtomic fails if path is an empty string"); michael@0: michael@0: // Cleanup. michael@0: OS.File.remove(tmp_file_name); michael@0: } michael@0: michael@0: /** michael@0: * Test that copying a file using |copy| works. michael@0: */ michael@0: function test_copy_existing_file() michael@0: { michael@0: let src_file_name = michael@0: OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", michael@0: "worker_test_osfile_front.js"); michael@0: let tmp_file_name = "test_osfile_front.tmp"; michael@0: info("Starting test_copy_existing"); michael@0: OS.File.copy(src_file_name, tmp_file_name); michael@0: michael@0: info("test_copy_existing: Copy complete"); michael@0: compare_files("test_copy_existing", src_file_name, tmp_file_name); michael@0: michael@0: // Create a bogus file with arbitrary content, then attempt to overwrite michael@0: // it with |copy|. michael@0: let dest = OS.File.open(tmp_file_name, {trunc: true}); michael@0: let buf = new Uint8Array(50); michael@0: dest.write(buf); michael@0: dest.close(); michael@0: michael@0: OS.File.copy(src_file_name, tmp_file_name); michael@0: michael@0: compare_files("test_copy_existing 2", src_file_name, tmp_file_name); michael@0: michael@0: // Attempt to overwrite with noOverwrite michael@0: let exn; michael@0: try { michael@0: OS.File.copy(src_file_name, tmp_file_name, {noOverwrite: true}); michael@0: } catch(x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn, "test_copy_existing: noOverwrite prevents overwriting existing files"); michael@0: michael@0: info("test_copy_existing: Cleaning up"); michael@0: OS.File.remove(tmp_file_name); michael@0: } michael@0: michael@0: /** michael@0: * Test that moving a file works. michael@0: */ michael@0: function test_move_file() michael@0: { michael@0: info("test_move_file: Starting"); michael@0: // 1. Copy file into a temporary file michael@0: let src_file_name = michael@0: OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", michael@0: "worker_test_osfile_front.js"); michael@0: let tmp_file_name = "test_osfile_front.tmp"; michael@0: let tmp2_file_name = "test_osfile_front.tmp2"; michael@0: OS.File.copy(src_file_name, tmp_file_name); michael@0: michael@0: info("test_move_file: Copy complete"); michael@0: michael@0: // 2. Move michael@0: OS.File.move(tmp_file_name, tmp2_file_name); michael@0: michael@0: info("test_move_file: Move complete"); michael@0: michael@0: // 3. Check that destination exists michael@0: compare_files("test_move_file", src_file_name, tmp2_file_name); michael@0: michael@0: // 4. Check that original file does not exist anymore michael@0: let exn; michael@0: try { michael@0: OS.File.open(tmp_file_name); michael@0: } catch (x) { michael@0: exn = x; michael@0: } michael@0: ok(!!exn, "test_move_file: Original file has been removed"); michael@0: michael@0: info("test_move_file: Cleaning up"); michael@0: OS.File.remove(tmp2_file_name); michael@0: } michael@0: michael@0: function test_iter_dir() michael@0: { michael@0: info("test_iter_dir: Starting"); michael@0: michael@0: // Create a file, to be sure that it exists michael@0: let tmp_file_name = "test_osfile_front.tmp"; michael@0: let tmp_file = OS.File.open(tmp_file_name, {write: true, trunc:true}); michael@0: tmp_file.close(); michael@0: michael@0: let parent = OS.File.getCurrentDirectory(); michael@0: info("test_iter_dir: directory " + parent); michael@0: let iterator = new OS.File.DirectoryIterator(parent); michael@0: info("test_iter_dir: iterator created"); michael@0: let encountered_tmp_file = false; michael@0: for (let entry in iterator) { michael@0: // Checking that |name| can be decoded properly michael@0: info("test_iter_dir: encountering entry " + entry.name); michael@0: michael@0: if (entry.name == tmp_file_name) { michael@0: encountered_tmp_file = true; michael@0: isnot(entry.isDir, "test_iter_dir: The temporary file is not a directory"); michael@0: isnot(entry.isSymLink, "test_iter_dir: The temporary file is not a link"); michael@0: } michael@0: michael@0: let file; michael@0: let success = true; michael@0: try { michael@0: file = OS.File.open(entry.path); michael@0: } catch (x) { michael@0: if (x.becauseNoSuchFile) { michael@0: success = false; michael@0: } michael@0: } michael@0: if (file) { michael@0: file.close(); michael@0: } michael@0: ok(success, "test_iter_dir: Entry " + entry.path + " exists"); michael@0: michael@0: if (OS.Win) { michael@0: let year = new Date().getFullYear(); michael@0: let creation = entry.winCreationDate; michael@0: ok(creation, "test_iter_dir: Windows creation date exists: " + creation); michael@0: ok(creation.getFullYear() >= year - 1 && creation.getFullYear() <= year, "test_iter_dir: consistent creation date"); michael@0: michael@0: let lastWrite = entry.winLastWriteDate; michael@0: ok(lastWrite, "test_iter_dir: Windows lastWrite date exists: " + lastWrite); michael@0: ok(lastWrite.getFullYear() >= year - 1 && lastWrite.getFullYear() <= year, "test_iter_dir: consistent lastWrite date"); michael@0: michael@0: let lastAccess = entry.winLastAccessDate; michael@0: ok(lastAccess, "test_iter_dir: Windows lastAccess date exists: " + lastAccess); michael@0: ok(lastAccess.getFullYear() >= year - 1 && lastAccess.getFullYear() <= year, "test_iter_dir: consistent lastAccess date"); michael@0: } michael@0: michael@0: } michael@0: ok(encountered_tmp_file, "test_iter_dir: We have found the temporary file"); michael@0: michael@0: info("test_iter_dir: Cleaning up"); michael@0: iterator.close(); michael@0: michael@0: // Testing nextBatch() michael@0: iterator = new OS.File.DirectoryIterator(parent); michael@0: let allentries = [x for(x in iterator)]; michael@0: iterator.close(); michael@0: michael@0: ok(allentries.length >= 14, "test_iter_dir: Meta-check: the test directory should contain at least 14 items"); michael@0: michael@0: iterator = new OS.File.DirectoryIterator(parent); michael@0: let firstten = iterator.nextBatch(10); michael@0: is(firstten.length, 10, "test_iter_dir: nextBatch(10) returns 10 items"); michael@0: for (let i = 0; i < firstten.length; ++i) { michael@0: is(allentries[i].path, firstten[i].path, "test_iter_dir: Checking that batch returns the correct entries"); michael@0: } michael@0: let nextthree = iterator.nextBatch(3); michael@0: is(nextthree.length, 3, "test_iter_dir: nextBatch(3) returns 3 items"); michael@0: for (let i = 0; i < nextthree.length; ++i) { michael@0: is(allentries[i + firstten.length].path, nextthree[i].path, "test_iter_dir: Checking that batch 2 returns the correct entries"); michael@0: } michael@0: let everythingelse = iterator.nextBatch(); michael@0: ok(everythingelse.length >= 1, "test_iter_dir: nextBatch() returns at least one item"); michael@0: for (let i = 0; i < everythingelse.length; ++i) { michael@0: is(allentries[i + firstten.length + nextthree.length].path, everythingelse[i].path, "test_iter_dir: Checking that batch 3 returns the correct entries"); michael@0: } michael@0: is(iterator.nextBatch().length, 0, "test_iter_dir: Once there is nothing left, nextBatch returns an empty array"); michael@0: iterator.close(); michael@0: michael@0: iterator = new OS.File.DirectoryIterator(parent); michael@0: iterator.close(); michael@0: is(iterator.nextBatch().length, 0, "test_iter_dir: nextBatch on closed iterator returns an empty array"); michael@0: michael@0: iterator = new OS.File.DirectoryIterator(parent); michael@0: let allentries2 = iterator.nextBatch(); michael@0: is(allentries.length, allentries2.length, "test_iter_dir: Checking that getBatch(null) returns the right number of entries"); michael@0: for (let i = 0; i < allentries.length; ++i) { michael@0: is(allentries[i].path, allentries2[i].path, "test_iter_dir: Checking that getBatch(null) returns everything in the right order"); michael@0: } michael@0: iterator.close(); michael@0: michael@0: // Test forEach michael@0: iterator = new OS.File.DirectoryIterator(parent); michael@0: let index = 0; michael@0: iterator.forEach( michael@0: function cb(entry, aIndex, aIterator) { michael@0: is(index, aIndex, "test_iter_dir: Checking that forEach index is correct"); michael@0: ok(iterator == aIterator, "test_iter_dir: Checking that right iterator is passed"); michael@0: if (index < 10) { michael@0: is(allentries[index].path, entry.path, "test_iter_dir: Checking that forEach entry is correct"); michael@0: } else if (index == 10) { michael@0: iterator.close(); michael@0: } else { michael@0: ok(false, "test_iter_dir: Checking that forEach can be stopped early"); michael@0: } michael@0: ++index; michael@0: }); michael@0: iterator.close(); michael@0: michael@0: //test for prototype |OS.File.DirectoryIterator.unixAsFile| michael@0: if ("unixAsFile" in OS.File.DirectoryIterator.prototype) { michael@0: info("testing property unixAsFile"); michael@0: let path = OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi"); michael@0: iterator = new OS.File.DirectoryIterator(path); michael@0: michael@0: let dir_file = iterator.unixAsFile();// return |File| michael@0: let stat0 = dir_file.stat(); michael@0: let stat1 = OS.File.stat(path); michael@0: michael@0: let unix_info_to_string = function unix_info_to_string(info) { michael@0: return "| " + info.unixMode + " | " + info.unixOwner + " | " + info.unixGroup + " | " + info.creationDate + " | " + info.lastModificationDate + " | " + info.lastAccessDate + " | " + info.size + " |"; michael@0: }; michael@0: michael@0: let s0_string = unix_info_to_string(stat0); michael@0: let s1_string = unix_info_to_string(stat1); michael@0: michael@0: ok(stat0.isDir, "unixAsFile returned a directory"); michael@0: is(s0_string, s1_string, "unixAsFile returned the correct file"); michael@0: dir_file.close(); michael@0: iterator.close(); michael@0: } michael@0: info("test_iter_dir: Complete"); michael@0: } michael@0: michael@0: function test_position() { michael@0: info("test_position: Starting"); michael@0: michael@0: ok("POS_START" in OS.File, "test_position: POS_START exists"); michael@0: ok("POS_CURRENT" in OS.File, "test_position: POS_CURRENT exists"); michael@0: ok("POS_END" in OS.File, "test_position: POS_END exists"); michael@0: michael@0: let ARBITRARY_POSITION = 321; michael@0: let src_file_name = michael@0: OS.Path.join("chrome", "toolkit", "components", "osfile", "tests", "mochi", michael@0: "worker_test_osfile_front.js"); michael@0: michael@0: let file = OS.File.open(src_file_name); michael@0: is(file.getPosition(), 0, "test_position: Initial position is 0"); michael@0: michael@0: let size = 0 + file.stat().size; // Hack: We can remove this 0 + once 776259 has landed michael@0: michael@0: file.setPosition(ARBITRARY_POSITION, OS.File.POS_START); michael@0: is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position from start"); michael@0: michael@0: file.setPosition(0, OS.File.POS_START); michael@0: is(file.getPosition(), 0, "test_position: Setting position from start back to 0"); michael@0: michael@0: file.setPosition(ARBITRARY_POSITION); michael@0: is(file.getPosition(), ARBITRARY_POSITION, "test_position: Setting position without argument"); michael@0: michael@0: file.setPosition(-ARBITRARY_POSITION, OS.File.POS_END); michael@0: is(file.getPosition(), size - ARBITRARY_POSITION, "test_position: Setting position from end"); michael@0: michael@0: file.setPosition(ARBITRARY_POSITION, OS.File.POS_CURRENT); michael@0: is(file.getPosition(), size, "test_position: Setting position from current"); michael@0: michael@0: file.close(); michael@0: info("test_position: Complete"); michael@0: } michael@0: michael@0: function test_info() { michael@0: info("test_info: Starting"); michael@0: michael@0: let filename = "test_info.tmp"; michael@0: let size = 261;// An arbitrary file length michael@0: let start = new Date(); michael@0: michael@0: // Cleanup any leftover from previous tests michael@0: try { michael@0: OS.File.remove(filename); michael@0: info("test_info: Cleaned up previous garbage"); michael@0: } catch (x) { michael@0: if (!x.becauseNoSuchFile) { michael@0: throw x; michael@0: } michael@0: info("test_info: No previous garbage"); michael@0: } michael@0: michael@0: let file = OS.File.open(filename, {trunc: true}); michael@0: let buf = new ArrayBuffer(size); michael@0: file._write(buf, size); michael@0: file.close(); michael@0: michael@0: // Test OS.File.stat on new file michael@0: let stat = OS.File.stat(filename); michael@0: ok(!!stat, "test_info: info acquired"); michael@0: ok(!stat.isDir, "test_info: file is not a directory"); michael@0: is(stat.isSymLink, false, "test_info: file is not a link"); michael@0: is(stat.size.toString(), size, "test_info: correct size"); michael@0: michael@0: let stop = new Date(); michael@0: michael@0: // We round down/up by 1s as file system precision is lower than michael@0: // Date precision (no clear specifications about that, but it seems michael@0: // that this can be a little over 1 second under ext3 and 2 seconds michael@0: // under FAT). michael@0: let SLOPPY_FILE_SYSTEM_ADJUSTMENT = 3000; michael@0: let startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT; michael@0: let stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT; michael@0: info("Testing stat with bounds [ " + startMs + ", " + stopMs +" ]"); michael@0: michael@0: (function() { michael@0: let birth; michael@0: if ("winBirthDate" in stat) { michael@0: birth = stat.winBirthDate; michael@0: } else if ("macBirthDate" in stat) { michael@0: birth = stat.macBirthDate; michael@0: } else { michael@0: ok(true, "Skipping birthdate test"); michael@0: return; michael@0: } michael@0: ok(birth.getTime() <= stopMs, michael@0: "test_info: platformBirthDate is consistent"); michael@0: // Note: Previous versions of this test checked whether the file michael@0: // has been created after the start of the test. Unfortunately, michael@0: // this sometimes failed under Windows, in specific circumstances: michael@0: // if the file has been removed at the start of the test and michael@0: // recreated immediately, the Windows file system detects this and michael@0: // decides that the file was actually truncated rather than michael@0: // recreated, hence that it should keep its previous creation michael@0: // date. Debugging hilarity ensues. michael@0: }); michael@0: michael@0: let change = stat.lastModificationDate; michael@0: info("Testing lastModificationDate: " + change); michael@0: ok(change.getTime() >= startMs && change.getTime() <= stopMs, michael@0: "test_info: lastModificationDate is consistent"); michael@0: michael@0: // Test OS.File.prototype.stat on new file michael@0: file = OS.File.open(filename); michael@0: try { michael@0: stat = file.stat(); michael@0: } finally { michael@0: file.close(); michael@0: } michael@0: michael@0: ok(!!stat, "test_info: info acquired 2"); michael@0: ok(!stat.isDir, "test_info: file is not a directory 2"); michael@0: ok(!stat.isSymLink, "test_info: file is not a link 2"); michael@0: is(stat.size.toString(), size, "test_info: correct size 2"); michael@0: michael@0: stop = new Date(); michael@0: michael@0: // Round up/down as above michael@0: startMs = start.getTime() - SLOPPY_FILE_SYSTEM_ADJUSTMENT; michael@0: stopMs = stop.getTime() + SLOPPY_FILE_SYSTEM_ADJUSTMENT; michael@0: info("Testing stat 2 with bounds [ " + startMs + ", " + stopMs +" ]"); michael@0: michael@0: let access = stat.lastAccessDate; michael@0: info("Testing lastAccessDate: " + access); michael@0: ok(access.getTime() >= startMs && access.getTime() <= stopMs, michael@0: "test_info: lastAccessDate is consistent"); michael@0: michael@0: change = stat.lastModificationDate; michael@0: info("Testing lastModificationDate 2: " + change); michael@0: ok(change.getTime() >= startMs && change.getTime() <= stopMs, michael@0: "test_info: lastModificationDate 2 is consistent"); michael@0: michael@0: // Test OS.File.stat on directory michael@0: stat = OS.File.stat(OS.File.getCurrentDirectory()); michael@0: ok(!!stat, "test_info: info on directory acquired"); michael@0: ok(stat.isDir, "test_info: directory is a directory"); michael@0: michael@0: info("test_info: Complete"); michael@0: } michael@0: michael@0: // Note that most of the features of path are tested in michael@0: // worker_test_osfile_{unix, win}.js michael@0: function test_path() michael@0: { michael@0: info("test_path: starting"); michael@0: let abcd = OS.Path.join("a", "b", "c", "d"); michael@0: is(OS.Path.basename(abcd), "d", "basename of a/b/c/d"); michael@0: michael@0: let abc = OS.Path.join("a", "b", "c"); michael@0: is(OS.Path.dirname(abcd), abc, "dirname of a/b/c/d"); michael@0: michael@0: let abdotsc = OS.Path.join("a", "b", "..", "c"); michael@0: is(OS.Path.normalize(abdotsc), OS.Path.join("a", "c"), "normalize a/b/../c"); michael@0: michael@0: let adotsdotsdots = OS.Path.join("a", "..", "..", ".."); michael@0: is(OS.Path.normalize(adotsdotsdots), OS.Path.join("..", ".."), "normalize a/../../.."); michael@0: michael@0: info("test_path: Complete"); michael@0: } michael@0: michael@0: /** michael@0: * Test the file |exists| method. michael@0: */ michael@0: function test_exists_file() michael@0: { michael@0: let file_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile", michael@0: "tests", "mochi", "test_osfile_front.xul"); michael@0: info("test_exists_file: starting"); michael@0: ok(OS.File.exists(file_name), "test_exists_file: file exists (OS.File.exists)"); michael@0: ok(!OS.File.exists(file_name + ".tmp"), "test_exists_file: file does not exists (OS.File.exists)"); michael@0: michael@0: let dir_name = OS.Path.join("chrome", "toolkit", "components" ,"osfile", michael@0: "tests", "mochi"); michael@0: ok(OS.File.exists(dir_name), "test_exists_file: directory exists"); michael@0: ok(!OS.File.exists(dir_name) + ".tmp", "test_exists_file: directory does not exist"); michael@0: michael@0: info("test_exists_file: complete"); michael@0: } michael@0: michael@0: /** michael@0: * Test the file |remove| method. michael@0: */ michael@0: function test_remove_file() michael@0: { michael@0: let absent_file_name = "test_osfile_front_absent.tmp"; michael@0: michael@0: // Check that removing absent files is handled correctly michael@0: let exn = should_throw(function() { michael@0: OS.File.remove(absent_file_name, {ignoreAbsent: false}); michael@0: }); michael@0: ok(!!exn, "test_remove_file: throws if there is no such file"); michael@0: michael@0: exn = should_throw(function() { michael@0: OS.File.remove(absent_file_name, {ignoreAbsent: true}); michael@0: OS.File.remove(absent_file_name); michael@0: }); michael@0: ok(!exn, "test_remove_file: ignoreAbsent works"); michael@0: michael@0: if (OS.Win) { michael@0: let file_name = "test_osfile_front_file_to_remove.tmp"; michael@0: let file = OS.File.open(file_name, {write: true}); michael@0: file.close(); michael@0: ok(OS.File.exists(file_name), "test_remove_file: test file exists"); michael@0: OS.Win.File.SetFileAttributes(file_name, michael@0: OS.Constants.Win.FILE_ATTRIBUTE_READONLY); michael@0: OS.File.remove(file_name); michael@0: ok(!OS.File.exists(file_name), michael@0: "test_remove_file: test file has been removed"); michael@0: } michael@0: }