Bug 870181 - Part 3: Test that we downgrade processes' CPU priorities when appropriate. r=bent
authorJustin Lebar <justin.lebar@gmail.com>
Thu, 09 May 2013 16:27:06 -0400
changeset 142431 1fb1b2e7660f77b389acac98d69cbe862380ad5d
parent 142430 6c53b7ecb2ee37e14b7d6a250af576e11deb23fe
child 142432 1fca89c36c8b91fbb815b3768d6b2a18a026dfd4
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs870181
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 870181 - Part 3: Test that we downgrade processes' CPU priorities when appropriate. r=bent
dom/browser-element/mochitest/browserElementTestHelpers.js
dom/browser-element/mochitest/priority/CAUTION
dom/browser-element/mochitest/priority/Makefile.in
dom/browser-element/mochitest/priority/test_HighPriorityDowngrade.html
dom/browser-element/mochitest/priority/test_HighPriorityDowngrade2.html
--- a/dom/browser-element/mochitest/browserElementTestHelpers.js
+++ b/dom/browser-element/mochitest/browserElementTestHelpers.js
@@ -138,46 +138,59 @@ function expectOnlyOneProcessCreated() {
     expectProcessCreated().then(function(childID) {
       ok(false, 'Got unexpected process creation, childID=' + childID);
     });
   });
   return p;
 }
 
 // Returns a promise which is resolved or rejected the next time the process
