Back out changeset 9d1f0b2cede7 / Bug 581838 due to test failures on the windows boxes
authorMark Banner <bugzilla@standard8.plus.com>
Mon, 09 Aug 2010 10:40:07 +0100
changeset 6109 b5e4c1df95ef213bd6218a81cdd21dcb9980cd12
parent 6108 c2cb7f16ade972e323526bd0fcb1fd94008a31f6
child 6110 65708cb363ab952bb5148200da9eee487507a00b
push idunknown
push userunknown
push dateunknown
bugs581838
backs out9d1f0b2cede7d06d1ef5642cf2cf9fb6fc32ac54
Back out changeset 9d1f0b2cede7 / Bug 581838 due to test failures on the windows boxes
mailnews/Makefile.in
mailnews/imap/test/unit/test_largeOfflineStore.js
mailnews/test/LargeOfflineStoreHelper.cpp
mailnews/test/Makefile.in
mailnews/test/resources/mailTestUtils.js
--- a/mailnews/Makefile.in
+++ b/mailnews/Makefile.in
@@ -53,16 +53,20 @@ PARALLEL_DIRS	+= \
 	extensions\
 	imap \
 	import \
 	local \
 	mime \
 	news \
 	$(NULL)
 
+ifdef ENABLE_TESTS
+PARALLEL_DIRS	+= test
+endif
+
 ifeq ($(OS_ARCH),WINNT)
 ifndef GNU_CC
 PARALLEL_DIRS	+= mapi/mapiDLL mapi/mapihook
 endif
 endif
 
 ifdef MOZ_STATIC_MAIL_BUILD
 DIRS += build
--- a/mailnews/imap/test/unit/test_largeOfflineStore.js
+++ b/mailnews/imap/test/unit/test_largeOfflineStore.js
@@ -4,17 +4,16 @@
  * stores, i.e., > 4GB.
  */
 
 var gIMAPDaemon, gServer, gIMAPIncomingServer;
 
 const gIMAPService = Cc["@mozilla.org/messenger/messageservice;1?type=imap"]
                        .getService(Ci.nsIMsgMessageService);
 
