Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite RTC ICE and DTLS transport tests with alternative dependencies (Rebased) #13886

Closed
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update code to work with async/await and newer browsers
  • Loading branch information
soareschen committed Dec 10, 2018
commit 2f0009209b13228105df585c3ae91ba554211a9b
68 changes: 32 additions & 36 deletions webrtc/RTCDtlsTransport-getRemoteCertificates.html
Original file line number Diff line number Diff line change
@@ -36,50 +36,46 @@
}
}

promise_test(t => {
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());

const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());

const [dtlsTransports1, dtlsTransports2] = await createDtlsTransportsFromSenderReceiver(pc1, pc2)
const dtlsTransports = [...dtlsTransports1, ... dtlsTransports2];

for (const dtlsTransport of dtlsTransports) {
validateConnectingDtlsTransport(dtlsTransport);
}

await waitConnectingPc(pc1);
await waitConnectingPc(pc2);

return createDtlsTransportsFromSenderReceiver(pc1, pc2)
.then(([dtlsTransports1, dtlsTransports2]) => {
const dtlsTransports = [...dtlsTransports1, ... dtlsTransports2];

for (const dtlsTransport of dtlsTransports) {
validateConnectingDtlsTransport(dtlsTransport);
}

return Promise.all([
waitConnectingPc(pc1),
waitConnectingPc(pc2)
])
.then(() => {
for (const dtlsTransport of dtlsTransports) {
validateConnectedDtlsTransport(dtlsTransport);
}
});
});
for (const dtlsTransport of dtlsTransports) {
validateConnectedDtlsTransport(dtlsTransport);
}
}, 'RTP - connected DTLS transports should have valid remote certificates');

promise_test(t => {
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());

const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());

const dtlsTransports = await createDtlsTransportsFromSctp(pc1, pc2)
for (const dtlsTransport of dtlsTransports) {
validateConnectingDtlsTransport(dtlsTransport);
}

return createDtlsTransportsFromSctp(pc1, pc2)
.then(dtlsTransports => {
for (const dtlsTransport of dtlsTransports) {
validateConnectingDtlsTransport(dtlsTransport);
}

return Promise.all([
waitConnectingPc(pc1),
waitConnectingPc(pc2)
])
.then(() => {
for (const dtlsTransport of dtlsTransports) {
validateConnectedDtlsTransport(dtlsTransport);
}
});
});
await waitConnectingPc(pc1);
await waitConnectingPc(pc2);

for (const dtlsTransport of dtlsTransports) {
validateConnectedDtlsTransport(dtlsTransport);
}
}, 'SCTP - connected DTLS transports should have valid remote certificates');

</script>
100 changes: 47 additions & 53 deletions webrtc/RTCIceTransport.html
Original file line number Diff line number Diff line change
@@ -81,85 +81,79 @@
'Expect selectedCandidatePair to be null');
}

promise_test(t => {
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());

const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());

return createIceTransportsFromSctp(pc1, pc2)
.then(([iceTransport1, iceTransport2]) => {
return Promise.all([
waitConnectingPc(pc1),
waitConnectingPc(pc2)
])
.then(() => {
validateConnectedIceTransport(iceTransport1);
validateConnectedIceTransport(iceTransport2);
});
});
const [iceTransport1, iceTransport2] = await createIceTransportsFromSctp(pc1, pc2);

await waitConnectingPc(pc1);
await waitConnectingPc(pc2);

validateConnectedIceTransport(iceTransport1);
validateConnectedIceTransport(iceTransport2);
}, 'SCTP - Connected ICE transports should have relevants attributes set');

promise_test(t => {
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());

const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());

const [iceTransports1, iceTransports2] = await createIceTransportsFromSenderReceiver(pc1, pc2)
const iceTransports = [...iceTransports1, ...iceTransports2];

return createIceTransportsFromSenderReceiver(pc1, pc2)
.then(([iceTransports1, iceTransports2]) => {
const iceTransports = [...iceTransports1, ...iceTransports2];
return Promise.all([
waitConnectingPc(pc1),
waitConnectingPc(pc2)
])
.then(() => {
for (const iceTransport of iceTransports) {
validateConnectedIceTransport(iceTransport);
}
});
});
await waitConnectingPc(pc1);
await waitConnectingPc(pc2);

for (const iceTransport of iceTransports) {
validateConnectedIceTransport(iceTransport);
}
}, 'RTP - Connected ICE transports should have relevants attributes set');

