Bug 834138 - Intermittent states/test_doc_busy.html | Test timed out, r=tbsaunde
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 12 Sep 2013 09:10:42 -0400
changeset 159737 fbf06a627656a27b29d5d26638a8543668065212
parent 159736 78f20a417a5a88971c27e53380626721b4f6fcb8
child 159738 1a65e666ccbed76fb5abee096a32cf61281b3c7b
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs834138
milestone26.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 834138 - Intermittent states/test_doc_busy.html | Test timed out, r=tbsaunde
accessible/tests/mochitest/events.js
accessible/tests/mochitest/states/test_doc_busy.html
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -288,21 +288,22 @@ function eventQueue(aEventType)
 
   /**
    * Process next invoker.
    */
   this.processNextInvoker = function eventQueue_processNextInvoker()
   {
     // Some scenario was matched, we wait on next invoker processing.
     if (this.mNextInvokerStatus == kInvokerCanceled) {
-      this.mNextInvokerStatus = kInvokerNotScheduled;
+      this.setInvokerStatus(kInvokerNotScheduled,
+                            "scenario was matched, wait for next invoker activation");
       return;
     }
 
-    this.mNextInvokerStatus = kInvokerNotScheduled;
+    this.setInvokerStatus(kInvokerNotScheduled, "the next invoker is processed now");
 
     // Finish processing of the current invoker if any.
     var testFailed = false;
 
     var invoker = this.getInvoker();
     if (invoker) {
       if ("finalCheck" in invoker)
         invoker.finalCheck();
@@ -428,17 +429,17 @@ function eventQueue(aEventType)
 
     if (this.hasUnexpectedEventsScenario())
       this.processNextInvokerInTimeout(true);
   }
 
   this.processNextInvokerInTimeout =
     function eventQueue_processNextInvokerInTimeout(aUncondProcess)
   {
-    this.mNextInvokerStatus = kInvokerPending;
+    this.setInvokerStatus(kInvokerPending, "Process next invoker in timeout");
 
     // No need to wait extra timeout when a) we know we don't need to do that
     // and b) there's no any single unexpected event.
     if (!aUncondProcess && this.areAllEventsExpected()) {
       // We need delay to avoid events coalesce from different invokers.
       var queue = this;
       SimpleTest.executeSoon(function() { queue.processNextInvoker(); });
       return;
@@ -536,25 +537,32 @@ function eventQueue(aEventType)
 
     if (hasMatchedCheckers) {
       var invoker = this.getInvoker();
       if ("check" in invoker)
         invoker.check(aEvent);
     }
 
     // If we don't have more events to wait then schedule next invoker.
-    if (this.hasMatchedScenario() &&
-        (this.mNextInvokerStatus == kInvokerNotScheduled)) {
-      this.processNextInvokerInTimeout();
+    if (this.hasMatchedScenario()) {
+      if (this.mNextInvokerStatus == kInvokerNotScheduled) {
+        this.processNextInvokerInTimeout();
+
+      } else if (this.mNextInvokerStatus == kInvokerCanceled) {
+        this.setInvokerStatus(kInvokerPending,
+                              "Full match. Void the cancelation of next invoker processing");
+      }
       return;
     }
 
     // If we have scheduled a next invoker then cancel in case of match.
-    if ((this.mNextInvokerStatus == kInvokerPending) && hasMatchedCheckers)
-      this.mNextInvokerStatus = kInvokerCanceled;
+    if ((this.mNextInvokerStatus == kInvokerPending) && hasMatchedCheckers) {
+      this.setInvokerStatus(kInvokerCanceled,
+                            "Cancel the scheduled invoker in case of match");
+    }
   }
 
   // Helpers
   this.processMatchedChecker =
     function eventQueue_function(aEvent, aMatchedChecker, aScenarioIdx, aEventIdx)
   {
     aMatchedChecker.wasCaught++;
 
@@ -617,40 +625,47 @@ function eventQueue(aEventType)
         if (eventSeq[idx].unexpected)
           return false;
       }
     }
 
     return true;
   }
 
+  this.isUnexpectedEventScenario =
+    function eventQueue_isUnexpectedEventsScenario(aScenario)
+  {
+    for (var idx = 0; idx < aScenario.length; idx++) {
+      if (!aScenario[idx].unexpected)
+        break;
+    }
+
+    return idx == aScenario.length;
+  }
+
   this.hasUnexpectedEventsScenario =
     function eventQueue_hasUnexpectedEventsScenario()
   {
     if (this.getInvoker().noEventsOnAction)
       return true;
 
     for (var scnIdx = 0; scnIdx < this.mScenarios.length; scnIdx++) {
-      var eventSeq = this.mScenarios[scnIdx];
-      for (var idx = 0; idx < eventSeq.length; idx++) {
-        if (!eventSeq[idx].unexpected)
-          break;
-      }
-      if (idx == eventSeq.length)
+      if (this.isUnexpectedEventScenario(this.mScenarios[scnIdx]))
         return true;
     }
 
     return false;
   }
-  
+
   this.hasMatchedScenario =
     function eventQueue_hasMatchedScenario()
   {
     for (var scnIdx = 0; scnIdx < this.mScenarios.length; scnIdx++) {
-      if (!this.areExpectedEventsLeft(this.mScenarios[scnIdx]))
+      var scn = this.mScenarios[scnIdx];
+      if (!this.isUnexpectedEventScenario(scn) && !this.areExpectedEventsLeft(scn))
         return true;
     }
     return false;
   }
 
   this.getInvoker = function eventQueue_getInvoker()
   {
     return this.mInvokers[this.mIndex];
@@ -770,16 +785,24 @@ function eventQueue(aEventType)
   {
     if ("getID" in aChecker)
       return aChecker.getID();
 
     var invoker = this.getInvoker();
     return invoker.getID();
   }
 
+  this.setInvokerStatus = function eventQueue_setInvokerStatus(aStatus, aLogMsg)
+  {
+    this.mNextInvokerStatus = aStatus;
+
+    // Uncomment it to debug invoker processing logic.
+    //gLogger.log(eventQueue.invokerStatusToMsg(aStatus, aLogMsg));
+  }
+
   this.mDefEventType = aEventType;
 
   this.mInvokers = new Array();
   this.mIndex = -1;
   this.mScenarios = null;
 
   this.mNextInvokerStatus = kInvokerNotScheduled;
 }
@@ -867,63 +890,63 @@ eventQueue.isSameEvent = function eventQ
   // We don't have stored info about handled event other than its type and
   // target, thus we should filter text change and state change events since
   // they may occur on the same element because of complex changes.
   return this.compareEvents(aChecker, aEvent) &&
     !(aEvent instanceof nsIAccessibleTextChangeEvent) &&
     !(aEvent instanceof nsIAccessibleStateChangeEvent);
 }
 
