Bug 1534818 - Test worker functionality. r=davidwalsh
☠☠ backed out by 3d4960bdee5f ☠ ☠
authorJason Laster <jlaster@mozilla.com>
Thu, 11 Apr 2019 13:45:28 +0000
changeset 469004 7899601d5d70ba39e13ec3332e6b7f145b4719c6
parent 469003 10c226df417e96f7d1127d023b72e701586dfe64
child 469005 b2fcdaeb0040ef5bd909d55412aa8386924085c3
push id35856
push usercsabou@mozilla.com
push dateFri, 12 Apr 2019 03:19:48 +0000
treeherdermozilla-central@940684cd1065 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidwalsh
bugs1534818
milestone68.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 1534818 - Test worker functionality. r=davidwalsh Differential Revision: https://phabricator.services.mozilla.com/D26808
devtools/client/debugger/test/mochitest/.eslintrc
devtools/client/debugger/test/mochitest/browser_dbg-windowless-workers.js
devtools/client/debugger/test/mochitest/helpers.js
--- a/devtools/client/debugger/test/mochitest/.eslintrc
+++ b/devtools/client/debugger/test/mochitest/.eslintrc
@@ -31,16 +31,17 @@
     "todo_isnot": false,
     "waitForClipboard": false,
     "waitForExplicitFinish": false,
     "waitForFocus": false,
     "selectSource": false,
     "prettyPrint": false,
     "closeTab": false,
     "pushPref": false,
+    "waitFor": false,
 
     // Globals introduced in debugger-specific head.js
     "getCM": false,
     "getDebuggerSplitConsole": false,
     "hasConsoleMessage": false,
     "findConsoleMessage": false,
     "promise": false,
     "BrowserToolboxProcess": false,
@@ -57,45 +58,53 @@
     "waitForSources": false,
     "waitForSource": false,
     "waitForLoadedSource": false,
     "waitForSelectedSource": false,
     "waitForBreakpoint": false,
     "waitForBreakpointCount": false,
     "waitForCondition": false,
     "waitForLog": false,
-    "isPaused": false,
+    "waitForPausedThread": false,
     "assertClass": false,
+    "assertNotPaused": false,
     "assertSourceCount": false,
+    "assertPausedAtSourceAndLine": false,
     "assertEditorBreakpoint": false,
     "assertBreakpointSnippet": false,
     "assertEmptyLines": false,
     "assertPausedLocation": false,
     "assertHighlightLocation": false,
     "createDebuggerContext": false,
     "initDebugger": false,
     "invokeInTab": false,
     "findBreakpoint": false,
     "findSource": false,
     "findElement": false,
     "findElementWithSelector": false,
     "findAllElements": false,
+    "getContext": false,
+    "getIsPaused": false,
+    "getThreadContext": false,
+    "getWorkers": false,
     "openNewTabAndToolbox": false,
     "selectLocation": false,
     "stepOver": false,
     "stepIn": false,
     "stepOut": false,
     "resume": false,
     "reload": false,
     "navigate": false,
     "removeBreakpoint": false,
     "addBreakpoint": false,
+    "addExpression": false,
     "toggleCallStack": false,
     "toggleScopes": false,
     "isVisibleWithin": false,
+    "isPaused": false,
     "clickElement": false,
     "clickElementWithSelector": false,
     "clickDOMElement": false,
     "altClickElement": false,
     "rightClickElement": false,
     "rightClickEl": false,
     "clickGutter": false,
     "typeInPanel": false,
--- a/devtools/client/debugger/test/mochitest/browser_dbg-windowless-workers.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg-windowless-workers.js
@@ -1,30 +1,36 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // Debugger operations may still be in progress when we switch threads.
 const { PromiseTestUtils } = ChromeUtils.import(
   "resource://testing-common/PromiseTestUtils.jsm"
 );
-PromiseTestUtils.whitelistRejectionsGlobally(/Current thread has paused or resumed/);
+PromiseTestUtils.whitelistRejectionsGlobally(
+  /Current thread has paused or resumed/
+);
 PromiseTestUtils.whitelistRejectionsGlobally(/Current thread has changed/);
 