promise_test(t => {
promise_test(async t => {
const pc = new RTCPeerConnection();
t.add_cleanup(() => pc.close());

return getTrackFromUserMedia('audio')
.then(([track, mediaStream]) => {
addTrackOrTransceiver(pc, track, mediaStream);

// setLocalDescription should initialize sender/receiver.transport
return pc.createOffer()
.then(offer => pc.setLocalDescription(offer))
.then(() => {
const iceTransports = getIceTransportsFromSenderReceiver(pc);

for (const iceTransport of iceTransports) {
validateUnconnectedIceTransport(iceTransport);
}
});
});
const [track, mediaStream] = await getTrackFromUserMedia('audio')
addTrackOrTransceiver(pc, track, mediaStream);

// setLocalDescription should initialize sender/receiver.transport
const offer = await pc.createOffer()
await pc.setLocalDescription(offer)

const iceTransports = getIceTransportsFromSenderReceiver(pc);

for (const iceTransport of iceTransports) {
validateUnconnectedIceTransport(iceTransport);
}
}, 'RTP - Unconnected iceTransport should have empty remote candidates and selected pair');

promise_test(t => {
promise_test(async t => {
const pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());

const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc2.close());

pc1.createDataChannel('');

// pc1.setRemoteDescription(answer) without pc2 setting answer to it's
// localDescription. This is because pc1.sctp is only set after setting
// answer description.
return pc1.createOffer()
.then(offer =>
pc1.setLocalDescription(offer)
.then(() => pc2.setRemoteDescription(offer))
.then(() => pc2.createAnswer()))
.then(answer => pc1.setRemoteDescription(answer))
.then(() => {
const iceTransport = getIceTransportFromSctpTransport(pc1.sctp);
const offer = await pc1.createOffer()

validateUnconnectedIceTransport(iceTransport);
});
await pc1.setLocalDescription(offer)
await pc2.setRemoteDescription(offer)
const answer = await pc2.createAnswer()
await pc1.setRemoteDescription(answer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip: could be inlined, for fewer names polluting the cognitive stack space:

await pc1.setRemoteDescription(await pc2.createAnswer());

Also, missing ; semicolons at EOLs here.


const iceTransport = getIceTransportFromSctpTransport(pc1.sctp);
validateUnconnectedIceTransport(iceTransport);
}, 'SCTP - Unconnected iceTransport should have empty remote candidates and selected pair');

</script>
20 changes: 18 additions & 2 deletions webrtc/RTCPeerConnection-helper.js
Original file line number Diff line number Diff line change
@@ -476,14 +476,29 @@ async function exchangeOfferAndListenToOntrack(t, caller, callee) {
const ontrackPromise = addEventListenerPromise(t, callee, 'track');
await exchangeOffer(caller, callee);
return ontrackPromise;
}

// Feature detect whether we can call add transceiver on the target browser.
// We cannot simply test if the addTransceiver method exist, as Chrome
// for example would have it implemented but only usable in unified plan,
// which means it would fail the tests when using default peer connection config
function canAddTransceiver() {
const pc = new RTCPeerConnection();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please close this PeerConnection in cleanup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not feature detect in tests IMHO, as it ends up testing different things on different browsers.

addTransceiver is in the spec; Chrome should be running these tests with unified-plan enabled already.

try {
pc.addTransceiver('audio');
return true;
} catch (err) {
return false;
}
}

// A dependency agnostic way of adding track depending
// on the supported method on a browser. Uses addTransceiver(track)
// first if available, otherwise use addTrack(track, mediaStream)
// or falls back to the legacy addStream method (which has been removed
// from the spec).
function addTrackOrTransceiver(pc, track, mediaStream) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this one?
It makes sense to support older tests for older browsers but for new tests/new constructs, we can probably hope to have transceivers available. Maybe we do want to test these new constructs with plan B as well, I guess this is fine.

Maybe we should rename it to addTransceiverOrTrack since we first try to add a transceiver and fall back to tracks otherwise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @youennf this helper is unneeded, unwanted even, because it ends up testing different things on different browsers. I vote we call addTransceiver or addTrack directly, whichever we intend to test with.

if (typeof pc.addTransceiver === 'function') {
if (canAddTransceiver()) {
return pc.addTransceiver(track);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably pass the mediaStream to addTransceiver so as to be consistent with addTrack

} else if (typeof pc.addTrack === 'function') {
// Note: The mediaStream argument is optional in the spec, but we require
@@ -542,8 +557,9 @@ async function createTrackAndStreamWithCleanup(t, kind = 'audio') {
function findTransceiverForSender(pc, sender) {
const transceivers = pc.getTransceivers();
for (let i = 0; i < transceivers.length; ++i) {
if (transceivers[i].sender == sender)
if (transceivers[i].sender == sender) {
return transceivers[i];
}
}
return null;
}
74 changes: 34 additions & 40 deletions webrtc/RTCTransport-helper.js
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ function getDtlsTransportsFromSenderReceiver(pc) {

const dtlsTransportsSet = new Set();

function adddDtlsTransport(transport) {
function addDtlsTransport(transport) {
// Add a dtls transport to the result set, if it is
// not null/undefined. Although the spec mandates both
// transport and rtcpTransport fields must be set together,
@@ -79,13 +79,13 @@ function getDtlsTransportsFromSenderReceiver(pc) {
}

for (const sender of senders) {
adddDtlsTransport(sender.transport);
adddDtlsTransport(sender.rtcpTransport);
addDtlsTransport(sender.transport);
addDtlsTransport(sender.rtcpTransport);
}

for (const receiver of receivers) {
adddDtlsTransport(receiver.transport);
adddDtlsTransport(receiver.rtcpTransport);
addDtlsTransport(receiver.transport);
addDtlsTransport(receiver.rtcpTransport);
}

const dtlsTransports = [...dtlsTransportsSet];
@@ -129,56 +129,50 @@ function getIceTransportsFromSenderReceiver(pc) {
// and connecting two peer connections. Returns an
// array of two RTCDtlsTransports, which obtained
// from RTCSctpTransport in pc.sctp.
function createDtlsTransportsFromSctp(pc1, pc2) {
async function createDtlsTransportsFromSctp(pc1, pc2) {
pc1.createDataChannel('');
exchangeIceCandidates(pc1, pc2);

return doSignalingHandshake(pc1, pc2)
.then(() => {
const dtlsTransport1 = getDtlsTransportFromSctpTransport(pc1.sctp);
const dtlsTransport2 = getDtlsTransportFromSctpTransport(pc2.sctp);
await doSignalingHandshake(pc1, pc2);

return [dtlsTransport1, dtlsTransport2];
});
const dtlsTransport1 = getDtlsTransportFromSctpTransport(pc1.sctp);
const dtlsTransport2 = getDtlsTransportFromSctpTransport(pc2.sctp);

return [dtlsTransport1, dtlsTransport2];
}

// Create DTLS transports by adding tracks and connecting
// two peer connections. Returns an array of two array of
// RTCDtlsTransports. This is because each peer connection
// may have multiple underlying DTLS transports for each
// RTP/RTCP sender/receivers.
function createDtlsTransportsFromSenderReceiver(pc1, pc2) {
return getTrackFromUserMedia('audio')
.then(([track, mediaStream]) => {
addTrackOrTransceiver(pc1, track, mediaStream);
exchangeIceCandidates(pc1, pc2);

return doSignalingHandshake(pc1, pc2)
.then(() => {
const dtlsTransports1 = getDtlsTransportsFromSenderReceiver(pc1);
const dtlsTransports2 = getDtlsTransportsFromSenderReceiver(pc2);

return [dtlsTransports1, dtlsTransports2];
});
});
async function createDtlsTransportsFromSenderReceiver(pc1, pc2) {
const [track, mediaStream] = await getTrackFromUserMedia('audio')
addTrackOrTransceiver(pc1, track, mediaStream);
exchangeIceCandidates(pc1, pc2);

await doSignalingHandshake(pc1, pc2);

const dtlsTransports1 = getDtlsTransportsFromSenderReceiver(pc1);
const dtlsTransports2 = getDtlsTransportsFromSenderReceiver(pc2);

return [dtlsTransports1, dtlsTransports2];
}

function createIceTransportsFromSctp(pc1, pc2) {
return createDtlsTransportsFromSctp(pc1, pc2)
.then(([dtlsTransport1, dtlsTransport2]) => {
const iceTransport1 = getIceTransportFromDtlsTransport(dtlsTransport1);
const iceTransport2 = getIceTransportFromDtlsTransport(dtlsTransport2);
async function createIceTransportsFromSctp(pc1, pc2) {
const [dtlsTransport1, dtlsTransport2] = await createDtlsTransportsFromSctp(pc1, pc2)

return [iceTransport1, iceTransport2];
});
const iceTransport1 = getIceTransportFromDtlsTransport(dtlsTransport1);
const iceTransport2 = getIceTransportFromDtlsTransport(dtlsTransport2);

return [iceTransport1, iceTransport2];
}

function createIceTransportsFromSenderReceiver(pc1, pc2) {
return createDtlsTransportsFromSenderReceiver(pc1, pc2)
.then(([dtlsTransports1, dtlsTransports2]) => {
const iceTransports1 = getIceTransportsFromDtlsTransports(dtlsTransports1);
const iceTransports2 = getIceTransportsFromDtlsTransports(dtlsTransports2);
async function createIceTransportsFromSenderReceiver(pc1, pc2) {
const [dtlsTransports1, dtlsTransports2] = await createDtlsTransportsFromSenderReceiver(pc1, pc2)

return [iceTransports1, iceTransports2];
});
const iceTransports1 = getIceTransportsFromDtlsTransports(dtlsTransports1);
const iceTransports2 = getIceTransportsFromDtlsTransports(dtlsTransports2);

return [iceTransports1, iceTransports2];
}