Bug 1060102 - added test cases for non trickle ICE offer-answer. r=bwc
☠☠ backed out by f6470e7cf35b ☠ ☠
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Wed, 08 Oct 2014 16:40:00 +0200
changeset 232756 46b2f793c2c916833a2720f76e9f52b6f2b0ca76
parent 232755 963d24ebf03b282bbf7b7fa0eabf20f71aefee8b
child 232757 883279fdc2c6e4b4e00bf81c5647fc357c083fde
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbwc
bugs1060102
milestone35.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 1060102 - added test cases for non trickle ICE offer-answer. r=bwc
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,133 @@
+/* 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) {
+        test._remote_answer = test.pcRemote.localDescription;
+        test._answer_constraints = test.pcRemote.constraints;
+        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._local_offer = test.pcLocal.localDescription;
+        test._offer_constraints = test.pcLocal.constraints;
+        test._offer_options = test.pcLocal.offerOptions;
+        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);
@@ -2080,39 +2094,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>