Bug 834138 - Intermittent states/test_doc_busy.html | Test timed out. r=tbsaunde, a=test-only
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 12 Sep 2013 09:10:42 -0400
changeset 154033 8e1dde8bf956b30f32c762e8e84030db7cada96d
parent 154032 74efb2b26f7cf2872dc543f100fd9791a81d8e89
child 154034 b8722497028839afd325680f11f3d2b4491496bb
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde, test-only
bugs834138
milestone25.0a2
Bug 834138 - Intermittent states/test_doc_busy.html | Test timed out. r=tbsaunde, a=test-only
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