Bug 874425 - Ensure that we never return an negative duration. r=froydnj, a=test-only
authorDavid Rajchenbach-Teller <dteller@mozilla.com>
Fri, 23 Aug 2013 10:06:33 -0400
changeset 149175 33914f2ed186d5930eb10690b8ea6dd912c53a2b
parent 149174 674c5378780cff63c3f3a77b5a4f1b8df78edb8c
child 149176 f7ce0ff85d0da64aaa70458bd1f87775905b2387
push id4182
push userryanvm@gmail.com
push dateTue, 27 Aug 2013 13:37:26 +0000
treeherdermozilla-aurora@3b52e8691c8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj, test-only
bugs874425
milestone25.0a2
Bug 874425 - Ensure that we never return an negative duration. r=froydnj, a=test-only
toolkit/components/osfile/modules/osfile_async_front.jsm
toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
--- a/toolkit/components/osfile/modules/osfile_async_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
@@ -154,16 +154,21 @@ let Scheduler = {
           !("outExecutionDuration" in options)) {
           return data.ok;
         }
         // If data.durationMs is not present, return data.ok (there was an
         // exception applying the method).
         if (!("durationMs" in data)) {
           return data.ok;
         }
+        // Bug 874425 demonstrates that two successive calls to Date.now()
+        // can actually produce an interval with negative duration.
+        // We assume that this is due to an operation that is so short
+        // that Date.now() is not monotonic, so we round this up to 0.
+        let durationMs = Math.max(0, data.durationMs);
         // Accumulate (or initialize) outExecutionDuration
         if (typeof options.outExecutionDuration == "number") {
           options.outExecutionDuration += data.durationMs;
         } else {
           options.outExecutionDuration = data.durationMs;
         }
         return data.ok;
       },
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -867,16 +867,17 @@ let test_system_shutdown = maketest("sys
   });
 });
 
 /**
  * Test optional duration reporting that can be used for telemetry.
  */
 let test_duration = maketest("duration", function duration(test) {
   return Task.spawn(function() {
+    Services.prefs.setBoolPref("toolkit.osfile.log", true);
     // Options structure passed to a OS.File copy method.
     let copyOptions = {
       // This field should be overridden with the actual duration
       // measurement.
       outExecutionDuration: null
     };
     let currentDir = yield OS.File.getCurrentDirectory();
     let pathSource = OS.Path.join(currentDir, EXISTING_FILE);
@@ -942,17 +943,17 @@ let test_duration = maketest("duration",
       tmpPath: tmpPath
     };
     backupDuration = writeAtomicOptions.outExecutionDuration;
 
     yield OS.File.writeAtomic(pathDest, contents, writeAtomicOptions);
     test.ok(copyOptions.outExecutionDuration >= backupDuration, "duration has increased 3");
     OS.File.remove(pathDest);
 
-    Services.prefs.setBoolPref("toolkit.osfile.log", true);
     OS.Shared.TEST = true;
 
     // Testing an operation that doesn't take arguments at all
     let file = yield OS.File.open(pathSource);
     yield file.stat();
     yield file.close();
+    Services.prefs.setBoolPref("toolkit.osfile.log", false);
   });
 });