Bug 1348050 - Part 6: Expand the original test to verify src attribute. r=baku, mayhemer draft
authorTom Tung <shes050117@gmail.com>
Thu, 04 May 2017 16:09:17 +0800
changeset 574698 00455e82876cb1724af203bfeefe168edb8d50dd
parent 574697 2758db003b3d7be23d3636adfd4e5ee398e93922
child 627688 68cee7dc710eb4e8eca1ec1a9ac0583cc663230e
push id57805
push userttung@mozilla.com
push dateTue, 09 May 2017 10:10:38 +0000
reviewersbaku, mayhemer
bugs1348050
milestone55.0a1
Bug 1348050 - Part 6: Expand the original test to verify src attribute. r=baku, mayhemer Since there are some mechanism to prevent from loading multiplace resorce at a same time for an element, I rewrote the test to isolate each subtests and make sure they will not bother each other. MozReview-Commit-ID: 59h8rzjDxKj
dom/base/test/test_urgent_start.html
--- a/dom/base/test/test_urgent_start.html
+++ b/dom/base/test/test_urgent_start.html
@@ -1,15 +1,15 @@
 <!DOCTYPE HTML>
 <!--
   https://bugzilla.mozilla.org/show_bug.cgi?id=1348050
   Test for fetch and xhr to guarantee we only mark channel as urgent-start when
   it is triggered by user input events.
 
-  For { Fetch, XHR }, do the test as following:
+  For { Fetch, SRC-*, XHR }, do the test as following:
   Step 1: Verify them not mark the channel when there is no any input event.
   Step 2: Verify them mark the channel there is a user input event.
   Step 3: Verify them not mark the channel when there is a non input event.
 
   In each steps, it shows that we only mark channel on direct triggering task.
   We won't mark the channel for additional task(setTimeout) or
   micro-task(promise).
 -->
@@ -19,29 +19,41 @@
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet"
         type="text/css"
         href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="text/javascript" src="manifest.js"></script>
 </head>
 <body>
+<img id="image"></body>
+<audio autoplay id="audio"></audio>
+<iframe id="iframe"></iframe>
+<input type="image" id="input"></input>
+<embed id="embed"></embed>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 const { classes: Cc, interfaces: Ci } = Components;
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(runTest);
 
