Bug 1060102: added test cases for non trickle ICE offer-answer r=bwc a=lmandel
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Sat, 11 Oct 2014 08:30:21 -0400
changeset 225660 e05a92abe9a804e09820eea610b858457e12ccca
parent 225659 28381a1a927fd1bbecccd34fcce59ab971f7a18b
child 225661 65c0a4f2b0e97fd7b11e4adaa950825500e4f14e
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbwc, lmandel
bugs1060102
milestone34.0a2
Bug 1060102: added test cases for non trickle ICE offer-answer r=bwc a=lmandel
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/nonTrickleIce.js
dom/media/tests/mochitest/pc.js
dom/media/tests/mochitest/test_peerConnection_noTrickleAnswer.html
dom/media/tests/mochitest/test_peerConnection_noTrickleOffer.html
dom/media/tests/mochitest/test_peerConnection_noTrickleOfferAnswer.html
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 support-files =
   head.js
   constraints.js
   mediaStreamPlayback.js
+  nonTrickleIce.js
   pc.js
   templates.js
   NetworkPreparationChromeScript.js
   blacksilence.js
   turnConfig.js
 
 [test_dataChannel_basicAudio.html]
 skip-if = toolkit == 'gonk' # Bug 962984 for debug, bug 963244 for opt
@@ -85,16 +86,22 @@ skip-if = toolkit == 'gonk' # b2g (Bug 1
 [test_peerConnection_bug1013809.html]
 skip-if = toolkit == 'gonk' # b2g emulator seems to be too slow (Bug 1016498 and 1008080)
 [test_peerConnection_bug1042791.html]
 skip-if = buildapp == 'b2g' || os == 'android' # bug 1043403
 [test_peerConnection_close.html]
 skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
 [test_peerConnection_errorCallbacks.html]
 skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
+[test_peerConnection_noTrickleAnswer.html]
+skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
+[test_peerConnection_noTrickleOffer.html]
+skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
+[test_peerConnection_noTrickleOfferAnswer.html]
+skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
 [test_peerConnection_offerRequiresReceiveAudio.html]
 skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_offerRequiresReceiveVideo.html]
 skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_offerRequiresReceiveVideoAudio.html]
 skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
 [test_peerConnection_replaceTrack.html]
 skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/nonTrickleIce.js
