Bug 1279006 - Clean up webaudioeditor node destruction tests, and fix another race condition. r=bgrins, a=test-only
authorEric Faust <efaustbmo@gmail.com>
Wed, 08 Jun 2016 14:54:53 -0700
changeset 341690 24c398084956930504a2855b3c0a438bb6e4cbdd
parent 341689 3b80e1206f581b5a890a4620a82b45a5a9f3cee0
child 341691 86463ff0610badf08515ad5bc8540f2c1ff68a4e
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins, test-only
bugs1279006
milestone49.0a2
Bug 1279006 - Clean up webaudioeditor node destruction tests, and fix another race condition. r=bgrins, a=test-only
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();
   });
 }
 
 /**