1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';
// In this test, the promises should resolve in the execution order
// (setLocalDescription, setLocalDescription, addIceCandidate) as is ensured by
// the Operations Chain; if an operation is pending, executing another operation
// will queue it. This test will fail if an Operations Chain is not implemented,
// but it gives the implementation some slack: it only ensures that
// addIceCandidate() is not resolved first, allowing timing issues in resolving
// promises where the test still passes even if addIceCandidate() is resolved
// *before* the second setLocalDescription().
//
// This test covers Chrome issue (https://crbug.com/1019222), but does not
// require setLocalDescription-promises to resolve immediately which is another
// Chrome bug (https://crbug.com/1019232). The true order is covered by the next
// test.
// TODO(https://crbug.com/1019232): Delete this test when the next test passes
// in Chrome.
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
caller.addTransceiver('audio');
const candidatePromise = new Promise(resolve => {
caller.onicecandidate = e => resolve(e.candidate);
});
await caller.setLocalDescription(await caller.createOffer());
await callee.setRemoteDescription(caller.localDescription);
const candidate = await candidatePromise;
// Chain setLocalDescription(), setLocalDescription() and addIceCandidate()
// without performing await between the calls.
const pendingPromises = [];
const resolveOrder = [];
pendingPromises.push(callee.setLocalDescription().then(() => {
resolveOrder.push('setLocalDescription 1');
}));
pendingPromises.push(callee.setLocalDescription().then(() => {
resolveOrder.push('setLocalDescription 2');
}));
pendingPromises.push(callee.addIceCandidate(candidate).then(() => {
resolveOrder.push('addIceCandidate');
}));
await Promise.all(pendingPromises);
assert_equals(resolveOrder[0], 'setLocalDescription 1');
}, 'addIceCandidate is not resolved first if 2x setLocalDescription ' +
'operations are pending');
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
caller.addTransceiver('audio');
const candidatePromise = new Promise(resolve => {
caller.onicecandidate = e => resolve(e.candidate);
});
await caller.setLocalDescription(await caller.createOffer());
await callee.setRemoteDescription(caller.localDescription);
const candidate = await candidatePromise;
// Chain setLocalDescription(), setLocalDescription() and addIceCandidate()
// without performing await between the calls.
const pendingPromises = [];
const resolveOrder = [];
pendingPromises.push(callee.setLocalDescription().then(() => {
resolveOrder.push('setLocalDescription 1');
}));
pendingPromises.push(callee.setLocalDescription().then(() => {
resolveOrder.push('setLocalDescription 2');
}));
pendingPromises.push(callee.addIceCandidate(candidate).then(() => {
resolveOrder.push('addIceCandidate');
}));
await Promise.all(pendingPromises);
// This test verifies that both issues described in https://crbug.com/1019222
// and https://crbug.com/1019232 are fixed. If this test passes in Chrome, the
// ICE candidate exchange issues described in
// https://github.com/web-platform-tests/wpt/issues/19866 should be resolved.
assert_array_equals(
resolveOrder,
['setLocalDescription 1', 'setLocalDescription 2', 'addIceCandidate']);
}, 'addIceCandidate and setLocalDescription are resolved in the correct ' +
'order, as defined by the operations chain specification');
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
caller.addTransceiver('audio');
let events = [];
let pendingPromises = [];
const onCandidatePromise = new Promise(resolve => {
caller.onicecandidate = () => {
events.push('candidate generated');
resolve();
}
});
pendingPromises.push(onCandidatePromise);
pendingPromises.push(caller.setLocalDescription().then(() => {
events.push('setLocalDescription');
}));
await Promise.all(pendingPromises);
assert_array_equals(events, ['setLocalDescription', 'candidate generated']);
}, 'onicecandidate fires after resolving setLocalDescription in offerer');
promise_test(async t => {
const caller = new RTCPeerConnection();
t.add_cleanup(() => caller.close());
const callee = new RTCPeerConnection();
t.add_cleanup(() => callee.close());
caller.addTransceiver('audio');
let events = [];
let pendingPromises = [];
caller.onicecandidate = (ev) => {
if (ev.candidate) {
callee.addIceCandidate(ev.candidate);
}
}
const offer = await caller.createOffer();
const onCandidatePromise = new Promise(resolve => {
callee.onicecandidate = () => {
events.push('candidate generated');
resolve();
}
});
await callee.setRemoteDescription(offer);
const answer = await callee.createAnswer();
pendingPromises.push(onCandidatePromise);
pendingPromises.push(callee.setLocalDescription(answer).then(() => {
events.push('setLocalDescription');
}));
await Promise.all(pendingPromises);
assert_array_equals(events, ['setLocalDescription', 'candidate generated']);
}, 'onicecandidate fires after resolving setLocalDescription in answerer');
</script>
|