-function threadIsPaused(dbg, index) {
-  return findElement(dbg, "threadsPaneItem", index).querySelector(
-    ".pause-badge"
+function assertClass(dbg, selector, className, ...args) {
+  ok(
+    findElement(dbg, selector, ...args).classList.contains(className),
+    `${className} class exists`
   );
 }
 
+function threadIsPaused(dbg, index) {
+  return ok(findElement(dbg, "threadsPaneItemPause", index));
+}
+
 function threadIsSelected(dbg, index) {
-  return findElement(dbg, "threadsPaneItem", index).classList.contains(
-    "selected"
-  );
+  return assertClass(dbg, "threadsPaneItem", "selected", index);
 }
 
 function getLabel(dbg, index) {
   return findElement(dbg, "expressionNode", index).innerText;
 }
 
 function getValue(dbg, index) {
   return findElement(dbg, "expressionValue", index).innerText;
@@ -40,87 +46,89 @@ add_task(async function() {
 
   // NOTE: by default we do not wait on worker
   // commands to complete because the thread could be
   // shutting down.
   dbg.client.waitForWorkers(true);
 
   const workers = await getWorkers(dbg);
   ok(workers.length == 2, "Got two workers");
-  const worker1Thread = workers[0].actor;
-  const worker2Thread = workers[1].actor;
+  const thread1 = workers[0].actor;
+  const thread2 = workers[1].actor;
 
   const mainThreadSource = findSource(dbg, "doc-windowless-workers.html");
 
   await waitForSource(dbg, "simple-worker.js");
   const workerSource = findSource(dbg, "simple-worker.js");
 
-  info("Test pausing in the main thread");
+  info("Pause in the main thread");
   assertNotPaused(dbg);
   await dbg.actions.breakOnNext(getThreadContext(dbg));
   await waitForPaused(dbg, "doc-windowless-workers.html");
   assertPausedAtSourceAndLine(dbg, mainThreadSource.id, 10);
+  threadIsSelected(dbg, 1);
 
-  info("Test pausing in a worker");
-  await dbg.actions.selectThread(getContext(dbg), worker1Thread);
+  info("Pause in the first worker");
+  await dbg.actions.selectThread(getContext(dbg), thread1);
   assertNotPaused(dbg);
   await dbg.actions.breakOnNext(getThreadContext(dbg));
   await waitForPaused(dbg, "simple-worker.js");
+  threadIsSelected(dbg, 2);
   assertPausedAtSourceAndLine(dbg, workerSource.id, 3);
 
+  info("Add a watch expression and view the value");
   await addExpression(dbg, "count");
   is(getLabel(dbg, 1), "count");
   const v = getValue(dbg, 1);
-  ok(v == "" + +v, "Value of count should be a number");
+  ok(v == `${+v}`, "Value of count should be a number");
 
-  info("Test stepping in a worker");
+  info("StepOver in the first worker");
   await stepOver(dbg);
   assertPausedAtSourceAndLine(dbg, workerSource.id, 4);
 
-  // The watch expression should update with an incremented value.
+  info("Ensure that the watch expression has updated");
   await waitUntil(() => {
     const v2 = getValue(dbg, 1);
     return +v2 == +v + 1;
   });
 
-  info("Test resuming in a worker");
+  info("Resume in the first worker");
   await resume(dbg);
   assertNotPaused(dbg);
 
-  info("Test stepping in the main thread");
+  info("StepOver in the main thread");
   dbg.actions.selectThread(getContext(dbg), mainThread);
   await stepOver(dbg);
   assertPausedAtSourceAndLine(dbg, mainThreadSource.id, 11);
 
-  info("Test resuming in the mainThread");
+  info("Resume in the mainThread");
   await resume(dbg);
   assertNotPaused(dbg);
 
-  info("Test pausing in both workers");
+  info("Pause in both workers");
   await addBreakpoint(dbg, "simple-worker", 10);
   invokeInTab("sayHello");
 
-  // Wait for both workers to pause. When a thread pauses the current thread
-  // changes, and we don't want to get confused.
-  const {
-    selectors: { getIsPaused },
-    getState
-  } = dbg;
-  await waitFor(() => {
-    const state = getState();
-    return getIsPaused(state, worker1Thread) && getIsPaused(state, worker2Thread);
-  });
+  info("Wait for both workers to pause");
+  // When a thread pauses the current thread changes,
+  // and we don't want to get confused.
+  await waitForPausedThread(dbg, thread1);
+  await waitForPausedThread(dbg, thread2);
+  threadIsPaused(dbg, 2);
+  threadIsPaused(dbg, 3);
 
-  dbg.actions.selectThread(getContext(dbg), worker1Thread);
-
+  info("View the first paused thread");
+  dbg.actions.selectThread(getContext(dbg), thread1);
   await waitForPaused(dbg);
   assertPausedAtSourceAndLine(dbg, workerSource.id, 10);
 
-  dbg.actions.selectThread(getContext(dbg), worker2Thread);
+  info("View the second paused thread");
+  dbg.actions.selectThread(getContext(dbg), thread2);
+  threadIsSelected(dbg, 3);
   await waitForPaused(dbg);
   assertPausedAtSourceAndLine(dbg, workerSource.id, 10);
 
-  info("Test stepping in second worker and not the first");
+  info("StepOver in second worker and not the first");
   await stepOver(dbg);
   assertPausedAtSourceAndLine(dbg, workerSource.id, 11);
-  dbg.actions.selectThread(getContext(dbg), worker1Thread);
+  dbg.actions.selectThread(getContext(dbg), thread1);
   assertPausedAtSourceAndLine(dbg, workerSource.id, 10);
 });
--- a/devtools/client/debugger/test/mochitest/helpers.js
+++ b/devtools/client/debugger/test/mochitest/helpers.js
@@ -509,16 +509,19 @@ function waitForCondition(dbg, condition
 }
 
 function waitForLog(dbg, logValue) {
   return waitForState(dbg, state =>
     dbg.selectors
       .getBreakpointsList(state)
       .find(bp => bp.options.logValue == logValue)
   );
+
+async function waitForPausedThread(dbg, thread) {
+  return waitForState(dbg, state => dbg.selectors.getIsPaused(state, thread));
 }
 
 /*
  * useful for when you want to see what is happening
  * e.g await waitForever()
  */
 function waitForever() {
   return new Promise(r => {});
@@ -1274,16 +1277,17 @@ const selectors = {
   outlineItems: ".outline-list__element",
   conditionalPanelInput: ".conditional-breakpoint-panel textarea",
   searchField: ".search-field",
   blackbox: ".action.black-box",
   projectSearchCollapsed: ".project-text-search .arrow:not(.expanded)",
   projectSerchExpandedResults: ".project-text-search .result",
   threadsPaneItems: ".workers-pane .worker",
   threadsPaneItem: i => `.workers-pane .worker:nth-child(${i})`,
+  threadsPaneItemPause: i => `${selectors.threadsPaneItem(i)} .pause-badge`,
   CodeMirrorLines: ".CodeMirror-lines"
 };
 
 function getSelector(elementName, ...args) {
   let selector = selectors[elementName];
   if (!selector) {
     throw new Error(`The selector ${elementName} is not defined`);
   }