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 209541 46b2f793c2c916833a2720f76e9f52b6f2b0ca76
parent 209540 963d24ebf03b282bbf7b7fa0eabf20f71aefee8b
child 209542 883279fdc2c6e4b4e00bf81c5647fc357c083fde
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbwc
bugs1060102
milestone35.0a1
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>