-const topic = "http-on-opening-request";
-const url = "http://mochi.test:8888/chrome/dom/base/test/file_empty.html";
+const topic_request = "http-on-opening-request";
+const topic_response = "http-on-examine-response";
+const topic_cachedResponse = "http-on-examine-cached-response";
+const scope = "http://mochi.test:8888/chrome/dom/base/test/"
+const url = scope + "file_empty.html";
 
 let expectedResults = [];
 let testcases = [
   "fetch",
+  "src-embed",
+  "src-img",
+  "src-input",
+  "src-media",
   "xhr",
 ];
 let testcase;
 
 function isUrgentStart(aClassFlags) {
   if (!aClassFlags) {
     return false;
   }
@@ -59,107 +71,146 @@ function testSetTimeout() {
 }
 
 // Test for promise chain (micro-task)
 function testPromise() {
   return Promise.resolve().then(testSimple);
 }
 
 function testSimple() {
+  let testUrl = url + "?" + expectedResults.length;
+
   if (testcase == "fetch") {
-    return fetch(url);
+    return fetch(testUrl);
+  } else if (testcase == "src-embed") {
+    document.getElementById('embed').src = testUrl;
+    return Promise.resolve();
+  } else if (testcase == "src-img") {
+    document.getElementById('image').src = testUrl;
+    return Promise.resolve();
+  } else if (testcase == "src-input") {
+    document.getElementById('input').src = testUrl;
+    return Promise.resolve();
+  } else if (testcase == "src-media") {
+    document.getElementById('audio').src = testUrl;
+    return Promise.resolve();
   } else if (testcase == "xhr") {
-    return new Promise(aResolve => {
-      let xhr = new XMLHttpRequest();
-      xhr.open("GET", url, false);
-      xhr.send(null);
-      aResolve();
-    });
+    let xhr = new XMLHttpRequest();
+    xhr.open("GET", testUrl, true);
+    xhr.send(null);
+    return Promise.resolve();
   }
 
   ok(false, "Shouldn't go here.");
 }
 
-function sendRequsetAndCheckUrgentStart() {
+function sendRequsetAndCheckUrgentStart(aEventToTest) {
   info("SendRequsetAndCheckUrgentStart");
 
-  let promise_resolve;
-  let promise = new Promise(aResolve => { promise_resolve = aResolve; });
+  let promise1, promise2;
+  let promise1_resolve, promise2_resolve;
 
   function checkUrgentStart(aSubject) {
     var channel = aSubject.QueryInterface(Ci.nsIChannel);
-    if (!channel.URI.spec.endsWith(url)) {
+    if (channel.URI.spec.indexOf(scope) === -1 ) {
       return;
     }
 
     info("CheckUrgentStart");
 
     let cos = channel.QueryInterface(Ci.nsIClassOfService);
 
     let expectedResult = expectedResults.shift();
     is(isUrgentStart(cos.classFlags), expectedResult,
        "Expect get: " + expectedResult + ", get: " +
        isUrgentStart(cos.classFlags) + " in the " +
        (9 - expectedResults.length) + " test of " + testcase);
 
-    // Resolve if we've tested each three conditions
-    // (simple, promise, setTimeout).
-    if (expectedResults.length % 3 === 0) {
-      SpecialPowers.removeObserver(checkUrgentStart, topic);
-      promise_resolve();
+    // Make sure we've run the check.
+    promise1_resolve();
+  }
+
+  // Resolve this after we've gotten response to prevent from sending too many
+  // requests to Necko in a short time.
+  function getResponse(aSubject) {
+    var channel = aSubject.QueryInterface(Ci.nsIChannel);
+    if (channel.URI.spec.indexOf(scope) === -1 ) {
+      return;
     }
+    info("GetResponse");
+
+    promise2_resolve();
   }
 
-  SpecialPowers.addObserver(checkUrgentStart, topic);
+  SpecialPowers.addObserver(checkUrgentStart, topic_request);
+  SpecialPowers.addObserver(getResponse, topic_response);
+  SpecialPowers.addObserver(getResponse, topic_cachedResponse);
 
-  return Promise.all([testSimple(), testSetTimeout(), testPromise(), promise]);
+  return Promise.resolve()
+    .then(() => {
+      promise1 = new Promise(aResolve => { promise1_resolve = aResolve; });
+      promise2 = new Promise(aResolve => { promise2_resolve = aResolve; });
+      return Promise.all([addListenerAndSendEvent(testSimple, aEventToTest),
+                          promise1,
+                          promise2]);
+    })
+    .then(() => {
+      promise1 = new Promise(aResolve => { promise1_resolve = aResolve; });
+      promise2 = new Promise(aResolve => { promise2_resolve = aResolve; });
+      return Promise.all([addListenerAndSendEvent(testSetTimeout, aEventToTest),
+                          promise1,
+                          promise2]);
+    })
+    .then(() => {
+      promise1 = new Promise(aResolve => { promise1_resolve = aResolve; });
+      promise2 = new Promise(aResolve => { promise2_resolve = aResolve; });
+      return Promise.all([addListenerAndSendEvent(testPromise, aEventToTest),
+                          promise1,
+                          promise2]);
+    })
+    .then(() => {
+      // remove obs if we've tested each three conditions
+      // (simple, promise, setTimeout).
+      SpecialPowers.removeObserver(checkUrgentStart, topic_request);
+      SpecialPowers.removeObserver(getResponse,topic_response);
+      SpecialPowers.removeObserver(getResponse, topic_cachedResponse);
+      return Promise.resolve();
+    });
 }
 
-function userInputEventTriggerRequestCheckUrgentStart() {
-  info("UserInputEventTriggerRequestCheckUrgentStart");
-
-  let promise_resolve;
-  let promise = new Promise(aResolve => { promise_resolve = aResolve; });
-
-  info("AddUserInputEventListener");
+function addListenerAndSendEvent(aFunction, aEventToTest) {
+  info("AddListenerAndSendEvent:" + aEventToTest);
 
   let eventHandle = function () {
-    sendRequsetAndCheckUrgentStart().then(_ => promise_resolve());
+    return aFunction();
+  };
+
+  if (aEventToTest === TestEvent.USER_INPUT_EVENT) {
+    // User Input Event
+    window.addEventListener("mousedown", eventHandle, {once: true});
+  } else if (aEventToTest === TestEvent.NONUSER_INPUT_EVENT) {
+    window.addEventListener("message", eventHandle, {once: true});
   }
-  // User Input Event
-  window.addEventListener("mousedown", eventHandle, {once: true});
 
-  info("SendUserInputEvent");
-
-  var utils = SpecialPowers.getDOMWindowUtils(window);
-  utils.sendMouseEvent("mousedown", 1, 1, 0, 1, 0);
-
-  return promise;
+  if (aEventToTest === TestEvent.USER_INPUT_EVENT) {
+    // User Input Event
+    var utils = SpecialPowers.getDOMWindowUtils(window);
+    utils.sendMouseEvent("mousedown", 1, 1, 0, 1, 0);
+  } else if (aEventToTest === TestEvent.NONUSER_INPUT_EVENT) {
+    window.postMessage("hello", "*");
+  } else if (aEventToTest === TestEvent.NOEVENT) {
+    eventHandle();
+  }
 }
 
-function nonUserInputEventTriggerRequestCheckUrgentStart() {
-  info("NonUserInputEventTriggerRequestCheckUrgentStart");
-
-  let promise_resolve;
-  let promise = new Promise(aResolve => { promise_resolve = aResolve; });
-
-  info("AddNonUserInputEventListener");
-
-  let eventHandle = function () {
-    sendRequsetAndCheckUrgentStart().then(_ => promise_resolve());
-  }
-  // Non user Input Event
-  window.addEventListener("message", eventHandle, {once: true});
-
-  info("SendNonUserInputEvent");
-
-  window.postMessage("hello", "*");
-
-  return promise;
-}
+const TestEvent = {
+  NOEVENT: 0,
+  USER_INPUT_EVENT: 1,
+  NONUSER_INPUT_EVENT: 2,
+};
 
 function executeTest() {
   is(expectedResults.length, 0, "expectedResults should be 0 be executeTest.");
 
   // We will test fetch first and then xhr.
   testcase = testcases.shift();
   info("Verify " + testcase);
 
@@ -173,26 +224,26 @@ function executeTest() {
     /* SimpleTest with a non user input event */ false,
     /* PromiseTest with a non user input event */ false,
     /* SetTimeoutTest with a non user input event */ false,
   ];
 
   return Promise.resolve()
   // Verify urgent-start is not set when the request is not triggered by any
   // events.
-    .then(sendRequsetAndCheckUrgentStart)
+    .then(() => sendRequsetAndCheckUrgentStart(TestEvent.NOEVENT))
 
   // Verify urgent-start is set only when the request is triggered by a user
   // input event. (not for another microtask (e.g. promise-chain) and
   // task (e.g. setTimeout)).
-    .then(userInputEventTriggerRequestCheckUrgentStart)
+    .then(() => sendRequsetAndCheckUrgentStart(TestEvent.USER_INPUT_EVENT))
 
   // Verify urgent-start is not set when the request is triggered by a non user
   // input event.
-    .then(nonUserInputEventTriggerRequestCheckUrgentStart)
+    .then(() => sendRequsetAndCheckUrgentStart(TestEvent.NONUSER_INPUT_EVENT))
     .then(_ => {
       if (testcases.length !== 0) {
         // Run the other test if we still have tests needed to be run.
         return executeTest();
       }
 
       return Promise.resolve();
     });