@@ -0,0 +1,130 @@
+/* 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/. */
+
+function makeOffererNonTrickle(chain) {
+  chain.replace('PC_LOCAL_SETUP_ICE_HANDLER', [
+    ['PC_LOCAL_SETUP_NOTRICKLE_ICE_HANDLER',
+      function (test) {
+        test.pcLocalWaitingForEndOfTrickleIce = false;
+        // We need to install this callback before calling setLocalDescription
+        // otherwise we might miss callbacks
+        test.pcLocal.setupIceCandidateHandler(test, function () {
+            // We ignore ICE candidates because we want the full offer
+          } , function (label) {
+            if (test.pcLocalWaitingForEndOfTrickleIce) {
+              // This callback is needed for slow environments where ICE
+              // trickling has not finished before the other side needs the
+              // full SDP. In this case, this call to test.next() will complete
+              // the PC_REMOTE_WAIT_FOR_OFFER step (see below).
+              info("Looks like we were still waiting for Trickle to finish");
+              // TODO replace this with a Promise
+              test.next();
+            }
+          });
+        // We can't wait for trickle to finish here as it will only start once
+        // we have called setLocalDescription in the next step
+        test.next();
+      }
+    ]
+  ]);
+  chain.replace('PC_REMOTE_GET_OFFER', [
+    ['PC_REMOTE_WAIT_FOR_OFFER',
+      function (test) {
+        if (test.pcLocal.endOfTrickleIce) {
+          info("Trickle ICE finished already");
+          test.next();
+        } else {
+          info("Waiting for trickle ICE to finish");
+          test.pcLocalWaitingForEndOfTrickleIce = true;
+          // In this case we rely on the callback from
+          // PC_LOCAL_SETUP_NOTRICKLE_ICE_HANDLER above to proceed to the next
+          // step once trickle is finished.
+        }
+      }
+    ],
+    ['PC_REMOTE_GET_FULL_OFFER',
+      function (test) {
+        test._local_offer = test.pcLocal.localDescription;
+        test._offer_constraints = test.pcLocal.constraints;
+        test._offer_options = test.pcLocal.offerOptions;
+        test.next();
+      }
+    ]
+  ]);
+  chain.insertAfter('PC_REMOTE_SANE_REMOTE_SDP', [
+    ['PC_REMOTE_REQUIRE_REMOTE_SDP_CANDIDATES',
+      function (test) {
+        info("test.pcLocal.localDescription.sdp: " + JSON.stringify(test.pcLocal.localDescription.sdp));
+        info("test._local_offer.sdp" + JSON.stringify(test._local_offer.sdp));
+        ok(!test.localRequiresTrickleIce, "Local does NOT require trickle");
+        ok(test._local_offer.sdp.contains("a=candidate"), "offer has ICE candidates")
+        // TODO check for a=end-of-candidates once implemented
+        test.next();
+      }
+    ]
+  ]);
+}
+
+function makeAnswererNonTrickle(chain) {
+  chain.replace('PC_REMOTE_SETUP_ICE_HANDLER', [
+    ['PC_REMOTE_SETUP_NOTRICKLE_ICE_HANDLER',
+      function (test) {
+        test.pcRemoteWaitingForEndOfTrickleIce = false;
+        // We need to install this callback before calling setLocalDescription
+        // otherwise we might miss callbacks
+        test.pcRemote.setupIceCandidateHandler(test, function () {
+          // We ignore ICE candidates because we want the full answer
+          }, function (label) {
+            if (test.pcRemoteWaitingForEndOfTrickleIce) {
+              // This callback is needed for slow environments where ICE
+              // trickling has not finished before the other side needs the
+              // full SDP. In this case this callback will call the step after
+              // PC_LOCAL_WAIT_FOR_ANSWER
+              info("Looks like we were still waiting for Trickle to finish");
+              // TODO replace this with a Promise
+              test.next();
+            }
+          });
+        // We can't wait for trickle to finish here as it will only start once
+        // we have called setLocalDescription in the next step
+        test.next();
+      }
+    ]
+  ]);
+  chain.replace('PC_LOCAL_GET_ANSWER', [
+    ['PC_LOCAL_WAIT_FOR_ANSWER',
+      function (test) {
+        if (test.pcRemote.endOfTrickleIce) {
+          info("Trickle ICE finished already");
+          test.next();
+        } else {
+          info("Waiting for trickle ICE to finish");
+          test.pcRemoteWaitingForEndOfTrickleIce = true;
+          // In this case we rely on the callback from
+          // PC_REMOTE_SETUP_NOTRICKLE_ICE_HANDLER above to proceed to the next
+          // step once trickle is finished.
+        }
+      }
+    ],
+    ['PC_LOCAL_GET_FULL_ANSWER',
+      function (test) {
+        test._remote_answer = test.pcRemote.localDescription;
+        test._answer_constraints = test.pcRemote.constraints;
+        test.next();
+      }
+    ]
+  ]);
+  chain.insertAfter('PC_LOCAL_SANE_REMOTE_SDP', [
+    ['PC_LOCAL_REQUIRE_REMOTE_SDP_CANDIDATES',
+      function (test) {
+        info("test.pcRemote.localDescription.sdp: " + JSON.stringify(test.pcRemote.localDescription.sdp));
+        info("test._remote_answer.sdp" + JSON.stringify(test._remote_answer.sdp));
+        ok(!test.remoteRequiresTrickleIce, "Remote does NOT require trickle");
+        ok(test._remote_answer.sdp.contains("a=candidate"), "answer has ICE candidates")
+        // TODO check for a=end-of-candidates once implemented
+        test.next();
+      }
+    ]
+  ]);
+}
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -220,16 +220,30 @@ CommandChain.prototype = {
     if (index > -1) {
       return this._commands.splice(0, index);
     }
 
     return null;
   },
 
   /**
+   * Replaces a single command.
+   *
+   * @param {string} id
+   *        Identifier of the command to be replaced
+   * @param {Array[]} commands
+   *        List of commands
+   * @returns {object[]} Removed commands
+   */
+  replace : function (id, commands) {
+    this.insertBefore(id, commands);
+    return this.remove(id);
+  },
+
+  /**
    * Replaces all commands after the specified one.
    *
    * @param {string} id
    *        Identifier of the command
    * @returns {object[]} Removed commands
    */
   replaceAfter : function (id, commands) {
     var oldCommands = this.removeAfter(id);
@@ -2076,39 +2090,43 @@ PeerConnectionWrapper.prototype = {
 
   /**
    * Setup a onicecandidate handler
    *
    * @param {object} test
    *        A PeerConnectionTest object to which the ice candidates gets
    *        forwarded.
    */
-  setupIceCandidateHandler : function PCW_setupIceCandidateHandler(test) {
+  setupIceCandidateHandler : function
+    PCW_setupIceCandidateHandler(test, candidateHandler, endHandler) {
     var self = this;
     self._local_ice_candidates = [];
     self._remote_ice_candidates = [];
     self._ice_candidates_to_add = [];
 
+    candidateHandler = candidateHandler || test.iceCandidateHandler.bind(test);
+    endHandler = endHandler || test.signalEndOfTrickleIce.bind(test);
+
     function iceCandidateCallback (anEvent) {
       info(self.label + ": received iceCandidateEvent");
       if (!anEvent.candidate) {
         info(self.label + ": received end of trickle ICE event");
         self.endOfTrickleIce = true;
-        test.signalEndOfTrickleIce(self.label);
+        endHandler(self.label);
       } else {
         if (self.endOfTrickleIce) {
           ok(false, "received ICE candidate after end of trickle");
         }
         info(self.label + ": iceCandidate = " + JSON.stringify(anEvent.candidate));
         ok(anEvent.candidate.candidate.length > 0, "ICE candidate contains candidate");
         // we don't support SDP MID's yet
         ok(anEvent.candidate.sdpMid.length === 0, "SDP MID has length zero");
         ok(typeof anEvent.candidate.sdpMLineIndex === 'number', "SDP MLine Index needs to exist");
         self._local_ice_candidates.push(anEvent.candidate);
-        test.iceCandidateHandler(self.label, anEvent.candidate);
+        candidateHandler(self.label, anEvent.candidate);
       }
     }
 
     self._pc.onicecandidate = iceCandidateCallback;
   },
 
   /**
    * Counts the amount of audio tracks in a given media constraint.
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_noTrickleAnswer.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="head.js"></script>
+  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+  <script type="application/javascript" src="nonTrickleIce.js"></script>
+  <script type="application/javascript" src="pc.js"></script>
+  <script type="application/javascript" src="templates.js"></script>
+  <script type="application/javascript" src="turnConfig.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1060102",
+    title: "Basic audio only SDP answer without trickle ICE"
+  });
+
+  var test;
+  runNetworkTest(function (options) {
+    test = new PeerConnectionTest(options);
+    makeAnswererNonTrickle(test.chain);
+    test.setMediaConstraints([{audio: true}], [{audio: true}]);
+    test.run();
+  });
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_noTrickleOffer.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="head.js"></script>
+  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+  <script type="application/javascript" src="nonTrickleIce.js"></script>
+  <script type="application/javascript" src="pc.js"></script>
+  <script type="application/javascript" src="templates.js"></script>
+  <script type="application/javascript" src="turnConfig.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1060102",
+    title: "Basic audio only SDP offer without trickle ICE"
+  });
+
+  var test;
+  runNetworkTest(function (options) {
+    test = new PeerConnectionTest(options);
+    makeOffererNonTrickle(test.chain);
+    test.setMediaConstraints([{audio: true}], [{audio: true}]);
+    test.run();
+  });
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_noTrickleOfferAnswer.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="head.js"></script>
+  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+  <script type="application/javascript" src="nonTrickleIce.js"></script>
+  <script type="application/javascript" src="pc.js"></script>
+  <script type="application/javascript" src="templates.js"></script>
+  <script type="application/javascript" src="turnConfig.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1060102",
+    title: "Basic audio only SDP offer and answer without trickle ICE"
+  });
+
+  var test;
+  runNetworkTest(function (options) {
+    test = new PeerConnectionTest(options);
+    makeOffererNonTrickle(test.chain);
+    makeAnswererNonTrickle(test.chain);
+    test.setMediaConstraints([{audio: true}], [{audio: true}]);
+    test.run();
+  });
+</script>
+</pre>
+</body>
+</html>