-eventQueue.logEvent = function eventQueue_logEvent(aOrigEvent, aMatchedChecker,
-                                                   aScenarioIdx, aEventIdx,
-                                                   aAreExpectedEventsLeft,
-                                                   aInvokerStatus)
+eventQueue.invokerStatusToMsg =
+  function eventQueue_invokerStatusToMsg(aInvokerStatus, aMsg)
 {
-  if (!gLogger.isEnabled()) // debug stuff
-    return;
-
-  // Dump DOM event information. Skip a11y event since it is dumped by
-  // gA11yEventObserver.
-  if (aOrigEvent instanceof nsIDOMEvent) {
-    var info = "Event type: " + eventQueue.getEventTypeAsString(aOrigEvent);
-    info += ". Target: " + eventQueue.getEventTargetDescr(aOrigEvent);
-    gLogger.logToDOM(info);
-  }
-
-  var msg = "unhandled expected events: " + aAreExpectedEventsLeft +
-    ", invoker status: ";
+  var msg = "invoker status: ";
   switch (aInvokerStatus) {
     case kInvokerNotScheduled:
       msg += "not scheduled";
       break;
     case kInvokerPending:
       msg += "pending";
       break;
     case kInvokerCanceled:
       msg += "canceled";
       break;
   }
 
-  gLogger.logToConsole(msg);
-  gLogger.logToDOM(msg);
+  if (aMsg)
+    msg += " (" + aMsg + ")";
+
+  return msg;
+}
 
-  if (!aMatchedChecker)
-    return;
+eventQueue.logEvent = function eventQueue_logEvent(aOrigEvent, aMatchedChecker,
+                                                   aScenarioIdx, aEventIdx,
+                                                   aAreExpectedEventsLeft,
+                                                   aInvokerStatus)
+{
+  // Dump DOM event information. Skip a11y event since it is dumped by
+  // gA11yEventObserver.
+  if (aOrigEvent instanceof nsIDOMEvent) {
+    var info = "Event type: " + eventQueue.getEventTypeAsString(aOrigEvent);
+    info += ". Target: " + eventQueue.getEventTargetDescr(aOrigEvent);
+    gLogger.logToDOM(info);
+  }
 
-  var msg = "EQ: ";
-  var emphText = "matched ";
+  var infoMsg = "unhandled expected events: " + aAreExpectedEventsLeft +
+    ", "  + eventQueue.invokerStatusToMsg(aInvokerStatus);
 
   var currType = eventQueue.getEventTypeAsString(aMatchedChecker);
   var currTargetDescr = eventQueue.getEventTargetDescr(aMatchedChecker);
   var consoleMsg = "*****\nScenario " + aScenarioIdx + 
-    ", event " + aEventIdx + " matched: " + currType + "\n*****";
+    ", event " + aEventIdx + " matched: " + currType + "\n" + infoMsg + "\n*****";
   gLogger.logToConsole(consoleMsg);
 
-  msg += " event, type: " + currType + ", target: " + currTargetDescr;
-
+  var emphText = "matched ";
+  var msg = "EQ event, type: " + currType + ", target: " + currTargetDescr +
+    ", " + infoMsg;
   gLogger.logToDOM(msg, true, emphText);
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Action sequence
 
 /**
--- a/accessible/tests/mochitest/states/test_doc_busy.html
+++ b/accessible/tests/mochitest/states/test_doc_busy.html
@@ -15,17 +15,17 @@
   <script type="application/javascript"
           src="../role.js"></script>
   <script type="application/javascript"
           src="../states.js"></script>
   <script type="application/javascript"
           src="../events.js"></script>
 
   <script type="application/javascript">
-    gA11yEventDumpToConsole = true; // debugging stuff
+    //gA11yEventDumpToConsole = true; // debugging stuff
 
     function loadFile()
     {
       var eventSeq = [
         new stateChangeChecker(STATE_BUSY, false, true, document, null, false, true),
         new stateChangeChecker(STATE_BUSY, false, false, document)
       ];
       defineScenario(this, eventSeq); // both events were fired