diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index 1e4e4a6b89206..ebb6f4591f730 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -1510,6 +1510,8 @@ function PeerConnectionWrapper(label, configuration, h264) { this.constraints = [ ]; this.offerOptions = {}; + this.offerAVCounters = {}; + this.answerAVCounters = {}; this.streams = [ ]; this.mediaCheckers = [ ]; @@ -2208,6 +2210,15 @@ PeerConnectionWrapper.prototype = { } }, + setAudioVideoCounters: function PCW_setAudioVideoCounters(counters, + constraints, options, _dataTracks) { + counters.constraintsAudioTracks = this.countAudioTracksInMediaConstraint(constraints); + counters.constraintsVideoTracks = this.countVideoTracksInMediaConstraint(constraints); + counters.optionsAudioTracks = this.audioInOfferOptions(options); + counters.optionsVideoTracks = this.videoInOfferOptions(options); + counters.dataTracks = _dataTracks; + }, + /* * Counts the amount of audio tracks in a given set of streams. * @@ -2250,37 +2261,33 @@ PeerConnectionWrapper.prototype = { * @param {object} constraintsRemote * The media constraints of the local and remote peer connection object */ - checkMediaTracks : function PCW_checkMediaTracks(constraintsRemote, onSuccess) { + checkMediaTracks : function PCW_checkMediaTracks(localCounters, remoteCounters, onSuccess) { var self = this; var addStreamTimeout = null; - function _checkMediaTracks(constraintsRemote, onSuccess) { + function _checkMediaTracks(onSuccess) { if (addStreamTimeout !== null) { clearTimeout(addStreamTimeout); } - var localConstraintAudioTracks = - self.countAudioTracksInMediaConstraint(self.constraints); + var localConstraintAudioTracks = localCounters.constraintsAudioTracks; var localStreams = self._pc.getLocalStreams(); var localAudioTracks = self.countAudioTracksInStreams(localStreams, false); is(localAudioTracks, localConstraintAudioTracks, self + ' has ' + localAudioTracks + ' local audio tracks'); - var localConstraintVideoTracks = - self.countVideoTracksInMediaConstraint(self.constraints); + var localConstraintVideoTracks = localCounters.constraintsVideoTracks; var localVideoTracks = self.countVideoTracksInStreams(localStreams, false); is(localVideoTracks, localConstraintVideoTracks, self + ' has ' + localVideoTracks + ' local video tracks'); - var remoteConstraintAudioTracks = - self.countAudioTracksInMediaConstraint(constraintsRemote); + var remoteConstraintAudioTracks = remoteCounters.constraintsAudioTracks; var remoteStreams = self._pc.getRemoteStreams(); var remoteAudioTracks = self.countAudioTracksInStreams(remoteStreams, false); is(remoteAudioTracks, remoteConstraintAudioTracks, self + ' has ' + remoteAudioTracks + ' remote audio tracks'); - var remoteConstraintVideoTracks = - self.countVideoTracksInMediaConstraint(constraintsRemote); + var remoteConstraintVideoTracks = remoteCounters.constraintsVideoTracks; var remoteVideoTracks = self.countVideoTracksInStreams(remoteStreams, false); is(remoteVideoTracks, remoteConstraintVideoTracks, self + ' has ' + remoteVideoTracks + ' remote video tracks'); @@ -2290,19 +2297,18 @@ PeerConnectionWrapper.prototype = { // we have to do this check as the onaddstream never fires if the remote // stream has no track at all! - var expectedRemoteTracks = - self.countAudioTracksInMediaConstraint(constraintsRemote) + - self.countVideoTracksInMediaConstraint(constraintsRemote); + var expectedRemoteTracks = remoteCounters.constraintsAudioTracks + + remoteCounters.constraintsVideoTracks; // TODO: remove this once Bugs 998552 and 998546 are closed if ((self.onAddStreamFired) || (expectedRemoteTracks == 0)) { - _checkMediaTracks(constraintsRemote, onSuccess); + _checkMediaTracks(onSuccess); } else { info(self + " checkMediaTracks() got called before onAddStream fired"); // we rely on the outer mochitest timeout to catch the case where // onaddstream never fires self.addStreamCallbacks.checkMediaTracks = function() { - _checkMediaTracks(constraintsRemote, onSuccess); + _checkMediaTracks(onSuccess); }; addStreamTimeout = setTimeout(function () { ok(self.onAddStreamFired, self + " checkMediaTracks() timed out waiting for onaddstream event to fire"); @@ -2313,11 +2319,9 @@ PeerConnectionWrapper.prototype = { } }, - verifySdp : function PCW_verifySdp(desc, expectedType, constraints, - offerOptions, trickleIceCallback) { + verifySdp : function PCW_verifySdp(desc, expectedType, counters, + trickleIceCallback) { 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"); @@ -2336,10 +2340,7 @@ PeerConnectionWrapper.prototype = { //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); - } + var audioTracks = Math.max(counters.constraintsAudioTracks, counters.optionsAudioTracks); info("expected audio tracks: " + audioTracks); if (audioTracks == 0) { ok(!desc.sdp.contains("m=audio"), "audio m-line is absent from SDP"); @@ -2353,10 +2354,7 @@ PeerConnectionWrapper.prototype = { } //TODO: how to handle media contraints + offer options - var videoTracks = this.countVideoTracksInMediaConstraint(constraints); - if (constraints.length === 0) { - videoTracks = this.videoInOfferOptions(offerOptions); - } + var videoTracks = Math.max(counters.constraintsVideoTracks, counters.optionsVideoTracks); info("expected video tracks: " + videoTracks); if (videoTracks == 0) { ok(!desc.sdp.contains("m=video"), "video m-line is absent from SDP"); @@ -2534,6 +2532,40 @@ PeerConnectionWrapper.prototype = { } }, + /** + * Compares amount of established ICE connection according to ICE candidate + * pairs in the RTCP reporting with the expected amount of connection based + * on the constraints. + * + * @param {object} stats + * The stats to check for ICE candidate pairs + * @param {object} counters + * The counters for media and data tracks based on constraints + * @param {object} answer + * The SDP answer to check for SDP bundle support + */ + checkRtcpIceConnections : function PCW_checkRtcpIceConnections(stats, + counters, answer) { + var iceConnections = 0; + Object.keys(stats).forEach(function(name) { + if ((stats[name].type === "candidatepair") && + (stats[name].state === "succeeded")) { + iceConnections += 1; + } + }); + info("ICE connections according to RTCP: " + iceConnections); + if (answer.sdp.contains('a=group:BUNDLE')) { + is(iceConnections, 1, "RTCP reports exactly 1 ICE connection"); + } else { + var audioTracks = Math.max(counters.constraintsAudioTracks, counters.optionsAudioTracks); + var videoTracks = Math.max(counters.constraintsVideoTracks, counters.optionsVideoTracks); + var dataTracks = counters.dataTracks; + var audioVideoDataTracks = audioTracks + videoTracks + dataTracks; + info("expected audio + video + data tracks: " + audioVideoDataTracks); + is(audioVideoDataTracks, iceConnections, "RTCP ICE connections matches expected A/V tracks"); + } + }, + /** * Property-matching function for finding a certain stat in passed-in stats * diff --git a/dom/media/tests/mochitest/templates.js b/dom/media/tests/mochitest/templates.js index be034f445bd12..051fcdf75d34f 100644 --- a/dom/media/tests/mochitest/templates.js +++ b/dom/media/tests/mochitest/templates.js @@ -216,12 +216,29 @@ var commandsPeerConnection = [ }); } ], + [ + 'PC_LOCAL_SET_AUDIO_VIDEO_COUNTERS_OFFER', + function (test) { + test.pcLocal.setAudioVideoCounters(test.pcLocal.offerAVCounters, + test._offer_constraints, test._offer_options, 0); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], + [ + 'PC_REMOTE_SET_AUDIO_VIDEO_COUNTERS_OFFER', + function (test) { + test.pcRemote.setAudioVideoCounters(test.pcRemote.offerAVCounters, + test._offer_constraints, test._offer_options, 0); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], [ 'PC_LOCAL_SANE_LOCAL_SDP', function (test) { test.pcLocal.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, - function(trickle) { + test.pcLocal.offerAVCounters, function(trickle) { test.pcLocal.localRequiresTrickleIce = trickle; }); test.next(); @@ -231,8 +248,7 @@ var commandsPeerConnection = [ 'PC_REMOTE_SANE_REMOTE_SDP', function (test) { test.pcRemote.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, - function (trickle) { + test.pcRemote.offerAVCounters, function (trickle) { test.pcRemote.remoteRequiresTrickleIce = trickle; }); test.next(); @@ -340,12 +356,29 @@ var commandsPeerConnection = [ ); } ], + [ + 'PC_LOCAL_SET_AUDIO_VIDEO_COUNTERS_ANSWER', + function (test) { + test.pcLocal.setAudioVideoCounters(test.pcLocal.answerAVCounters, + test._answer_constraints, test._offer_options, 0); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], + [ + 'PC_REMOTE_SET_AUDIO_VIDEO_COUNTERS_ANSWER', + function (test) { + test.pcRemote.setAudioVideoCounters(test.pcRemote.answerAVCounters, + test._answer_constraints, test._offer_options, 0); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], [ 'PC_REMOTE_SANE_LOCAL_SDP', function (test) { test.pcRemote.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, - function (trickle) { + test.pcRemote.answerAVCounters, function (trickle) { test.pcRemote.localRequiresTrickleIce = trickle; }); test.next(); @@ -355,8 +388,7 @@ var commandsPeerConnection = [ 'PC_LOCAL_SANE_REMOTE_SDP', function (test) { test.pcLocal.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, - function (trickle) { + test.pcLocal.answerAVCounters, function (trickle) { test.pcLocal.remoteRequiresTrickleIce = trickle; }); test.next(); @@ -449,7 +481,8 @@ var commandsPeerConnection = [ [ 'PC_LOCAL_CHECK_MEDIA_TRACKS', function (test) { - test.pcLocal.checkMediaTracks(test._answer_constraints, function () { + test.pcLocal.checkMediaTracks(test.pcLocal.offerAVCounters, + test.pcLocal.answerAVCounters, function () { test.next(); }); } @@ -457,7 +490,8 @@ var commandsPeerConnection = [ [ 'PC_REMOTE_CHECK_MEDIA_TRACKS', function (test) { - test.pcRemote.checkMediaTracks(test._offer_constraints, function () { + test.pcRemote.checkMediaTracks(test.pcRemote.answerAVCounters, + test.pcRemote.offerAVCounters, function () { test.next(); }); } @@ -496,6 +530,24 @@ var commandsPeerConnection = [ }); } ], + [ + 'PC_LOCAL_CHECK_ICE_CONNECTIONS', + function (test) { + test.pcLocal.getStats(null, function(stats) { + test.pcLocal.checkRtcpIceConnections(stats, test.pcLocal.offerAVCounters, test.originalAnswer); + test.next(); + }); + } + ], + [ + 'PC_REMOTE_CHECK_ICE_CONNECTIONS', + function (test) { + test.pcRemote.getStats(null, function(stats) { + test.pcRemote.checkRtcpIceConnections(stats, test.pcRemote.answerAVCounters, test.originalAnswer); + test.next(); + }); + } + ], [ 'PC_LOCAL_CHECK_GETSTATS_AUDIOTRACK_OUTBOUND', function (test) { @@ -837,12 +889,29 @@ var commandsDataChannel = [ }); } ], + [ + 'PC_LOCAL_SET_AUDIO_VIDEO_COUNTERS_OFFER', + function (test) { + test.pcLocal.setAudioVideoCounters(test.pcLocal.offerAVCounters, + test._offer_constraints, test._offer_options, 1); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], + [ + 'PC_REMOTE_SET_AUDIO_VIDEO_COUNTERS_OFFER', + function (test) { + test.pcRemote.setAudioVideoCounters(test.pcRemote.offerAVCounters, + test._offer_constraints, test._offer_options, 1); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], [ 'PC_LOCAL_SANE_LOCAL_SDP', function (test) { test.pcLocal.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, - function(trickle) { + test.pcLocal.offerAVCounters, function(trickle) { test.pcLocal.localRequiresTrickleIce = trickle; }); test.next(); @@ -852,8 +921,7 @@ var commandsDataChannel = [ 'PC_REMOTE_SANE_REMOTE_SDP', function (test) { test.pcRemote.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, - function (trickle) { + test.pcRemote.offerAVCounters, function (trickle) { test.pcRemote.remoteRequiresTrickleIce = trickle; }); test.next(); @@ -941,12 +1009,29 @@ var commandsDataChannel = [ ); } ], + [ + 'PC_LOCAL_SET_AUDIO_VIDEO_COUNTERS_ANSWER', + function (test) { + test.pcLocal.setAudioVideoCounters(test.pcLocal.answerAVCounters, + test._answer_constraints, test._offer_options, 1); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], + [ + 'PC_REMOTE_SET_AUDIO_VIDEO_COUNTERS_ANSWER', + function (test) { + test.pcRemote.setAudioVideoCounters(test.pcRemote.answerAVCounters, + test._answer_constraints, test._offer_options, 1); + info("Audio/Video counters: " + JSON.stringify(test.pcLocal.offerAVCounters)); + test.next(); + } + ], [ 'PC_REMOTE_SANE_LOCAL_SDP', function (test) { test.pcRemote.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, - function (trickle) { + test.pcRemote.answerAVCounters, function (trickle) { test.pcRemote.localRequiresTrickleIce = trickle; }); test.next(); @@ -956,8 +1041,7 @@ var commandsDataChannel = [ 'PC_LOCAL_SANE_REMOTE_SDP', function (test) { test.pcLocal.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, - function (trickle) { + test.pcLocal.answerAVCounters, function (trickle) { test.pcLocal.remoteRequiresTrickleIce = trickle; }); test.next(); @@ -1078,7 +1162,8 @@ var commandsDataChannel = [ [ 'PC_LOCAL_CHECK_MEDIA_TRACKS', function (test) { - test.pcLocal.checkMediaTracks(test._answer_constraints, function () { + test.pcLocal.checkMediaTracks(test.pcLocal.offerAVCounters, + test.pcLocal.answerAVCounters, function () { test.next(); }); } @@ -1086,7 +1171,8 @@ var commandsDataChannel = [ [ 'PC_REMOTE_CHECK_MEDIA_TRACKS', function (test) { - test.pcRemote.checkMediaTracks(test._offer_constraints, function () { + test.pcRemote.checkMediaTracks(test.pcRemote.answerAVCounters, + test.pcRemote.offerAVCounters, function () { test.next(); }); } @@ -1107,6 +1193,24 @@ var commandsDataChannel = [ }); } ], + [ + 'PC_LOCAL_CHECK_ICE_CONNECTIONS', + function (test) { + test.pcLocal.getStats(null, function(stats) { + test.pcLocal.checkRtcpIceConnections(stats, test.pcLocal.offerAVCounters, test.originalAnswer); + test.next(); + }); + } + ], + [ + 'PC_REMOTE_CHECK_ICE_CONNECTIONS', + function (test) { + test.pcRemote.getStats(null, function(stats) { + test.pcRemote.checkRtcpIceConnections(stats, test.pcRemote.answerAVCounters, test.originalAnswer); + test.next(); + }); + } + ], [ 'SEND_MESSAGE', function (test) { diff --git a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html index fe01f789cbec5..f9bb7474e8ba6 100644 --- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html +++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html @@ -21,6 +21,7 @@ // TODO: Stop using old constraint-like RTCOptions soon (Bug 1064223). // Watch out for case-difference when fixing: { offerToReceiveAudio: true } + test.setMediaConstraints([], [{audio: true}]); test.setOfferOptions({ mandatory: { OfferToReceiveAudio: true } }); test.run(); }); diff --git a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html index 44c74ca6315ec..7d2c2c98ea158 100644 --- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html +++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html @@ -18,9 +18,10 @@ runNetworkTest(function() { var test = new PeerConnectionTest(); + test.setMediaConstraints([], [{video: true}]); // TODO: Stop using old constraint-like RTCOptions soon (Bug 1064223). // Watch out for case-difference when fixing: { offerToReceiveVideo: true } - test.setOfferOptions({ optional: [{ OfferToReceiveAudio: true }] }); + test.setOfferOptions({ optional: [{ OfferToReceiveVideo: true }] }); test.run(); }); diff --git a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html index 65880476e876c..25c0ec428a09e 100644 --- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html +++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html @@ -18,10 +18,8 @@ runNetworkTest(function() { var test = new PeerConnectionTest(); - test.setOfferOptions({ - offerToReceiveVideo: true, - offerToReceiveAudio: true - }); + test.setMediaConstraints([], [{audio: true, video: true}]); + test.setOfferOptions({ offerToReceiveVideo: true, offerToReceiveAudio: true }); test.run(); });