-// childID changes its priority.  We resolve if the priority matches
-// expectedPriority, and we reject otherwise.
-function expectPriorityChange(childID, expectedPriority) {
+// childID changes its priority.  We resolve if the (priority, CPU priority)
+// tuple matches (expectedPriority, expectedCPUPriority) and we reject
+// otherwise.
+//
+// expectedCPUPriority is an optional argument; if it's not specified, we
+// resolve if priority matches expectedPriority.
+
+function expectPriorityChange(childID, expectedPriority,
+                              /* optional */ expectedCPUPriority) {
   var deferred = Promise.defer();
 
   var observed = false;
   browserElementTestHelpers.addProcessPriorityObserver(
     'process-priority-set',
     function(subject, topic, data) {
       if (observed) {
         return;
       }
 
-      [id, priority] = data.split(":");
+      [id, priority, cpuPriority] = data.split(":");
       if (id != childID) {
         return;
       }
 
       // Make sure we run the is() calls in this observer only once, otherwise
       // we'll expect /every/ priority change to match expectedPriority.
       observed = true;
 
       is(priority, expectedPriority,
          'Expected priority of childID ' + childID +
          ' to change to ' + expectedPriority);
 
-      if (priority == expectedPriority) {
-        deferred.resolve(priority);
+      if (expectedCPUPriority) {
+        is(cpuPriority, expectedCPUPriority,
+           'Expected CPU priority of childID ' + childID +
+           ' to change to ' + expectedCPUPriority);
+      }
+
+      if (priority == expectedPriority &&
+          (!expectedCPUPriority || expectedCPUPriority == cpuPriority)) {
+        deferred.resolve();
       } else {
-        deferred.reject(priority);
+        deferred.reject();
       }
     }
   );
 
   return deferred.promise;
 }
 
 // Returns a promise which is resolved the first time the given iframe fires
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/priority/CAUTION
@@ -0,0 +1,15 @@
+A word to the wise:
+
+You must ensure that if your test finishes successfully, no processes have
+priority FOREGROUND_HIGH.
+
+If you don't do this, expect to see tests randomly fail with mysterious
+FOREGROUND --> FOREGROUND priority transitions.
+
+What's happening in this case is that your FOREGROUND_HIGH process lives until
+the beginning of the next test.  This causes the process started by the next
+test to have low CPU priority.  Then the FOREGROUND_HIGH process dies, because
+its iframe gets GC'ed, and we transition the new test's process from low CPU
+priority to regular CPU priority.
+
+Ouch.
--- a/dom/browser-element/mochitest/priority/Makefile.in
+++ b/dom/browser-element/mochitest/priority/Makefile.in
@@ -23,16 +23,18 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 #       test_WebGLContextLost.html \
 #       file_WebGLContextLost.html \
 
 MOCHITEST_FILES = \
 	test_Simple.html \
 	test_Visibility.html \
 	test_HighPriority.html \
 	file_HighPriority.html \
+	test_HighPriorityDowngrade.html \
+	test_HighPriorityDowngrade2.html \
 	test_Background.html \
 	test_Audio.html \
 	file_Audio.html \
 	silence.ogg \
 	test_MultipleFrames.html \
 	file_MultipleFrames.html \
 	test_Preallocated.html \
 	test_ExpectingSystemMessage.html \
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that high-priority processes downgrade the CPU priority of regular
+processes.
+-->
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="../browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="application/javascript;version=1.7">
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+browserElementTestHelpers.setEnabledPref(true);
+browserElementTestHelpers.addPermission();
+browserElementTestHelpers.enableProcessPriorityManager();
+SpecialPowers.addPermission("embed-apps", true, document);
+
+var iframe = null;
+var childID = null;
+
+function runTest() {
+  var iframe = document.createElement('iframe');
+  iframe.setAttribute('mozbrowser', true);
+
+  iframe.src = browserElementTestHelpers.emptyPage1;
+
+  var highPriorityIframe = null;
+  var childID = null;
+
+  expectProcessCreated().then(function(chid) {
+    childID = chid;
+    return expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
+  }).then(function() {
+    // Create a new, high-priority iframe.
+    highPriorityIframe = document.createElement('iframe');
+    highPriorityIframe.setAttribute('mozbrowser', true);
+    highPriorityIframe.setAttribute('expecting-system-message', true);
+    highPriorityIframe.setAttribute('mozapptype', 'critical');
+    highPriorityIframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
+    highPriorityIframe.src = browserElementTestHelpers.emptyPage2;
+
+    var p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW');
+
+    document.body.appendChild(highPriorityIframe);
+
+    return p;
+  }).then(function() {
+    return expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
+  }).then(SimpleTest.finish);
+
+  document.body.appendChild(iframe);
+}
+
+addEventListener('testready', function() {
+  // Cause the CPU wake lock taken on behalf of the high-priority process to
+  // time out after 1s.
+  SpecialPowers.pushPrefEnv(
+    {set: [["dom.ipc.systemMessageCPULockTimeoutSec", 1]]},
+    runTest);
+});
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/browser-element/mochitest/priority/test_HighPriorityDowngrade2.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that high-priority processes downgrade the CPU priority of regular
+processes.
+
+This is just like test_HighPriorityDowngrade, except instead of waiting for the
+high-priority process's wake lock to expire, we kill the process by removing
+its iframe from the DOM.
+-->
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="../browserElementTestHelpers.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<script type="application/javascript;version=1.7">
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+browserElementTestHelpers.setEnabledPref(true);
+browserElementTestHelpers.addPermission();
+browserElementTestHelpers.enableProcessPriorityManager();
+SpecialPowers.addPermission("embed-apps", true, document);
+
+function runTest() {
+  var iframe = document.createElement('iframe');
+  iframe.setAttribute('mozbrowser', true);
+
+  iframe.src = browserElementTestHelpers.emptyPage1;
+
+  var highPriorityIframe = null;
+  var childID = null;
+
+  expectProcessCreated().then(function(chid) {
+    childID = chid;
+    return expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
+  }).then(function() {
+    // Create a new, high-priority iframe.
+    highPriorityIframe = document.createElement('iframe');
+    highPriorityIframe.setAttribute('mozbrowser', true);
+    highPriorityIframe.setAttribute('expecting-system-message', true);
+    highPriorityIframe.setAttribute('mozapptype', 'critical');
+    highPriorityIframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
+    highPriorityIframe.src = browserElementTestHelpers.emptyPage2;
+
+    var p = Promise.all(
+      [expectPriorityChange(childID, 'FOREGROUND', 'CPU_LOW'),
+       expectMozbrowserEvent(highPriorityIframe, 'loadend')]
+    );
+
+    document.body.appendChild(highPriorityIframe);
+
+    return p;
+  }).then(function() {
+    // Killing the high-priority iframe should cause our CPU priority to go back
+    // up to regular.
+    var p = expectPriorityChange(childID, 'FOREGROUND', 'CPU_NORMAL');
+    document.body.removeChild(highPriorityIframe);
+    return p;
+  }).then(SimpleTest.finish);
+
+  document.body.appendChild(iframe);
+}
+
+addEventListener('testready', function() {
+  // Cause the CPU wake lock taken on behalf of the high-priority process never
+  // to time out during this test.
+  SpecialPowers.pushPrefEnv(
+    {set: [["dom.ipc.systemMessageCPULockTimeoutSec", 1000]]},
+    runTest);
+});
+
+</script>
+</body>
+</html>