Bug 1063635 Part 3 - Fix tests for native writeAtomic. r?Yoric draft
authorMilindL <i.milind.luthra@gmail.com>
Tue, 29 Aug 2017 20:20:26 +0530
changeset 679545 03d6788c0ae0cf800f219d567217b4c122a350f4
parent 679544 5d5b01c0f8a79d7ef371b25b2c6eb171b26507e6
child 735642 94bcd29b6a435aa9c8ce719480b3df27cdfab959
push id84268
push userbmo:i.milind.luthra@gmail.com
push dateThu, 12 Oct 2017 21:35:29 +0000
reviewersYoric
bugs1063635
milestone58.0a1
Bug 1063635 Part 3 - Fix tests for native writeAtomic. r?Yoric MozReview-Commit-ID: 94lNCMUEg7c
toolkit/components/osfile/tests/xpcshell/test_duration.js
toolkit/components/osfile/tests/xpcshell/test_osfile_writeAtomic_unicode_filename.js
toolkit/components/osfile/tests/xpcshell/xpcshell.ini
--- a/toolkit/components/osfile/tests/xpcshell/test_duration.js
+++ b/toolkit/components/osfile/tests/xpcshell/test_duration.js
@@ -52,22 +52,22 @@ add_task(async function duration() {
     outExecutionDuration: null
   };
   let contents = await OS.File.read(pathSource, undefined, readOptions);
   testOptions(readOptions, "OS.File.read", ["outExecutionDuration"]);
   // Options structure passed to a OS.File writeAtomic method.
   let writeAtomicOptions = {
     // This field should be first initialized with the actual
     // duration measurement then progressively incremented.
-    outSerializationDuration: null,
     outExecutionDuration: null,
     tmpPath
   };
+  // Note that |contents| cannot be reused after this call since it is detached.
   await OS.File.writeAtomic(pathDest, contents, writeAtomicOptions);
-  testOptions(writeAtomicOptions, "OS.File.writeAtomic");
+  testOptions(writeAtomicOptions, "OS.File.writeAtomic", ["outExecutionDuration"]);
   await OS.File.remove(pathDest);
 
   do_print(`Ensuring that we can use ${availableDurations.join(", ")} to accumulate durations`);
 
   let ARBITRARY_BASE_DURATION = 5;
   copyOptions = {
     // This field should now be incremented with the actual duration
     // measurement.
@@ -83,20 +83,25 @@ add_task(async function duration() {
   testOptionIncrements(copyOptions, "copy", backupDuration);
 
   backupDuration = Object.assign({}, copyOptions);
   await OS.File.remove(copyFile, copyOptions);
   testOptionIncrements(copyOptions, "remove", backupDuration);
 
   // Trying an operation where options are cloned.
   // Options structure passed to a OS.File writeAtomic method.
-  writeAtomicOptions = copyOptions;
+  writeAtomicOptions = {
+    // We do not check for |outSerializationDuration| since |Scheduler.post|
+    // may not be called whenever |writeAtomic| is called.
+    outExecutionDuration: ARBITRARY_BASE_DURATION
+  };
   writeAtomicOptions.tmpPath = tmpPath;
-  backupDuration = Object.assign({}, copyOptions);
+  backupDuration = Object.assign({}, writeAtomicOptions);
+  contents = await OS.File.read(pathSource, undefined, readOptions);
   await OS.File.writeAtomic(pathDest, contents, writeAtomicOptions);
-  testOptionIncrements(writeAtomicOptions, "writeAtomicOptions", backupDuration);
+  testOptionIncrements(writeAtomicOptions, "writeAtomicOptions", backupDuration, ["outExecutionDuration"]);
   OS.File.remove(pathDest);
 
   // Testing an operation that doesn't take arguments at all
   let file = await OS.File.open(pathSource);
   await file.stat();
   await file.close();
 });
new file mode 100644
--- /dev/null
+++ b/toolkit/components/osfile/tests/xpcshell/test_osfile_writeAtomic_unicode_filename.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * This test checks against failures that may occur while creating and/or
+ * renaming files with Unicode paths on Windows.
+ * See bug 1063635#c89 for a failure due to a Unicode filename being renamed.
+ */
+
+"use strict";
+var profileDir;
+
+async function writeAndCheck(path, tmpPath) {
+  const encoder = new TextEncoder();
+  const content = "tmpContent";
+  const outBin = encoder.encode(content);
+  await OS.File.writeAtomic(path, outBin, { tmpPath });
+
+  const decoder = new TextDecoder();
+  const writtenBin = await OS.File.read(path);
+  const written = decoder.decode(writtenBin);
+
+  // Clean up
+  await OS.File.remove(path);
+  Assert.equal(written, content, `Expected correct write/read for ${path} with tmpPath ${tmpPath}`);
+}
+
+add_task(async function init() {
+  do_get_profile();
+  profileDir = OS.Constants.Path.profileDir;
+});
+
+add_test_pair(async function test_osfile_writeAtomic_unicode_filename() {
+  await writeAndCheck(OS.Path.join(profileDir, "☕") + ".tmp", undefined);
+  await writeAndCheck(OS.Path.join(profileDir, "☕"), undefined);
+  await writeAndCheck(OS.Path.join(profileDir, "☕") + ".tmp",
+                      OS.Path.join(profileDir, "☕"));
+  await writeAndCheck(OS.Path.join(profileDir, "☕"),
+                      OS.Path.join(profileDir, "☕") + ".tmp");
+});
--- a/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
@@ -25,16 +25,17 @@ skip-if = os == "win" || os == "android"
 [test_osfile_closed.js]
 [test_osfile_error.js]
 [test_osfile_kill.js]
 # Windows test
 [test_osfile_win_async_setPermissions.js]
 skip-if = os != "win"
 [test_osfile_writeAtomic_backupTo_option.js]
 [test_osfile_writeAtomic_zerobytes.js]
+[test_osfile_writeAtomic_unicode_filename.js]
 [test_path.js]
 [test_path_constants.js]
 [test_queue.js]
 [test_read_write.js]
 requesttimeoutfactor = 4
 [test_remove.js]
 [test_removeDir.js]
 requesttimeoutfactor = 4