Bug 1021220 - Verify absence of loopback in SDP offer. r=bwc, a=test-only
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Thu, 31 Jul 2014 17:24:00 -0400
changeset 216705 fdf2f580b665
parent 216704 8e9b139e30b9
child 216706 d4082d3a082c
push id3883
push userryanvm@gmail.com
push date2014-09-11 20:34 +0000
treeherdermozilla-beta@d4082d3a082c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbwc, test-only
bugs1021220
milestone33.0
Bug 1021220 - Verify absence of loopback in SDP offer. r=bwc, a=test-only
dom/media/tests/mochitest/pc.js
dom/media/tests/mochitest/templates.js
dom/media/tests/mochitest/test_peerConnection_bug827843.html
dom/media/tests/mochitest/test_peerConnection_bug835370.html
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -1,14 +1,15 @@
 /* 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/. */
 
 "use strict";
 
+const LOOPBACK_ADDR = "127.0.0.";
 
 const iceStateTransitions = {
   "new": ["checking", "closed"], //Note: 'failed' might need to added here
                                  //      even though it is not in the standard
   "checking": ["new", "connected", "failed", "closed"], //Note: do we need to
                                                         // allow 'completed' in
                                                         // here as well?
   "connected": ["new", "completed", "disconnected", "closed"],
@@ -750,19 +751,19 @@ PeerConnectionTest.prototype.setMediaCon
 function PCT_setMediaConstraints(constraintsLocal, constraintsRemote) {
   if (this.pcLocal)
     this.pcLocal.constraints = constraintsLocal;
   if (this.pcRemote)
     this.pcRemote.constraints = constraintsRemote;
 };
 
 /**
- * Sets the media constraints used on a createOffer call in the test.
+ * Sets the media options used on a createOffer call in the test.
  *
- * @param {object} constraints the media constraints to use on createOffer
+ * @param {object} options the media constraints to use on createOffer
  */
 PeerConnectionTest.prototype.setOfferOptions =
 function PCT_setOfferOptions(options) {
   if (this.pcLocal)
     this.pcLocal.offerOptions = options;
 };
 
 /**
@@ -1891,16 +1892,34 @@ PeerConnectionWrapper.prototype = {
       if (constraints[i].audio) {
         audioTracks++;
       }
     }
     return audioTracks;
   },
 
   /**
+   * Checks for audio in given offer options.
+   *
+   * @param options
+   *        The options to be examined.
+   */
+  audioInOfferOptions : function
+    PCW_audioInOfferOptions(options) {
+    if (!options) {
+      return 0;
+    }
+    if (options.offerToReceiveAudio) {
+      return 1;
+    } else {
+      return 0;
+    }
+  },
+
+  /**
    * Counts the amount of video tracks in a given media constraint.
    *
    * @param constraint
    *        The contraint to be examined.
    */
   countVideoTracksInMediaConstraint : function
     PCW_countVideoTracksInMediaConstraint(constraints) {
     if ((!constraints) || (constraints.length === 0)) {
@@ -1910,16 +1929,34 @@ PeerConnectionWrapper.prototype = {
     for (var i = 0; i < constraints.length; i++) {
       if (constraints[i].video) {
         videoTracks++;
       }
     }
     return videoTracks;
   },
 
+  /**
+   * Checks for video in given offer options.
+   *
+   * @param options
+   *        The options to be examined.
+   */
+  videoInOfferOptions : function
+    PCW_videoInOfferOptions(options) {
+    if (!options) {
+      return 0;
+    }
+    if (options.offerToReceiveVideo) {
+      return 1;
+    } else {
+      return 0;
+    }
+  },
+
   /*
    * Counts the amount of audio tracks in a given set of streams.
    *
    * @param streams
    *        An array of streams (as returned by getLocalStreams()) to be
    *        examined.
    */
   countAudioTracksInStreams : function PCW_countAudioTracksInStreams(streams) {
@@ -2015,16 +2052,69 @@ PeerConnectionWrapper.prototype = {
         ok(self.onAddStreamFired, self + " checkMediaTracks() timed out waiting for onaddstream event to fire");
         if (!self.onAddStreamFired) {
           onSuccess();
         }
       }, 60000);
     }
   },
 
+  verifySdp : function PCW_verifySdp(desc, expectedType, constraints, offerOptions) {
+    info("Examining this SessionDescription: " + JSON.stringify(desc));
+    info("constraints: " + JSON.stringify(constraints));
+    info("offerOptions: " + JSON.stringify(offerOptions));
+    ok(desc, "SessionDescription is not null");
+    is(desc.type, expectedType, "SessionDescription type is " + expectedType);
+    ok(desc.sdp.length > 10, "SessionDescription body length is plausible");
+    ok(desc.sdp.contains("a=ice-ufrag"), "ICE username is present in SDP");
+    ok(desc.sdp.contains("a=ice-pwd"), "ICE password is present in SDP");
+    ok(desc.sdp.contains("a=fingerprint"), "ICE fingerprint is present in SDP");
+    //TODO: update this for loopback support bug 1027350
+    ok(!desc.sdp.contains(LOOPBACK_ADDR), "loopback interface is absent from SDP");
+    //TODO: update this for trickle ICE bug 1041832
+    ok(desc.sdp.contains("a=candidate"), "at least one ICE candidate is present in SDP");
+    //TODO: how can we check for absence/presence of m=application?
+
+    //TODO: how to handle media contraints + offer options
+    var audioTracks = this.countAudioTracksInMediaConstraint(constraints);
+    if (constraints.length === 0) {
+      audioTracks = this.audioInOfferOptions(offerOptions);
+    }
+    info("expected audio tracks: " + audioTracks);
+    if (audioTracks == 0) {
+      ok(!desc.sdp.contains("m=audio"), "audio m-line is absent from SDP");
+    } else {
+      ok(desc.sdp.contains("m=audio"), "audio m-line is present in SDP");
+      ok(desc.sdp.contains("a=rtpmap:109 opus/48000/2"), "OPUS codec is present in SDP");
+      //TODO: ideally the rtcp-mux should be for the m=audio, and not just
+      //      anywhere in the SDP (JS SDP parser bug 1045429)
+      ok(desc.sdp.contains("a=rtcp-mux"), "RTCP Mux is offered in SDP");
+
+    }
+
+    //TODO: how to handle media contraints + offer options
+    var videoTracks = this.countVideoTracksInMediaConstraint(constraints);
+    if (constraints.length === 0) {
+      videoTracks = this.videoInOfferOptions(offerOptions);
+    }
+    info("expected video tracks: " + videoTracks);
+    if (videoTracks == 0) {
+      ok(!desc.sdp.contains("m=video"), "video m-line is absent from SDP");
+    } else {
+      ok(desc.sdp.contains("m=video"), "video m-line is present in SDP");
+      if (this.h264) {
+        ok(desc.sdp.contains("a=rtpmap:126 H264/90000"), "H.264 codec is present in SDP");
+      } else {
+        ok(desc.sdp.contains("a=rtpmap:120 VP8/90000"), "VP8 codec is present in SDP");
+      }
+      ok(desc.sdp.contains("a=rtcp-mux"), "RTCP Mux is offered in SDP");
+    }
+
+  },
+
   /**
    * Check that media flow is present on all media elements involved in this
    * test by waiting for confirmation that media flow is present.
    *
    * @param {Function} onSuccess the success callback when media flow
    *                             is confirmed on all media elements
    */
   checkMediaFlowPresent : function PCW_checkMediaFlowPresent(onSuccess) {
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -120,22 +120,23 @@ var commandsPeerConnection = [
       is(test.pcRemote.iceConnectionState, ICE_NEW,
         "Initial remote ICE connection state is 'new'");
       test.next();
     }
   ],
   [
     'PC_LOCAL_CREATE_OFFER',
     function (test) {
-      test.createOffer(test.pcLocal, function () {
+      test.createOffer(test.pcLocal, function (offer) {
         is(test.pcLocal.signalingState, STABLE,
            "Local create offer does not change signaling state");
         if (!test.pcRemote) {
           send_message({"offer": test.pcLocal._last_offer,
-                        "media_constraints": test.pcLocal.constraints});
+                        "offer_constraints": test.pcLocal.constraints,
+                        "offer_options": test.pcLocal.offerOptions});
         }
         test.next();
       });
     }
   ],
   [
     'PC_LOCAL_SET_LOCAL_DESCRIPTION',
     function (test) {
@@ -146,47 +147,63 @@ var commandsPeerConnection = [
       });
     }
   ],
   [
     'PC_REMOTE_GET_OFFER',
     function (test) {
       if (test.pcLocal) {
         test._local_offer = test.pcLocal._last_offer;
-        test._local_constraints = test.pcLocal.constraints;
+        test._offer_constraints = test.pcLocal.constraints;
+        test._offer_options = test.pcLocal.offerOptions;
         test.next();
       } else {
         wait_for_message().then(function(message) {
           ok("offer" in message, "Got an offer message");
           test._local_offer = new mozRTCSessionDescription(message.offer);
-          test._local_constraints = message.media_constraints;
+          test._offer_constraints = message.offer_constraints;
+          test._offer_options = message.offer_options;
           test.next();
         });
       }
     }
   ],
   [
     'PC_REMOTE_SET_REMOTE_DESCRIPTION',
     function (test) {
       test.setRemoteDescription(test.pcRemote, test._local_offer, HAVE_REMOTE_OFFER, function () {
         is(test.pcRemote.signalingState, HAVE_REMOTE_OFFER,
            "signalingState after remote setRemoteDescription is 'have-remote-offer'");
         test.next();
       });
     }
   ],
   [
+    'PC_LOCAL_SANE_LOCAL_SDP',
+    function (test) {
+      test.pcLocal.verifySdp(test.pcLocal.localDescription, "offer", test._offer_constraints, test._offer_options);
+      test.next();
+    }
+  ],
+  [
+    'PC_REMOTE_SANE_REMOTE_SDP',
+    function (test) {
+      test.pcRemote.verifySdp(test.pcRemote.remoteDescription, "offer", test._offer_constraints, test._offer_options);
+      test.next();
+    }
+  ],
+  [
     'PC_REMOTE_CREATE_ANSWER',
     function (test) {
-      test.createAnswer(test.pcRemote, function () {
+      test.createAnswer(test.pcRemote, function (answer) {
         is(test.pcRemote.signalingState, HAVE_REMOTE_OFFER,
            "Remote createAnswer does not change signaling state");
         if (!test.pcLocal) {
           send_message({"answer": test.pcRemote._last_answer,
-                        "media_constraints": test.pcRemote.constraints});
+                        "answer_constraints": test.pcRemote.constraints});
         }
         test.next();
       });
     }
   ],
   [
     'PC_REMOTE_CHECK_FOR_DUPLICATED_PORTS_IN_SDP',
     function (test) {
@@ -241,39 +258,53 @@ var commandsPeerConnection = [
       });
     }
   ],
   [
     'PC_LOCAL_GET_ANSWER',
     function (test) {
       if (test.pcRemote) {
         test._remote_answer = test.pcRemote._last_answer;
-        test._remote_constraints = test.pcRemote.constraints;
+        test._answer_constraints = test.pcRemote.constraints;
         test.next();
       } else {
         wait_for_message().then(function(message) {
           ok("answer" in message, "Got an answer message");
           test._remote_answer = new mozRTCSessionDescription(message.answer);
-          test._remote_constraints = message.media_constraints;
+          test._answer_constraints = message.answer_constraints;
           test.next();
         });
       }
     }
   ],
   [
     'PC_LOCAL_SET_REMOTE_DESCRIPTION',
     function (test) {
       test.setRemoteDescription(test.pcLocal, test._remote_answer, STABLE, function () {
         is(test.pcLocal.signalingState, STABLE,
            "signalingState after local setRemoteDescription is 'stable'");
         test.next();
       });
     }
   ],
   [
+    'PC_REMOTE_SANE_LOCAL_SDP',
+    function (test) {
+      test.pcRemote.verifySdp(test.pcRemote.localDescription, "answer", test._answer_constraints, test._offer_options);
+      test.next();
+    }
+  ],
+  [
+    'PC_LOCAL_SANE_REMOTE_SDP',
+    function (test) {
+      test.pcLocal.verifySdp(test.pcLocal.remoteDescription, "answer", test._answer_constraints, test._offer_options);
+      test.next();
+    }
+  ],
+  [
     'PC_LOCAL_WAIT_FOR_ICE_CONNECTED',
     function (test) {
       var myTest = test;
       var myPc = myTest.pcLocal;
 
       function onIceConnectedSuccess () {
         info("pcLocal ICE connection state log: " + test.pcLocal.iceConnectionLog);
         ok(true, "pc_local: ICE switched to 'connected' state");
@@ -326,25 +357,25 @@ var commandsPeerConnection = [
         ok(false, "pc_remote: ICE is already in bad state: " + myPc.iceConnectionState);
         myTest.next();
       }
     }
   ],
   [
     'PC_LOCAL_CHECK_MEDIA_TRACKS',
     function (test) {
-      test.pcLocal.checkMediaTracks(test._remote_constraints, function () {
+      test.pcLocal.checkMediaTracks(test._answer_constraints, function () {
         test.next();
       });
     }
   ],
   [
     'PC_REMOTE_CHECK_MEDIA_TRACKS',
     function (test) {
-      test.pcRemote.checkMediaTracks(test._local_constraints, function () {
+      test.pcRemote.checkMediaTracks(test._offer_constraints, function () {
         test.next();
       });
     }
   ],
   [
     'PC_LOCAL_CHECK_MEDIA_FLOW_PRESENT',
     function (test) {
       test.pcLocal.checkMediaFlowPresent(function () {
@@ -476,16 +507,18 @@ var commandsDataChannel = [
     }
   ],
   [
     'PC_LOCAL_CREATE_OFFER',
     function (test) {
       test.pcLocal.createOffer(function (offer) {
         is(test.pcLocal.signalingState, STABLE,
            "Local create offer does not change signaling state");
+        ok(!offer.sdp.contains(LOOPBACK_ADDR),
+           "loopback interface is absent from SDP");
         ok(offer.sdp.contains("m=application"),
            "m=application is contained in the SDP");
         test.next();
       });
     }
   ],
   [
     'PC_LOCAL_SET_LOCAL_DESCRIPTION',
@@ -505,21 +538,37 @@ var commandsDataChannel = [
         function () {
         is(test.pcRemote.signalingState, HAVE_REMOTE_OFFER,
            "signalingState after remote setRemoteDescription is 'have-remote-offer'");
         test.next();
       });
     }
   ],
   [
+    'PC_LOCAL_SANE_LOCAL_SDP',
+    function (test) {
+      test.pcLocal.verifySdp(test.pcLocal.localDescription, "offer", test.pcLocal.constraints);
+      test.next();
+    }
+  ],
+  [
+    'PC_REMOTE_SANE_REMOTE_SDP',
+    function (test) {
+      test.pcRemote.verifySdp(test.pcRemote.remoteDescription, "offer", test.pcLocal.constraints);
+      test.next();
+    }
+  ],
+  [
     'PC_REMOTE_CREATE_ANSWER',
     function (test) {
-      test.createAnswer(test.pcRemote, function () {
+      test.createAnswer(test.pcRemote, function (answer) {
         is(test.pcRemote.signalingState, HAVE_REMOTE_OFFER,
            "Remote create offer does not change signaling state");
+        ok(!answer.sdp.contains(LOOPBACK_ADDR),
+           "loopback interface is absent in SDP");
         test.next();
       });
     }
   ],
   [
     'PC_LOCAL_SETUP_DATA_CHANNEL_CALLBACK',
     function (test) {
       test.waitForInitialDataChannel(test.pcLocal, function () {
@@ -560,16 +609,30 @@ var commandsDataChannel = [
         function () {
         is(test.pcLocal.signalingState, STABLE,
            "signalingState after local setRemoteDescription is 'stable'");
         test.next();
       });
     }
   ],
   [
+    'PC_REMOTE_SANE_LOCAL_SDP',
+    function (test) {
+      test.pcRemote.verifySdp(test.pcRemote.localDescription, "answer", test.pcRemote.constraints);
+      test.next();
+    }
+  ],
+  [
+    'PC_LOCAL_SANE_REMOTE_SDP',
+    function (test) {
+      test.pcLocal.verifySdp(test.pcLocal.remoteDescription, "answer", test.pcRemote.constraints);
+      test.next();
+    }
+  ],
+  [
     'PC_LOCAL_WAIT_FOR_ICE_CONNECTED',
     function (test) {
       var myTest = test;
       var myPc = myTest.pcLocal;
 
       function onIceConnectedSuccess () {
         info("pcLocal ICE connection state log: " + test.pcLocal.iceConnectionLog);
         ok(true, "pc_local: ICE switched to 'connected' state");
--- a/dom/media/tests/mochitest/test_peerConnection_bug827843.html
+++ b/dom/media/tests/mochitest/test_peerConnection_bug827843.html
@@ -13,50 +13,16 @@
 <script type="application/javascript">
   createHTML({
     bug: "827843",
     title: "Ensure that localDescription and remoteDescription are null after close"
   });
 
   var steps = [
     [
-      "CHECK_FOR_SANE_SDP",
-      function (test) {
-        // TODO: We might want to move those checks into the default chain
-        ok(test.pcLocal.localDescription,
-           "test.pcLocal.localDescription is not null");
-        is(test.pcLocal.localDescription.type, "offer",
-           "test.pcLocal.localDescription type is offer");
-        ok(test.pcLocal.localDescription.sdp.length > 10,
-           "test.pcLocal.localDescription body length is plausible");
-
-        ok(test.pcLocal.remoteDescription,
-           "test.pcLocal.remoteDescription is not null");
-        is(test.pcLocal.remoteDescription.type, "answer",
-            "test.pcLocal.remoteDescription type is answer");
-        ok(test.pcLocal.remoteDescription.sdp.length > 10,
-           "test.pcLocal.remoteDescription body length is plausible");
-
-        ok(test.pcRemote.localDescription,
-           "test.pcRemote.localDescription is not null");
-        is(test.pcRemote.localDescription.type, "answer",
-           "test.pcRemote.localDescription type is answer");
-        ok(test.pcRemote.localDescription.sdp.length > 10,
-           "test.pcRemote.localDescription body length is plausible");
-
-        ok(test.pcRemote.remoteDescription,
-           "test.pcRemote.remoteDescription is not null");
-        is(test.pcRemote.remoteDescription.type, "offer",
-           "test.pcRemote.remoteDescription type is offer");
-        ok(test.pcRemote.remoteDescription.sdp.length > 10,
-           "test.pcRemote.remoteDescription body length is plausible");
-
-        test.next();
-      }
-    ], [
       "CHECK_SDP_ON_CLOSED_PC",
       function (test) {
         var description;
         var exception = null;
 
         // handle the event which the close() triggers
         test.pcLocal.onsignalingstatechange = function (state) {
           is(state, "closed", "Received expected onsignalingstatechange event 'closed'");
--- a/dom/media/tests/mochitest/test_peerConnection_bug835370.html
+++ b/dom/media/tests/mochitest/test_peerConnection_bug835370.html
@@ -5,17 +5,17 @@
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="head.js"></script>
   <script type="application/javascript" src="pc.js"></script>
 </head>
 <body>
 <pre id="test">
 <script type="application/javascript">
   createHTML({
-    bug: "825703",
+    bug: "835370",
     title: "PeerConnection.createOffer valid/invalid constraints permutations"
   });
 
   runNetworkTest(function () {
     var pconnect  = new mozRTCPeerConnection();
     var pconnects = new mozRTCPeerConnection();
 
     function step1(offer) {}