Bug 1279006 - Clean up webaudioeditor node destruction tests, and fix another race condition. (r=bgrins)
authorEric Faust <efaustbmo@gmail.com>
Wed, 08 Jun 2016 14:54:53 -0700
changeset 301138 df61facc5659fca43f03e367cd899382f5f9cfce
parent 301137 30174708069d124a762b8fbd617f4fc0dc17a5b8
child 301139 2dbc26e0764692cd9d6e9d6c01ad21063de00dbe
push id78234
push userefaustbmo@gmail.com
push dateWed, 08 Jun 2016 21:55:09 +0000
treeherdermozilla-inbound@df61facc5659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1279006
milestone50.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 1279006 - Clean up webaudioeditor node destruction tests, and fix another race condition. (r=bgrins)
devtools/client/webaudioeditor/test/browser_wa_destroy-node-01.js
devtools/client/webaudioeditor/test/browser_webaudio-actor-destroy-node.js
devtools/client/webaudioeditor/test/doc_destroy-nodes.html
devtools/client/webaudioeditor/test/head.js
--- a/devtools/client/webaudioeditor/test/browser_wa_destroy-node-01.js
+++ b/devtools/client/webaudioeditor/test/browser_wa_destroy-node-01.js
@@ -13,32 +13,32 @@ add_task(function* () {
   let { target, panel } = yield initWebAudioEditor(DESTROY_NODES_URL);
   let { panelWin } = panel;
   let { gFront, $, $$, gAudioNodes } = panelWin;
 
   let started = once(gFront, "start-context");
 
   reload(target);
 
-  let destroyed = getN(gAudioNodes, "remove", 10);
-
   let [created] = yield Promise.all([
     getNSpread(gAudioNodes, "add", 13),
     waitForGraphRendered(panelWin, 13, 2)
   ]);
 
   // Flatten arrays of event arguments and take the first (AudioNodeModel)
   // and get its ID.
   let actorIDs = created.map(ev => ev[0].id);
 
   // Click a soon-to-be dead buffer node
   yield clickGraphNode(panelWin, actorIDs[5]);
 
+  let destroyed = getN(gAudioNodes, "remove", 10);
+
   // Force a CC in the child process to collect the orphaned nodes.
-  forceCC();
+  forceNodeCollection();
 
   // Wait for destruction and graph to re-render
   yield Promise.all([destroyed, waitForGraphRendered(panelWin, 3, 2)]);
 
   // Test internal storage
   is(panelWin.gAudioNodes.length, 3, "All nodes should be GC'd except one gain, osc and dest node.");
 
   // Test graph rendering
--- a/devtools/client/webaudioeditor/test/browser_webaudio-actor-destroy-node.js
+++ b/devtools/client/webaudioeditor/test/browser_webaudio-actor-destroy-node.js
@@ -3,30 +3,28 @@
 
 /**
  * Test `destroy-node` event on WebAudioActor.
  */
 
 add_task(function* () {
   let { target, front } = yield initBackend(DESTROY_NODES_URL);
 
-  let waitUntilDestroyed = getN(front, "destroy-node", 10);
   let [, , created] = yield Promise.all([
     front.setup({ reload: true }),
     once(front, "start-context"),
-    // Should create 1 destination node and 10 disposable buffer nodes
+    // Should create dest, gain, and oscillator node and 10
+    // disposable buffer nodes
     getN(front, "create-node", 13)
   ]);
 
-  // Wait for a tick before gc to prevent this test from intermittent timeout
-  // where the node never get collected.
-  yield DevToolsUtils.waitForTick();
+  let waitUntilDestroyed = getN(front, "destroy-node", 10);
 
   // Force CC so we can ensure it's run to clear out dead AudioNodes
-  forceCC();
+  forceNodeCollection();
 
   let destroyed = yield waitUntilDestroyed;
 
   destroyed.forEach((node, i) => {
     ok(node.type, "AudioBufferSourceNode", "Only buffer nodes are destroyed");
     ok(actorIsInList(created, destroyed[i]),
       "`destroy-node` called only on AudioNodes in current document.");
   });
--- a/devtools/client/webaudioeditor/test/doc_destroy-nodes.html
+++ b/devtools/client/webaudioeditor/test/doc_destroy-nodes.html
@@ -7,23 +7,27 @@
     <meta charset="utf-8"/>
     <title>Web Audio Editor test page</title>
   </head>
 
   <body>
 
     <script type="text/javascript;version=1.8">
       "use strict";
+      // Keep the nodes we want to GC alive until we are ready for them to
+      // be collected. We will zero this reference by force from the devtools
+      // side.
+      var keepAlive = [];
       (function () {
       let ctx = new AudioContext();
       let osc = ctx.createOscillator();
       let gain = ctx.createGain();
 
       for (let i = 0; i < 10; i++) {
-        ctx.createBufferSource();
+        keepAlive.push(ctx.createBufferSource());
       }
 
       osc.connect(gain);
       gain.connect(ctx.destination);
       gain.gain.value = 0;
       osc.start();
       })();
     </script>
--- a/devtools/client/webaudioeditor/test/head.js
+++ b/devtools/client/webaudioeditor/test/head.js
@@ -415,18 +415,22 @@ function countGraphObjects(win) {
     nodes: win.document.querySelectorAll(".nodes > .audionode").length,
     edges: win.document.querySelectorAll(".edgePaths > .edgePath").length
   };
 }
 
 /**
 * Forces cycle collection and GC, used in AudioNode destruction tests.
 */
-function forceCC() {
+function forceNodeCollection() {
   ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() {
+    // Kill the reference keeping stuff alive.
+    content.wrappedJSObject.keepAlive = null;
+
+    // Collect the now-deceased nodes.
     Cu.forceGC();
     Cu.forceCC();
     Cu.forceGC();
     Cu.forceCC();
   });
 }
 
 /**