Bug 1167443 - Fix verification of end-of-candidates in mochitests. r=mt

This commit is contained in:
Nils Ohlmeier [:drno] 2015-08-24 14:49:41 -07:00
parent dfc93cd111
commit 2de8192c1e
12 changed files with 377 additions and 221 deletions

View File

@ -13,6 +13,7 @@ support-files =
NetworkPreparationChromeScript.js
blacksilence.js
turnConfig.js
sdpUtils.js
[test_dataChannel_basicAudio.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # Bug 962984 for debug, bug 963244 for opt
@ -62,12 +63,18 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 1021776, too --ing
[test_peerConnection_addIceCandidate.html]
[test_peerConnection_basicAudio.html]
skip-if = toolkit == 'gonk' # B2G emulator is too slow to handle a two-way audio call reliably
[test_peerConnection_basicAudioRequireEOC.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
[test_peerConnection_basicAudioVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g(Bug 960442, video support for WebRTC is disabled on b2g), android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_basicAudioVideoCombined.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g(Bug 960442, video support for WebRTC is disabled on b2g), android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_basicAudioVideoNoBundle.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' || (android_version == '18' && debug) # b2g(Bug 960442, video support for WebRTC is disabled on b2g), android(Bug 1189784, timeouts on 4.3 emulator)
[test_peerConnection_basicAudioVideoNoBundleNoRtcpMux.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicAudioVideoNoRtcpMux.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicVideo.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_basicScreenshare.html]

View File

@ -28,19 +28,6 @@ const signalingStateTransitions = {
"closed": []
}
// Also remove mode 0 if it's offered
// Note, we don't bother removing the fmtp lines, which makes a good test
// for some SDP parsing issues.
function removeVP8(sdp) {
var updated_sdp = sdp.replace("a=rtpmap:120 VP8/90000\r\n","");
updated_sdp = updated_sdp.replace("RTP/SAVPF 120 126 97\r\n","RTP/SAVPF 126 97\r\n");
updated_sdp = updated_sdp.replace("RTP/SAVPF 120 126\r\n","RTP/SAVPF 126\r\n");
updated_sdp = updated_sdp.replace("a=rtcp-fb:120 nack\r\n","");
updated_sdp = updated_sdp.replace("a=rtcp-fb:120 nack pli\r\n","");
updated_sdp = updated_sdp.replace("a=rtcp-fb:120 ccm fir\r\n","");
return updated_sdp;
}
var makeDefaultCommands = () => {
return [].concat(commandsPeerConnectionInitial,
commandsGetUserMedia,
@ -72,6 +59,10 @@ function PeerConnectionTest(options) {
options.is_local = "is_local" in options ? options.is_local : true;
options.is_remote = "is_remote" in options ? options.is_remote : true;
options.h264 = "h264" in options ? options.h264 : false;
options.bundle = "bundle" in options ? options.bundle : true;
options.rtcpmux = "rtcpmux" in options ? options.rtcpmux : true;
if (typeof turnServers !== "undefined") {
if ((!options.turn_disabled_local) && (turnServers.local)) {
if (!options.hasOwnProperty("config_local")) {
@ -91,26 +82,24 @@ function PeerConnectionTest(options) {
}
}
if (options.is_local)
this.pcLocal = new PeerConnectionWrapper('pcLocal', options.config_local, options.h264);
else
if (options.is_local) {
this.pcLocal = new PeerConnectionWrapper('pcLocal', options.config_local);
} else {
this.pcLocal = null;
}
if (options.is_remote)
this.pcRemote = new PeerConnectionWrapper('pcRemote', options.config_remote || options.config_local, options.h264);
else
if (options.is_remote) {
this.pcRemote = new PeerConnectionWrapper('pcRemote', options.config_remote || options.config_local);
} else {
this.pcRemote = null;
}
this.steeplechase = this.pcLocal === null || this.pcRemote === null;
options.steeplechase = !options.is_local || !options.is_remote;
// Create command chain instance and assign default commands
this.chain = new CommandChain(this, options.commands);
if (!options.is_local) {
this.chain.filterOut(/^PC_LOCAL/);
}
if (!options.is_remote) {
this.chain.filterOut(/^PC_REMOTE/);
}
this.testOptions = options;
}
/** TODO: consider removing this dependency on timeouts */
@ -332,6 +321,14 @@ function(peer, desc, stateExpected) {
peer.setLocalDescDate = new Date();
});
peer.endOfTrickleSdp = peer.endOfTrickleIce.then(() => {
if (this.testOptions.steeplechase) {
send_message({"type": "end_of_trickle_ice"});
}
return peer._pc.localDescription;
})
.catch(e => ok(false, "Sending EOC message failed: " + e));
return Promise.all([eventFired, stateChanged]);
};
@ -396,10 +393,41 @@ function(peer, desc, stateExpected) {
return Promise.all([eventFired, stateChanged]);
};
/**
* Adds and removes steps to/from the execution chain based on the configured
* testOptions.
*/
PeerConnectionTest.prototype.updateChainSteps = function() {
if (this.testOptions.h264) {
this.chain.insertAfterEach(
'PC_LOCAL_CREATE_OFFER',
[PC_LOCAL_REMOVE_VP8_FROM_OFFER]);
}
if (!this.testOptions.bundle) {
this.chain.insertAfterEach(
'PC_LOCAL_CREATE_OFFER',
[PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER]);
}
if (!this.testOptions.rtcpmux) {
this.chain.insertAfterEach(
'PC_LOCAL_CREATE_OFFER',
[PC_LOCAL_REMOVE_RTCPMUX_FROM_OFFER]);
}
if (!this.testOptions.is_local) {
this.chain.filterOut(/^PC_LOCAL/);
}
if (!this.testOptions.is_remote) {
this.chain.filterOut(/^PC_REMOTE/);
}
};
/**
* Start running the tests as assigned to the command chain.
*/
PeerConnectionTest.prototype.run = function() {
/* We have to modify the chain here to allow tests which modify the default
* test chain instantiating a PeerConnectionTest() */
this.updateChainSteps();
return this.chain.execute()
.then(() => this.close())
.then(() => {
@ -651,7 +679,7 @@ DataChannelWrapper.prototype = {
* @param {object} configuration
* Configuration for the peer connection instance
*/
function PeerConnectionWrapper(label, configuration, h264) {
function PeerConnectionWrapper(label, configuration) {
this.configuration = configuration;
if (configuration && configuration.label_suffix) {
label = label + "_" + configuration.label_suffix;
@ -680,8 +708,6 @@ function PeerConnectionWrapper(label, configuration, h264) {
this.iceCheckingRestartExpected = false;
this.h264 = typeof h264 !== "undefined" ? true : false;
info("Creating " + this);
this._pc = new mozRTCPeerConnection(this.configuration);
@ -918,10 +944,6 @@ PeerConnectionWrapper.prototype = {
info("Got offer: " + JSON.stringify(offer));
// note: this might get updated through ICE gathering
this._latest_offer = offer;
if (this.h264) {
isnot(offer.sdp.search("H264/90000"), -1, "H.264 should be present in the SDP offer");
offer.sdp = removeVP8(offer.sdp);
}
return offer;
});
},
@ -1215,18 +1237,16 @@ PeerConnectionWrapper.prototype = {
this.endOfTrickleIce = new Promise(r => resolveEndOfTrickle = r);
this.holdIceCandidates = new Promise(r => this.releaseIceCandidates = r);
this.endOfTrickleIce.then(() => {
this._pc.onicecandidate = () =>
ok(false, this.label + " received ICE candidate after end of trickle");
var localSdp = this._pc.getLocalDescription();
ok(localSdp.includes("a=end-of-candidates"));
ok(localSdp.includes("a=rtcp:"));
ok(!localSdp.includes("c=IN IP4 0.0.0.0"));
});
this._pc.onicecandidate = anEvent => {
if (!anEvent.candidate) {
this._pc.onicecandidate = () =>
ok(false, this.label + " received ICE candidate after end of trickle");
info(this.label + ": received end of trickle ICE event");
/* Bug 1193731. Accroding to WebRTC spec 4.3.1 the ICE Agent first sets
* the gathering state to completed (step 3.) before sending out the
* null newCandidate in step 4. */
todo(this._pc.iceGatheringState === 'completed',
"ICE gathering state has reached completed");
resolveEndOfTrickle(this.label);
return;
}
@ -1241,19 +1261,6 @@ PeerConnectionWrapper.prototype = {
};
},
/**
* Counts the amount of audio tracks in a given media constraint.
*
* @param constraints
* The contraint to be examined.
*/
countTracksInConstraint : function(type, constraints) {
if (!Array.isArray(constraints)) {
return 0;
}
return constraints.reduce((sum, c) => sum + (c[type] ? 1 : 0), 0);
},
checkLocalMediaTracks : function() {
var observed = {};
info(this + " Checking local tracks " + JSON.stringify(this.expectedLocalTrackInfoById));
@ -1302,66 +1309,6 @@ PeerConnectionWrapper.prototype = {
"remote");
},
verifySdp: function(desc, expectedType, offerConstraintsList, offerOptions, isLocal) {
info("Examining this SessionDescription: " + JSON.stringify(desc));
info("offerConstraintsList: " + JSON.stringify(offerConstraintsList));
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.includes("a=ice-ufrag"), "ICE username is present in SDP");
ok(desc.sdp.includes("a=ice-pwd"), "ICE password is present in SDP");
ok(desc.sdp.includes("a=fingerprint"), "ICE fingerprint is present in SDP");
//TODO: update this for loopback support bug 1027350
ok(!desc.sdp.includes(LOOPBACK_ADDR), "loopback interface is absent from SDP");
var requiresTrickleIce = !desc.sdp.includes("a=candidate");
if (requiresTrickleIce) {
info("at least one ICE candidate is present in SDP");
} else {
info("No ICE candidate in SDP -> requiring trickle ICE");
}
if (isLocal) {
this.localRequiresTrickleIce = requiresTrickleIce;
} else {
this.remoteRequiresTrickleIce = requiresTrickleIce;
}
//TODO: how can we check for absence/presence of m=application?
var audioTracks =
this.countTracksInConstraint('audio', offerConstraintsList) ||
((offerOptions && offerOptions.offerToReceiveAudio) ? 1 : 0);
info("expected audio tracks: " + audioTracks);
if (audioTracks == 0) {
ok(!desc.sdp.includes("m=audio"), "audio m-line is absent from SDP");
} else {
ok(desc.sdp.includes("m=audio"), "audio m-line is present in SDP");
ok(desc.sdp.includes("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.includes("a=rtcp-mux"), "RTCP Mux is offered in SDP");
}
var videoTracks =
this.countTracksInConstraint('video', offerConstraintsList) ||
((offerOptions && offerOptions.offerToReceiveVideo) ? 1 : 0);
info("expected video tracks: " + videoTracks);
if (videoTracks == 0) {
ok(!desc.sdp.includes("m=video"), "video m-line is absent from SDP");
} else {
ok(desc.sdp.includes("m=video"), "video m-line is present in SDP");
if (this.h264) {
ok(desc.sdp.includes("a=rtpmap:126 H264/90000"), "H.264 codec is present in SDP");
} else {
ok(desc.sdp.includes("a=rtpmap:120 VP8/90000"), "VP8 codec is present in SDP");
}
ok(desc.sdp.includes("a=rtcp-mux"), "RTCP Mux is offered in SDP");
}
},
/**
* Check that media flow is present on the given media element by waiting for
* it to reach ready state HAVE_ENOUGH_DATA and progress time further than
@ -1691,11 +1638,11 @@ PeerConnectionWrapper.prototype = {
* 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
* @param {object} testOptions
* The test options object from the PeerConnectionTest
*/
checkStatsIceConnections : function(stats,
offerConstraintsList, offerOptions, answer) {
offerConstraintsList, offerOptions, testOptions) {
var numIceConnections = 0;
Object.keys(stats).forEach(key => {
if ((stats[key].type === "candidatepair") && stats[key].selected) {
@ -1704,24 +1651,34 @@ PeerConnectionWrapper.prototype = {
});
info("ICE connections according to stats: " + numIceConnections);
isnot(numIceConnections, 0, "Number of ICE connections according to stats is not zero");
if (answer.sdp.includes('a=group:BUNDLE')) {
is(numIceConnections, 1, "stats reports exactly 1 ICE connection");
if (testOptions.bundle) {
if (testOptions.rtcpmux) {
is(numIceConnections, 1, "stats reports exactly 1 ICE connection");
} else {
is(numIceConnections, 2, "stats report exactly 2 ICE connections for media and RTCP");
}
} else {
// This code assumes that no media sections have been rejected due to
// codec mismatch or other unrecoverable negotiation failures.
var numAudioTracks =
this.countTracksInConstraint('audio', offerConstraintsList) ||
sdputils.countTracksInConstraint('audio', offerConstraintsList) ||
((offerOptions && offerOptions.offerToReceiveAudio) ? 1 : 0);
var numVideoTracks =
this.countTracksInConstraint('video', offerConstraintsList) ||
sdputils.countTracksInConstraint('video', offerConstraintsList) ||
((offerOptions && offerOptions.offerToReceiveVideo) ? 1 : 0);
var numDataTracks = this.dataChannels.length;
var numExpectedTransports = numAudioTracks + numVideoTracks;
if (!testOptions.rtcpmux) {
numExpectedTransports *= 2;
}
var numAudioVideoDataTracks = numAudioTracks + numVideoTracks + numDataTracks;
info("expected audio + video + data tracks: " + numAudioVideoDataTracks);
is(numAudioVideoDataTracks, numIceConnections, "stats ICE connections matches expected A/V tracks");
if (this.dataChannels.length) {
++numExpectedTransports;
}
info("expected audio + video + data transports: " + numExpectedTransports);
is(numIceConnections, numExpectedTransports, "stats ICE connections matches expected A/V transports");
}
},
@ -1789,7 +1746,8 @@ var scriptsReady = Promise.all([
"templates.js",
"turnConfig.js",
"dataChannel.js",
"network.js"
"network.js",
"sdpUtils.js"
].map(script => {
var el = document.createElement("script");
if (typeof scriptRelativePath === 'string' && script.charAt(0) !== '/') {

View File

@ -0,0 +1,111 @@
/* 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/. */
var sdputils = {
checkSdpAfterEndOfTrickle: function(sdp, testOptions, label) {
info("EOC-SDP: " + JSON.stringify(sdp));
ok(sdp.sdp.includes("a=end-of-candidates"), label + ": SDP contains end-of-candidates");
ok(!sdp.sdp.includes("c=IN IP4 0.0.0.0"), label + ": SDP contains non-zero IP c line");
if (testOptions.rtcpmux) {
ok(sdp.sdp.includes("a=rtcp-mux"), label + ": SDP contains rtcp-mux");
} else {
ok(sdp.sdp.includes("a=rtcp:"), label + ": SDP contains rtcp port");
}
},
// Also remove mode 0 if it's offered
// Note, we don't bother removing the fmtp lines, which makes a good test
// for some SDP parsing issues.
removeVP8: function(sdp) {
var updated_sdp = sdp.replace("a=rtpmap:120 VP8/90000\r\n","");
updated_sdp = updated_sdp.replace("RTP/SAVPF 120 126 97\r\n","RTP/SAVPF 126 97\r\n");
updated_sdp = updated_sdp.replace("RTP/SAVPF 120 126\r\n","RTP/SAVPF 126\r\n");
updated_sdp = updated_sdp.replace("a=rtcp-fb:120 nack\r\n","");
updated_sdp = updated_sdp.replace("a=rtcp-fb:120 nack pli\r\n","");
updated_sdp = updated_sdp.replace("a=rtcp-fb:120 ccm fir\r\n","");
return updated_sdp;
},
removeRtcpMux: function(sdp) {
return sdp.replace(/a=rtcp-mux\r\n/g,"");
},
removeBundle: function(sdp) {
return sdp.replace(/a=group:BUNDLE .*\r\n/g, "");
},
verifySdp: function(desc, expectedType, offerConstraintsList, offerOptions,
testOptions) {
info("Examining this SessionDescription: " + JSON.stringify(desc));
info("offerConstraintsList: " + JSON.stringify(offerConstraintsList));
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.includes("a=ice-ufrag"), "ICE username is present in SDP");
ok(desc.sdp.includes("a=ice-pwd"), "ICE password is present in SDP");
ok(desc.sdp.includes("a=fingerprint"), "ICE fingerprint is present in SDP");
//TODO: update this for loopback support bug 1027350
ok(!desc.sdp.includes(LOOPBACK_ADDR), "loopback interface is absent from SDP");
var requiresTrickleIce = !desc.sdp.includes("a=candidate");
if (requiresTrickleIce) {
info("at least one ICE candidate is present in SDP");
} else {
info("No ICE candidate in SDP -> requiring trickle ICE");
}
//TODO: how can we check for absence/presence of m=application?
var audioTracks =
sdputils.countTracksInConstraint('audio', offerConstraintsList) ||
((offerOptions && offerOptions.offerToReceiveAudio) ? 1 : 0);
info("expected audio tracks: " + audioTracks);
if (audioTracks == 0) {
ok(!desc.sdp.includes("m=audio"), "audio m-line is absent from SDP");
} else {
ok(desc.sdp.includes("m=audio"), "audio m-line is present in SDP");
ok(desc.sdp.includes("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)
is(testOptions.rtcpmux, desc.sdp.includes("a=rtcp-mux"), "RTCP Mux is offered in SDP");
}
var videoTracks =
sdputils.countTracksInConstraint('video', offerConstraintsList) ||
((offerOptions && offerOptions.offerToReceiveVideo) ? 1 : 0);
info("expected video tracks: " + videoTracks);
if (videoTracks == 0) {
ok(!desc.sdp.includes("m=video"), "video m-line is absent from SDP");
} else {
ok(desc.sdp.includes("m=video"), "video m-line is present in SDP");
if (testOptions.h264) {
ok(desc.sdp.includes("a=rtpmap:126 H264/90000"), "H.264 codec is present in SDP");
} else {
ok(desc.sdp.includes("a=rtpmap:120 VP8/90000"), "VP8 codec is present in SDP");
}
is(testOptions.rtcpmux, desc.sdp.includes("a=rtcp-mux"), "RTCP Mux is offered in SDP");
}
return requiresTrickleIce;
},
/**
* Counts the amount of audio tracks in a given media constraint.
*
* @param constraints
* The contraint to be examined.
*/
countTracksInConstraint: function(type, constraints) {
if (!Array.isArray(constraints)) {
return 0;
}
return constraints.reduce((sum, c) => sum + (c[type] ? 1 : 0), 0);
},
};

View File

@ -208,20 +208,10 @@ var commandsGetUserMedia = [
var commandsPeerConnectionOfferAnswer = [
function PC_LOCAL_SETUP_ICE_HANDLER(test) {
test.pcLocal.setupIceCandidateHandler(test);
if (test.steeplechase) {
test.pcLocal.endOfTrickleIce.then(() => {
send_message({"type": "end_of_trickle_ice"});
});
}
},
function PC_REMOTE_SETUP_ICE_HANDLER(test) {
test.pcRemote.setupIceCandidateHandler(test);
if (test.steeplechase) {
test.pcRemote.endOfTrickleIce.then(() => {
send_message({"type": "end_of_trickle_ice"});
});
}
},
function PC_LOCAL_STEEPLECHASE_SIGNAL_EXPECTED_LOCAL_TRACKS(test) {
@ -316,15 +306,17 @@ var commandsPeerConnectionOfferAnswer = [
},
function PC_LOCAL_SANE_LOCAL_SDP(test) {
test.pcLocal.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._offer_options,
true);
test.pcLocal.localRequiresTrickleIce =
sdputils.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._offer_options,
test.testOptions);
},
function PC_REMOTE_SANE_REMOTE_SDP(test) {
test.pcRemote.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._offer_options,
false);
test.pcRemote.remoteRequiresTrickleIce =
sdputils.verifySdp(test._local_offer, "offer",
test._offer_constraints, test._offer_options,
test.testOptions);
},
function PC_REMOTE_CREATE_ANSWER(test) {
@ -342,46 +334,6 @@ var commandsPeerConnectionOfferAnswer = [
});
},
function PC_REMOTE_CHECK_FOR_DUPLICATED_PORTS_IN_SDP(test) {
var re = /a=candidate.* (UDP|TCP) [\d]+ ([\d\.]+) ([\d]+) typ host/g;
var _sdpCandidatesIntoArray = sdp => {
var regexArray = [];
var resultArray = [];
while ((regexArray = re.exec(sdp)) !== null) {
info("regexArray: " + regexArray);
if ((regexArray[1] === "TCP") && (regexArray[3] === "9")) {
// As both sides can advertise TCP active connection on port 9 lets
// ignore them all together
info("Ignoring TCP candidate on port 9");
continue;
}
var triple = regexArray[1] + ":" + regexArray[2] + ":" + regexArray[3];
info("triple: " + triple);
if (resultArray.indexOf(triple) !== -1) {
dump("SDP: " + sdp.replace(/[\r]/g, '') + "\n");
ok(false, "This Transport:IP:Port " + triple + " appears twice in the SDP above!");
}
resultArray.push(triple);
}
return resultArray;
};
var offerTriples = _sdpCandidatesIntoArray(test._local_offer.sdp);
info("Offer ICE host candidates: " + JSON.stringify(offerTriples));
var answerTriples = _sdpCandidatesIntoArray(test.originalAnswer.sdp);
info("Answer ICE host candidates: " + JSON.stringify(answerTriples));
offerTriples.forEach(o => {
if (answerTriples.indexOf(o) !== -1) {
dump("SDP offer: " + test._local_offer.sdp.replace(/[\r]/g, '') + "\n");
dump("SDP answer: " + test.originalAnswer.sdp.replace(/[\r]/g, '') + "\n");
ok(false, "This IP:Port " + o + " appears in SDP offer and answer!");
}
});
},
function PC_REMOTE_SET_LOCAL_DESCRIPTION(test) {
return test.setLocalDescription(test.pcRemote, test.originalAnswer, STABLE)
.then(() => {
@ -412,14 +364,16 @@ var commandsPeerConnectionOfferAnswer = [
});
},
function PC_REMOTE_SANE_LOCAL_SDP(test) {
test.pcRemote.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._offer_options,
true);
test.pcRemote.localRequiresTrickleIce =
sdputils.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._offer_options,
test.testOptions);
},
function PC_LOCAL_SANE_REMOTE_SDP(test) {
test.pcLocal.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._offer_options,
false);
test.pcLocal.remoteRequiresTrickleIce =
sdputils.verifySdp(test._remote_answer, "answer",
test._offer_constraints, test._offer_options,
test.testOptions);
},
function PC_LOCAL_WAIT_FOR_ICE_CONNECTED(test) {
@ -483,7 +437,7 @@ var commandsPeerConnectionOfferAnswer = [
test.pcLocal.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
test._remote_answer);
test.testOptions);
});
},
@ -492,7 +446,7 @@ var commandsPeerConnectionOfferAnswer = [
test.pcRemote.checkStatsIceConnections(stats,
test._offer_constraints,
test._offer_options,
test.originalAnswer);
test.testOptions);
});
},
@ -509,22 +463,46 @@ var commandsPeerConnectionOfferAnswer = [
function PC_REMOTE_CHECK_STATS(test) {
return checkAllTrackStats(test.pcRemote);
},
function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
return test.pcLocal.endOfTrickleIce;
function PC_LOCAL_VERIFY_SDP_AFTER_END_OF_TRICKLE(test) {
/* In case the endOfTrickleSdp promise is resolved already it will win the
* race because it gets evaluated first. But if endOfTrickleSdp is still
* pending the rejection will win the race. */
return Promise.race([
test.pcLocal.endOfTrickleSdp,
Promise.reject("No SDP")
])
.then(sdp => sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcLocal.label),
() => info("pcLocal: Gathering is not complete yet, skipping post-gathering SDP check"));
},
function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) {
return test.pcRemote.endOfTrickleIce;
function PC_REMOTE_VERIFY_SDP_AFTER_END_OF_TRICKLE(test) {
/* In case the endOfTrickleSdp promise is resolved already it will win the
* race because it gets evaluated first. But if endOfTrickleSdp is still
* pending the rejection will win the race. */
return Promise.race([
test.pcRemote.endOfTrickleSdp,
Promise.reject("No SDP")
])
.then(sdp => sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcRemote.label),
() => info("pcRemote: Gathering is not complete yet, skipping post-gathering SDP check"));
}
];
function PC_LOCAL_REMOVE_VP8_FROM_OFFER(test) {
isnot(test.originalOffer.sdp.search("H264/90000"), -1, "H.264 should be present in the SDP offer");
test.originalOffer.sdp = sdputils.removeVP8(test.originalOffer.sdp);
info("Updated H264 only offer: " + JSON.stringify(test.originalOffer));
};
function PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER(test) {
test.originalOffer.sdp = test.originalOffer.sdp.replace(
/a=group:BUNDLE .*\r\n/g,
""
);
test.originalOffer.sdp = sdputils.removeBundle(test.originalOffer.sdp);
info("Updated no bundle offer: " + JSON.stringify(test.originalOffer));
};
function PC_LOCAL_REMOVE_RTCPMUX_FROM_OFFER(test) {
test.originalOffer.sdp = sdputils.removeRtcpMux(test.originalOffer.sdp);
info("Updated no RTCP-Mux offer: " + JSON.stringify(test.originalOffer));
};
var addRenegotiation = (chain, commands, checks) => {
chain.append(commands);
chain.append(commandsPeerConnectionOfferAnswer);

View File

@ -12,17 +12,11 @@
});
var test;
runNetworkTest(function () {
test = new PeerConnectionTest();
runNetworkTest(function (options) {
options = options || { };
options.bundle = false;
test = new PeerConnectionTest(options);
addInitialDataChannel(test.chain);
test.chain.insertAfter("PC_LOCAL_CREATE_OFFER", [
function PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER(test) {
// Just replace a=group:BUNDLE with something that will be ignored.
test.originalOffer.sdp = test.originalOffer.sdp.replace(
"a=group:BUNDLE",
"a=foo:");
}
]);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.run();

View File

@ -13,6 +13,8 @@
var test;
runNetworkTest(function (options) {
options = options || { };
options.bundle = false;
test = new PeerConnectionTest(options);
addRenegotiation(test.chain,
commandsCreateDataChannel.concat(
@ -27,9 +29,6 @@
),
commandsCheckDataChannel);
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
// Insert before the second PC_LOCAL_CHECK_MEDIA_TRACKS
test.chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS',
commandsWaitForDataChannel,

View File

@ -13,6 +13,8 @@
var test;
runNetworkTest(function (options) {
options = options || { };
options.bundle = false;
test = new PeerConnectionTest(options);
addRenegotiation(test.chain,
[
@ -30,9 +32,6 @@
]
);
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();

View File

@ -13,6 +13,8 @@
var test;
runNetworkTest(function (options) {
options = options || { };
options.bundle = false;
test = new PeerConnectionTest(options);
addRenegotiation(test.chain,
[
@ -30,9 +32,6 @@
]
);
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
test.setMediaConstraints([{video: true}], [{video: true}]);
test.run();

View File

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1167443",
title: "Basic audio-only peer connection which waits for end-of-candidates"
});
var test;
runNetworkTest(function (options) {
test = new PeerConnectionTest(options);
test.chain.replace("PC_LOCAL_VERIFY_SDP_AFTER_END_OF_TRICKLE", [
function PC_LOCAL_REQUIRE_SDP_AFTER_END_OF_TRICKLE(test) {
return test.pcLocal.endOfTrickleSdp.then(sdp =>
sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcLocal.label));
}
]);
test.chain.replace("PC_REMOTE_VERIFY_SDP_AFTER_END_OF_TRICKLE", [
function PC_REMOTE_REQUIRE_SDP_AFTER_END_OF_TRICKLE(test) {
return test.pcRemote.endOfTrickleSdp.then(sdp =>
sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcRemote.label));
}
]);
test.setMediaConstraints([{audio: true}], [{audio: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -12,10 +12,9 @@
});
runNetworkTest(options => {
options = options || { };
options.bundle = false;
var test = new PeerConnectionTest(options);
test.chain.insertAfter(
'PC_LOCAL_CREATE_OFFER',
[PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER]);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.run();

View File

@ -0,0 +1,39 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1167443",
title: "Basic audio & video call with disabled bundle and disbaled RTCP-Mux"
});
var test;
runNetworkTest(function (options) {
options = options || { };
options.bundle = false;
options.rtcpmux = false;
test = new PeerConnectionTest(options);
test.chain.replace("PC_LOCAL_VERIFY_SDP_AFTER_END_OF_TRICKLE", [
function PC_LOCAL_REQUIRE_SDP_AFTER_END_OF_TRICKLE(test) {
return test.pcLocal.endOfTrickleSdp .then(sdp =>
sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcLocal.label));
}
]);
test.chain.replace("PC_REMOTE_VERIFY_SDP_AFTER_END_OF_TRICKLE", [
function PC_REMOTE_REQUIRE_SDP_AFTER_END_OF_TRICKLE(test) {
return test.pcRemote.endOfTrickleSdp .then(sdp =>
sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcRemote.label));
}
]);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.run();
});
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1167443",
title: "Basic audio & video call with disabled RTCP-Mux"
});
var test;
runNetworkTest(function (options) {
options = options || { };
options.rtcpmux = false;
test = new PeerConnectionTest(options);
test.chain.replace("PC_LOCAL_VERIFY_SDP_AFTER_END_OF_TRICKLE", [
function PC_LOCAL_REQUIRE_SDP_AFTER_END_OF_TRICKLE(test) {
return test.pcLocal.endOfTrickleSdp .then(sdp =>
sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcLocal.label));
}
]);
test.chain.replace("PC_REMOTE_VERIFY_SDP_AFTER_END_OF_TRICKLE", [
function PC_REMOTE_REQUIRE_SDP_AFTER_END_OF_TRICKLE(test) {
return test.pcRemote.endOfTrickleSdp .then(sdp =>
sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcRemote.label));
}
]);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.run();
});
</script>
</pre>
</body>
</html>