-load("../../mailnews/resources/mailTestUtils.js");
 load("../../mailnews/resources/messageGenerator.js");
 
 var gDownloadedOnce = false;
 var gIMAPInbox;
 var gOfflineStoreSize;
 
 function run_test()
 {
@@ -31,39 +30,59 @@ function run_test()
   // pref tuning: one connection only, turn off notifications
   let prefBranch = Cc["@mozilla.org/preferences-service;1"]
                      .getService(Ci.nsIPrefBranch);
   prefBranch.setBoolPref("mail.biff.play_sound", false);
   prefBranch.setBoolPref("mail.biff.show_alert", false);
   prefBranch.setBoolPref("mail.biff.show_tray_icon", false);
   prefBranch.setBoolPref("mail.biff.animate_dock_icon", false);
 
-  // Figure out the name of the IMAP inbox
-  let inboxFile = gIMAPIncomingServer.rootMsgFolder.filePath.clone();
-  inboxFile.append("INBOX");
-  if (!inboxFile.exists())
-    inboxFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0644", 8));
-
   // On Windows, check whether the drive is NTFS. If it is, mark the file as
   // sparse. If it isn't, then bail out now, because in all probability it is
   // FAT32, which doesn't support file sizes greater than 4 GB.
-  if ("@mozilla.org/windows-registry-key;1" in Cc &&
-      get_file_system(inboxFile) != "NTFS")
+  if ("@mozilla.org/windows-registry-key;1" in Cc)
   {
-    dump("On Windows, this test only works on NTFS volumes.\n");
-    endTest();
-    return;
-  }
-  let isFileSparse = mark_file_region_sparse(inboxFile, 0, 0x10000000f);
-  if (!isFileSparse && inboxFile.diskSpaceAvailable < 0x200000000)
-  {
-    dump("On systems where files can't be marked sparse, this test needs 8 " +
-         "GB of free disk space.\n");
-    endTest();
-    return;
+    // Figure out the name of the IMAP inbox
+    let file = gIMAPIncomingServer.rootMsgFolder.filePath.clone();
+    file.append("INBOX");
+    if (!file.exists())
+      file.create(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0644", 8));
+
+    // Now call upon our helper
+    let helper = do_get_cwd().clone();
+    // '../../mailnews/LargeOfflineStoreHelper.exe'.
+    helper = helper.parent.parent;
+    helper.normalize();
+    helper.append("mailnews");
+    helper.append("LargeOfflineStoreHelper.exe");
+    if (!helper.exists()) {
+      do_throw(helper.leafName + " not found");
+    }
+
+    let helperProc = Cc["@mozilla.org/process/util;1"]
+                       .createInstance(Ci.nsIProcess);
+    helperProc.init(helper);
+    let args = [file.path];
+    // XXX This needs to be fixed to use runw once it lands (bug 411511)
+    helperProc.run(true, args, args.length);
+    let exitValue = helperProc.exitValue;
+
+    // 0 is success, 1 is "unable to run," and any other value is failure
+    if (exitValue == 1)
+    {
+      dump("On Windows, this test only works on NTFS volumes.\n");
+      endTest();
+      return;
+    }
+
+    if (exitValue != 0)
+    {
+      do_throw(helper.leafName + " failed with exit value " + exitValue +
+                 ", see above for details");
+    }
   }
 
   let inbox = gIMAPDaemon.getMailbox("INBOX");
 
   let ioService = Cc["@mozilla.org/network/io-service;1"]
                     .getService(Ci.nsIIOService);
 
   // "Master" do_test_pending(), paired with a do_test_finished() at the end of
@@ -85,16 +104,27 @@ function run_test()
   dataUri = ioService.newURI("data:text/plain;base64," +
                    btoa(messages[1].toMessageString()),
                         null, null);
   imapMsg = new imapMessage(dataUri.spec, inbox.uidnext++, []);
   inbox.addMessage(imapMsg);
 
   // Get the IMAP inbox...
   let rootFolder = gIMAPIncomingServer.rootFolder;
+  let freeDiskSpace = rootFolder.filePath.diskSpaceAvailable;
+
+  // On Windows, the file is marked as sparse above. Linux file systems
+  // generally support sparse files automatically. OS X's HFS+, however, doesn't
+  // support sparse files, so check for at least 8 GB of free disk space before
+  // consuming 4 GB.
+  if ("nsILocalFileMac" in Ci && freeDiskSpace < 0x200000000) {
+    dump("On MacOSX, this test needs 8 GB of free disk space.\n");
+    endTest();
+    return;
+  }
 
   gIMAPInbox = rootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Inbox);
   let outputStream = gIMAPInbox.offlineStoreOutputStream
                                .QueryInterface(Ci.nsISeekableStream);
   // seek to 15 bytes past 4GB.
   outputStream.seek(0, 0x10000000f);
   outputStream.write("from\r\n", 6);
   outputStream.close();
new file mode 100644
--- /dev/null
+++ b/mailnews/test/LargeOfflineStoreHelper.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Messaging, Inc.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Siddharth Agarwal <sid.bugzilla@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * A helper to large offline store tests on Windows. This:
+ *
+ * - Detects whether the volume of the given file (provided using argv[1]) is
+ *   NTFS. If it isn't, then it returns the error code 1.
+ * - If the volume is NTFS, then it proceeds to mark the given file as
+ *   sparse. It also marks the first 4 GB + 15 bytes of the file as zero.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <winioctl.h>
+
+#define SUCCESS (0)
+#define UNABLE_TO_RUN (1)
+#define FAIL (2)
+
+int markFileAsSparse(HANDLE hFile)
+{
+  // Mark the file as sparse, and mark the first 4 GB + 15 bytes as a sparse
+  // region
+  DWORD bytesReturned;
+  FILE_SET_SPARSE_BUFFER sparseBuffer = {0};
+  sparseBuffer.SetSparse = 1;
+  if (!::DeviceIoControl(hFile, FSCTL_SET_SPARSE, &sparseBuffer,
+                         sizeof(sparseBuffer), NULL, 0, &bytesReturned, NULL))
+  {
+    fprintf(stderr, "Unable to mark file as sparse, error %d\n",
+            ::GetLastError());
+    return FAIL;
+  }
+
+  LARGE_INTEGER zdStart;
+  zdStart.QuadPart = 0;
+  LARGE_INTEGER zdEnd;
+  zdEnd.QuadPart = 0x10000000fLL;
+  FILE_ZERO_DATA_INFORMATION zdInfo = {0};
+  zdInfo.FileOffset = zdStart;
+  zdInfo.BeyondFinalZero = zdEnd;
+  if (!::DeviceIoControl(hFile, FSCTL_SET_ZERO_DATA, &zdInfo, sizeof(zdInfo),
+                         NULL, 0, &bytesReturned, NULL))
+  {
+    fprintf(stderr, "Unable to mark region as zero, error %d\n",
+            ::GetLastError());
+    return FAIL;
+  }
+
+  // Move to past the sparse region and mark it as the end of the file. The
+  // above DeviceIoControl call is useless unless followed by this.
+  if (!::SetFilePointerEx(hFile, zdEnd, NULL, FILE_BEGIN))
+  {
+    fprintf(stderr, "Unable to set file pointer to end, error %d\n",
+            ::GetLastError());
+    return FAIL;
+  }
+  if (!::SetEndOfFile(hFile))
+  {
+    fprintf(stderr, "Unable to set end of file, error %d\n", ::GetLastError());
+    return FAIL;
+  }
+
+  return SUCCESS;
+}
+
+int wmain(int argc, wchar_t* argv[])
+{
+  if (argc != 2)
+    return FAIL;
+
+  // The volume path should be at most 1 greater than than the length of the
+  // path -- add 1 for a trailing backslash if necessary, and 1 for the
+  // terminating null character
+  size_t volumePathLength = wcslen(argv[1]) + 2;
+  wchar_t* volumePath = new wchar_t[volumePathLength];
+  if (!::GetVolumePathNameW(argv[1], volumePath, volumePathLength))
+  {
+    fprintf(stderr, "Unable to get volume path for %s, error %d\n", argv[1],
+            ::GetLastError());
+    return FAIL;
+  }
+
+  wchar_t fsName[MAX_PATH + 1];
+  if (!::GetVolumeInformationW(volumePath, NULL, NULL, NULL, NULL,
+                               NULL, fsName, MAX_PATH + 1))
+  {
+    fprintf(stderr, "Unable to get volume information for %s, error %d\n",
+            argv[1], ::GetLastError());
+    return FAIL;
+  }
+
+  // We're only going to run the test on NTFS
+  if (wcscmp(fsName, L"NTFS"))
+    return UNABLE_TO_RUN;
+
+  HANDLE hFile = ::CreateFileW(argv[1], GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
+                               FILE_ATTRIBUTE_NORMAL, NULL);
+
+  if (hFile == INVALID_HANDLE_VALUE)
+  {
+    fprintf(stderr, "CreateFile failed for %s, error %d\n", argv[1],
+            ::GetLastError());
+    return FAIL;
+  }
+
+  int rv = markFileAsSparse(hFile);
+  ::CloseHandle(hFile);
+  return rv;
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/test/Makefile.in
@@ -0,0 +1,61 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Messaging, Inc.
+#
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Siddharth Agarwal <sid.bugzilla@gmail.com>
+#   Serge Gautherie <sgautherie.bz@free.fr>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH     = ../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH     = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+ifeq ($(OS_ARCH),WINNT)
+CPPSRCS = \
+  LargeOfflineStoreHelper.cpp \
+  $(NULL)
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+endif # ifeq ($(OS_ARCH),WINNT)
+
+include $(topsrcdir)/config/rules.mk
+
+ifeq ($(OS_ARCH),WINNT)
+# need the executable for running the xpcshell unit tests
+libs::
+	$(INSTALL) $(SIMPLE_PROGRAMS) $(DEPTH)/mozilla/_tests/xpcshell/mailnews
+endif # ifeq ($(OS_ARCH),WINNT)
--- a/mailnews/test/resources/mailTestUtils.js
+++ b/mailnews/test/resources/mailTestUtils.js
@@ -15,17 +15,16 @@
  *
  * The Initial Developer of the Original Code is
  * Kent James <kent@caspia.com>.
  * Portions created by the Initial Developer are Copyright (C) 2008
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Mark Banner <bugzilla@standard8.plus.com>
- *   Siddharth Agarwal <sid.bugzilla@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -40,18 +39,16 @@
 var gMailTestUtils_js__;
 if (!gMailTestUtils_js__) {
 gMailTestUtils_js__ = true;
 
 // we would like for everyone to have fixIterator and toXPComArray
 Components.utils.import("resource:///modules/iteratorUtils.jsm");
 // exposes component loader's btoa impl
 Components.utils.import("resource:///modules/IOUtils.js");
-// JS ctypes, needed for a few native functions
-Components.utils.import("resource://gre/modules/ctypes.jsm");
 
 // Local Mail Folders. Requires prior setup of profile directory
 
 var gLocalIncomingServer;
 var gLocalInboxFolder;
 
 function loadLocalMailAccount()
 {
@@ -171,273 +168,16 @@ function loadFileToString(aFile, aCharse
   }
 
   fstream.close();
 
   return data;
 }
 
 /**
- * Return the file system a particular file is on. Currently only supported on
- * Windows.
- *
- * @param aFile The file to get the file system for.
- */
-function get_file_system(aFile) {
-  if (!("@mozilla.org/windows-registry-key;1" in Cc))
-    throw new Exception("get_file_system is only supported on Windows");
-
-  // Win32 type and other constants.
-  const BOOL = ctypes.int32_t;
-  const MAX_PATH = 260;
-  
-  let kernel32 = ctypes.open("kernel32.dll");
-
-  try {
-    // Returns the path of the volume a file is on.
-    let GetVolumePathName = kernel32.declare(
-      "GetVolumePathNameW",
-      ctypes.stdcall_abi,
-      BOOL,              // return type: 1 indicates success, 0 failure
-      ctypes.jschar.ptr, // in: lpszFileName
-      ctypes.jschar.ptr, // out: lpszVolumePathName
-      ctypes.uint32_t    // in: cchBufferLength
-    );
-
-    // Returns the last error.
-    let GetLastError = kernel32.declare(
-      "GetLastError",
-      ctypes.stdcall_abi,
-      ctypes.uint32_t // return type: the last error
-    );
-
-    let filePath = aFile.path;
-    // The volume path should be at most 1 greater than than the length of the
-    // path -- add 1 for a trailing backslash if necessary, and 1 for the
-    // terminating null character. Note that the parentheses around the type are
-    // necessary for new to apply correctly.
-    let volumePath = new (ctypes.jschar.array(filePath.length + 2));
-
-    if (!GetVolumePathName(filePath, volumePath, volumePath.length)) {
-      throw new Exception("Unable to get volume path for " + filePath + ", error " +
-                          GetLastError());
-    }
-
-    // Returns information about the file system for the given volume path. We just need
-    // the file system name.
-    let GetVolumeInformation = kernel32.declare(
-      "GetVolumeInformationW",
-      ctypes.stdcall_abi,
-      BOOL,                // return type: 1 indicates success, 0 failure
-      ctypes.jschar.ptr,   // in, optional: lpRootPathName
-      ctypes.jschar.ptr,   // out: lpVolumeNameBuffer
-      ctypes.uint32_t,     // in: nVolumeNameSize
-      ctypes.uint32_t.ptr, // out, optional: lpVolumeSerialNumber
-      ctypes.uint32_t.ptr, // out, optional: lpMaximumComponentLength
-      ctypes.uint32_t.ptr, // out, optional: lpFileSystemFlags
-      ctypes.jschar.ptr,   // out: lpFileSystemNameBuffer
-      ctypes.uint32_t      // in: nFileSystemNameSize
-    );
-
-    // We're only interested in the name of the file system.
-    let fsName = new (ctypes.jschar.array(MAX_PATH + 1));
-
-    if (!GetVolumeInformation(volumePath, null, 0, null, null, null, fsName,
-                              fsName.length)) {
-      throw new Exception("Unable to get volume information for " +
-                          volumePath.readString() + ", error " + GetLastError());
-    }
-
-    return fsName.readString();
-  }
-  finally {
-    kernel32.close();
-  }
-}
-
-/**
- * Try marking a region of a file as sparse, so that zeros don't consume
- * significant amounts of disk space.  This is a platform-dependent routine and
- * is not supported on all platforms. The current status of this function is:
- * - Windows: Supported, but only on NTFS volumes.
- * - Mac: Not supported.
- * - Linux: As long as you seek to a position before writing, happens automatically
- *   on most file systems, so this function is a no-op.
- *
- * @param aFile The file to mark as sparse.
- * @param aRegionStart The start position of the sparse region, in bytes.
- * @param aRegionBytes The number of bytes to mark as sparse.
- * @returns Whether the OS and file system supports marking files as sparse. If
- *          this is true, then the file has been marked as sparse. If this is
- *          false, then the underlying system doesn't support marking files as
- *          sparse. If an exception is thrown, then the system does support
- *          marking files as sparse, but an error occured while doing so.
- *
- */
-function mark_file_region_sparse(aFile, aRegionStart, aRegionBytes) {
-  if ("@mozilla.org/windows-registry-key;1" in Cc) {
-    // If the file system is not NTFS, sorry, we don't support sparse files.
-    if (get_file_system(aFile) != "NTFS")
-      return false;
-
-    // Win32 type and other constants.
-    const BOOL = ctypes.int32_t;
-    const HANDLE = ctypes.voidptr_t;
-    // A BOOLEAN (= BYTE = unsigned char) is distinct from a BOOL.
-    // http://blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspx
-    const BOOLEAN = ctypes.unsigned_char;
-    const FILE_SET_SPARSE_BUFFER = new ctypes.StructType(
-      "FILE_SET_SPARSE_BUFFER",
-      [{"SetSparse": BOOLEAN}]
-    );
-    // LARGE_INTEGER is actually a type union. We'll use the int64 representation
-    const LARGE_INTEGER = ctypes.int64_t;
-    const FILE_ZERO_DATA_INFORMATION = new ctypes.StructType(
-      "FILE_ZERO_DATA_INFORMATION",
-      [{"FileOffset": LARGE_INTEGER},
-       {"BeyondFinalZero": LARGE_INTEGER}]
-    );
-
-    const GENERIC_WRITE = 0x40000000;
-    const OPEN_ALWAYS = 4;
-    const FILE_ATTRIBUTE_NORMAL = 0x80;
-    const INVALID_HANDLE_VALUE = new ctypes.Int64(-1);
-    const FSCTL_SET_SPARSE = 0x900c4;
-    const FSCTL_SET_ZERO_DATA = 0x980c8;
-    const FILE_BEGIN = 0;
-
-    let kernel32 = ctypes.open("kernel32.dll");
-
-    try {
-      let CreateFile = kernel32.declare(
-        "CreateFileW",
-        ctypes.stdcall_abi,
-        HANDLE,            // return type: handle to the file
-        ctypes.jschar.ptr, // in: lpFileName
-        ctypes.uint32_t,   // in: dwDesiredAccess
-        ctypes.uint32_t,   // in: dwShareMode
-        ctypes.voidptr_t,  // in, optional: lpSecurityAttributes (note that
-                           // we're cheating here by not declaring a
-                           // SECURITY_ATTRIBUTES structure -- that's because
-                           // we're going to pass in null anyway)
-        ctypes.uint32_t,   // in: dwCreationDisposition
-        ctypes.uint32_t,   // in: dwFlagsAndAttributes
-        HANDLE             // in, optional: hTemplateFile
-      );
-
-      // Returns the last error.
-      let GetLastError = kernel32.declare(
-        "GetLastError",
-        ctypes.stdcall_abi,
-        ctypes.uint32_t // return type: the last error
-      );
-
-      let filePath = aFile.path;
-      let hFile = CreateFile(filePath, GENERIC_WRITE, 0, null, OPEN_ALWAYS,
-                             FILE_ATTRIBUTE_NORMAL, null);
-      let hFileInt = ctypes.cast(hFile, ctypes.intptr_t);
-      if (ctypes.Int64.compare(hFileInt.value, INVALID_HANDLE_VALUE) == 0) {
-        throw new Exception("CreateFile failed for " + filePath + ", error " +
-                            GetLastError());
-      }
-
-      try {
-        let DeviceIoControl = kernel32.declare(
-          "DeviceIoControl",
-          ctypes.stdcall_abi,
-          BOOL,                // return type: 1 indicates success, 0 failure
-          HANDLE,              // in: hDevice
-          ctypes.uint32_t,     // in: dwIoControlCode
-          ctypes.voidptr_t,    // in, optional: lpInBuffer
-          ctypes.uint32_t,     // in: nInBufferSize
-          ctypes.voidptr_t,    // out, optional: lpOutBuffer
-          ctypes.uint32_t,     // in: nOutBufferSize
-          ctypes.uint32_t.ptr, // out, optional: lpBytesReturned
-          ctypes.voidptr_t     // inout, optional: lpOverlapped (again, we're
-                               // cheating here by not having this as an
-                               // OVERLAPPED structure
-        );
-        // bytesReturned needs to be passed in, even though it's meaningless
-        let bytesReturned = new ctypes.uint32_t();
-        let sparseBuffer = new FILE_SET_SPARSE_BUFFER();
-        sparseBuffer.SetSparse = 1;
-
-        // Mark the file as sparse
-        if (!DeviceIoControl(hFile, FSCTL_SET_SPARSE, sparseBuffer.address(),
-                             FILE_SET_SPARSE_BUFFER.size, null, 0,
-                             bytesReturned.address(), null)) {
-          throw new Exception("Unable to mark file as sparse, error " +
-                              GetLastError());
-        }
-        
-        let zdInfo = new FILE_ZERO_DATA_INFORMATION();
-        zdInfo.FileOffset = aRegionStart;
-        let regionEnd = aRegionStart + aRegionBytes;
-        zdInfo.BeyondFinalZero = regionEnd;
-        // Mark the region as a sparse region
-        if (!DeviceIoControl(hFile, FSCTL_SET_ZERO_DATA, zdInfo.address(),
-                             FILE_ZERO_DATA_INFORMATION.size, null, 0,
-                             bytesReturned.address(), null)) {
-          throw new Exception("Unable to mark region as zero, error " +
-                              GetLastError());
-        }
-
-        // Move to past the sparse region and mark it as the end of the file. The
-        // above DeviceIoControl call is useless unless followed by this.
-        let SetFilePointerEx = kernel32.declare(
-          "SetFilePointerEx",
-          ctypes.stdcall_abi,
-          BOOL,              // return type: 1 indicates success, 0 failure
-          HANDLE,            // in: hFile
-          LARGE_INTEGER,     // in: liDistanceToMove
-          LARGE_INTEGER.ptr, // out, optional: lpNewFilePointer
-          ctypes.uint32_t    // in: dwMoveMethod
-        );
-        if (!SetFilePointerEx(hFile, regionEnd, null, FILE_BEGIN)) {
-          throw new Exception("Unable to set file pointer to end, error " +
-                              GetLastError());
-        }
-
-        let SetEndOfFile = kernel32.declare(
-          "SetEndOfFile",
-          ctypes.stdcall_abi,
-          BOOL,  // return type: 1 indicates success, 0 failure
-          HANDLE // in: hFile
-        );
-        if (!SetEndOfFile(hFile))
-          throw new Exception("Unable to set end of file, error " + GetLastError());
-
-        return true;
-      }
-      finally {
-        let CloseHandle = kernel32.declare(
-          "CloseHandle",
-          ctypes.stdcall_abi,
-          BOOL,  // return type: 1 indicates success, 0 failure
-          HANDLE // in: hObject
-        );
-        CloseHandle(hFile);
-      }
-    }
-    finally {
-      kernel32.close();
-    }
-  }
-  else if ("nsILocalFileMac" in Ci) {
-    // Macs don't support marking files as sparse.
-    return false;
-  }
-  else {
-    // Assuming Unix here. Unix file systems generally automatically sparsify
-    // files.
-    return true;
-  }
-}
-
-/**
  * A variant of do_timeout that accepts an actual function instead of
  *  requiring you to pass a string to evaluate.  If the function throws an
  *  exception when invoked, we will use do_throw to ensure that the test fails.
  *
  * @param aDelayInMS The number of milliseconds to wait before firing the timer.
  * @param aFunc The function to invoke when the timer fires.
  * @param aFuncThis Optional 'this' pointer to use.
  * @param aFuncArgs Optional list of arguments to pass to the function.