Commit ebf57a00 authored by Henrik Boström's avatar Henrik Boström Committed by Commit Bot

[Perfect Negotiation] Split Perfect Negotiation WPTs into smaller files.

As of implementing Perfect Negotiation these WPTs have been timing out
on some bots. Running locally, the tests are very slow to run (because
some of them are stress tests) and anecdotally it takes 20-30 seconds;
but I've never been able to repro a real failure locally. I can't tell
if the Timeouts on the bots are due to real bugs or due to the tests
simply being too slow to run on bot infra.

This CL splits the tests up into separate files, giving each test more
time to run. This CL also makes the stress tests run for less
iterations. With these changes, it is reasonable to assume that the
bots will be able to run them unless we have a real bug.

Let's re-enable the tests with these changes and keep an eye on the
bots...

TBR=hta@chromium.org

Bug: chromium:1123832
Change-Id: Ief43b998479caf91f9216718d6b7259e01256202
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2386796Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803431}
parent ec83f499
...@@ -6646,6 +6646,3 @@ crbug.com/1122106 external/wpt/webrtc/protocol/crypto-suite.https.html [ Pass Ti ...@@ -6646,6 +6646,3 @@ crbug.com/1122106 external/wpt/webrtc/protocol/crypto-suite.https.html [ Pass Ti
crbug.com/1122742 http/tests/devtools/sources/debugger/source-frame-inline-breakpoint-decorations.js [ Pass Timeout ] crbug.com/1122742 http/tests/devtools/sources/debugger/source-frame-inline-breakpoint-decorations.js [ Pass Timeout ]
crbug.com/1122582 external/wpt/html/cross-origin-opener-policy/coop-csp-sandbox-navigate.https.html [ Pass Failure ] crbug.com/1122582 external/wpt/html/cross-origin-opener-policy/coop-csp-sandbox-navigate.https.html [ Pass Failure ]
# Sheriff 2020-09-01
crbug.com/1123558 external/wpt/webrtc/RTCPeerConnection-perfect-negotiation.https.html [ Pass Timeout ]
'use strict'
function peer(other, polite, fail = null) {
const send = (tgt, msg) => tgt.postMessage(JSON.parse(JSON.stringify(msg)),
"*");
if (!fail) fail = e => send(window.parent, {error: `${e.name}: ${e.message}`});
const pc = new RTCPeerConnection();
if (!window.assert_equals) {
window.assert_equals = (a, b, msg) => a === b ||
fail(new Error(`${msg} expected ${b} but got ${a}`));
}
const commands = {
async addTransceiver() {
const transceiver = pc.addTransceiver("video");
await new Promise(r => pc.addEventListener("negotiated", r, {once: true}));
if (!transceiver.currentDirection) {
// Might have just missed the negotiation train. Catch next one.
await new Promise(r => pc.addEventListener("negotiated", r, {once: true}));
}
assert_equals(transceiver.currentDirection, "sendonly", "have direction");
return pc.getTransceivers().length;
},
async simpleConnect() {
const p = commands.addTransceiver();
await new Promise(r => pc.oniceconnectionstatechange =
() => pc.iceConnectionState == "connected" && r());
return await p;
},
async getNumTransceivers() {
return pc.getTransceivers().length;
},
};
try {
pc.addEventListener("icecandidate", ({candidate}) => send(other,
{candidate}));
let makingOffer = false, ignoreOffer = false;
let srdAnswerPending = false;
pc.addEventListener("negotiationneeded", async () => {
try {
assert_equals(pc.signalingState, "stable", "negotiationneeded always fires in stable state");
assert_equals(makingOffer, false, "negotiationneeded not already in progress");
makingOffer = true;
await pc.setLocalDescription();
assert_equals(pc.signalingState, "have-local-offer", "negotiationneeded not racing with onmessage");
assert_equals(pc.localDescription.type, "offer", "negotiationneeded SLD worked");
send(other, {description: pc.localDescription});
} catch (e) {
fail(e);
} finally {
makingOffer = false;
}
});
window.onmessage = async ({data: {description, candidate, run}}) => {
try {
if (description) {
// If we have a setRemoteDescription() answer operation pending, then
// we will be "stable" by the time the next setRemoteDescription() is
// executed, so we count this being stable when deciding whether to
// ignore the offer.
let isStable =
pc.signalingState == "stable" ||
(pc.signalingState == "have-local-offer" && srdAnswerPending);
ignoreOffer = description.type == "offer" && !polite &&
(makingOffer || !isStable);
if (ignoreOffer) {
return;
}
if (description.type == "answer")
srdAnswerPending = true;
await pc.setRemoteDescription(description);
srdAnswerPending = false;
if (description.type == "offer") {
assert_equals(pc.signalingState, "have-remote-offer", "Remote offer");
assert_equals(pc.remoteDescription.type, "offer", "SRD worked");
await pc.setLocalDescription();
assert_equals(pc.signalingState, "stable", "onmessage not racing with negotiationneeded");
assert_equals(pc.localDescription.type, "answer", "onmessage SLD worked");
send(other, {description: pc.localDescription});
} else {
assert_equals(pc.remoteDescription.type, "answer", "Answer was set");
assert_equals(pc.signalingState, "stable", "answered");
pc.dispatchEvent(new Event("negotiated"));
}
} else if (candidate) {
try {
await pc.addIceCandidate(candidate);
} catch (e) {
if (!ignoreOffer) throw e;
}
} else if (run) {
send(window.parent, {[run.id]: await commands[run.cmd]() || 0});
}
} catch (e) {
fail(e);
}
};
} catch (e) {
fail(e);
}
return pc;
}
async function setupPeerIframe(t, polite) {
const iframe = document.createElement("iframe");
t.add_cleanup(() => iframe.remove());
iframe.srcdoc =
`<html\><script\>(${peer.toString()})(window.parent, ${polite});</script\></html\>`;
document.documentElement.appendChild(iframe);
const failCatcher = t.step_func(({data}) =>
("error" in data) && assert_unreached(`Error in iframe: ${data.error}`));
window.addEventListener("message", failCatcher);
t.add_cleanup(() => window.removeEventListener("message", failCatcher));
await new Promise(r => iframe.onload = r);
return iframe;
}
function setupPeerTopLevel(t, other, polite) {
const pc = peer(other, polite, t.step_func(e => { throw e; }));
t.add_cleanup(() => { pc.close(); window.onmessage = null; });
}
let counter = 0;
async function run(target, cmd) {
const id = `result${counter++}`;
target.postMessage({run: {cmd, id}}, "*");
return new Promise(r => window.addEventListener("message",
function listen({data}) {
if (!(id in data)) return;
window.removeEventListener("message", listen);
r(data[id]);
}));
}
let iframe;
async function setupAB(t, politeA, politeB) {
iframe = await setupPeerIframe(t, politeB);
return setupPeerTopLevel(t, iframe.contentWindow, politeA);
}
const runA = cmd => run(window, cmd);
const runB = cmd => run(iframe.contentWindow, cmd);
const runBoth = (cmdA, cmdB = cmdA) => Promise.all([runA(cmdA), runB(cmdB)]);
async function promise_test_both_roles(f, name) {
promise_test(async t => f(t, await setupAB(t, true, false)), name);
promise_test(async t => f(t, await setupAB(t, false, true)),
`${name} with roles reversed`);
}
<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<title></title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="RTCPeerConnection-perfect-negotiation-helper.js"></script>
<script>
'use strict';
promise_test_both_roles(async (t, pc) => {
const ps = [];
for (let i = 10; i > 0; i--) {
ps.push(runBoth("addTransceiver"));
await new Promise(r => t.step_timeout(r, 0));
}
ps.push(runBoth("addTransceiver"));
await Promise.all(ps);
const [numA, numB] = await runBoth("getNumTransceivers");
assert_equals(numA, 22, "22 transceivers on side A");
assert_equals(numB, 22, "22 transceivers on side B");
}, "Perfect negotiation stress glare linear");
</script>
<!doctype html>
<meta charset=utf-8>
<meta name="timeout" content="long">
<title></title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="RTCPeerConnection-perfect-negotiation-helper.js"></script>
<script>
'use strict';
promise_test_both_roles(async (t, pc) => {
const ps = [];
for (let i = 10; i > 0; i--) {
ps.push(runBoth("addTransceiver"));
await new Promise(r => t.step_timeout(r, i - 1));
}
ps.push(runBoth("addTransceiver"));
await Promise.all(ps);
const [numA, numB] = await runBoth("getNumTransceivers");
assert_equals(numA, 22, "22 transceivers on side A");
assert_equals(numB, 22, "22 transceivers on side B");
}, "Perfect negotiation stress glare");
</script>
...@@ -4,159 +4,10 @@ ...@@ -4,159 +4,10 @@
<title></title> <title></title>
<script src=/resources/testharness.js></script> <script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script> <script src=/resources/testharnessreport.js></script>
<script src="RTCPeerConnection-perfect-negotiation-helper.js"></script>
<script> <script>
'use strict'; 'use strict';
function peer(other, polite, fail = null) {
const send = (tgt, msg) => tgt.postMessage(JSON.parse(JSON.stringify(msg)),
"*");
if (!fail) fail = e => send(window.parent, {error: `${e.name}: ${e.message}`});
const pc = new RTCPeerConnection();
if (!window.assert_equals) {
window.assert_equals = (a, b, msg) => a === b ||
fail(new Error(`${msg} expected ${b} but got ${a}`));
}
const commands = {
async addTransceiver() {
const transceiver = pc.addTransceiver("video");
await new Promise(r => pc.addEventListener("negotiated", r, {once: true}));
if (!transceiver.currentDirection) {
// Might have just missed the negotiation train. Catch next one.
await new Promise(r => pc.addEventListener("negotiated", r, {once: true}));
}
assert_equals(transceiver.currentDirection, "sendonly", "have direction");
return pc.getTransceivers().length;
},
async simpleConnect() {
const p = commands.addTransceiver();
await new Promise(r => pc.oniceconnectionstatechange =
() => pc.iceConnectionState == "connected" && r());
return await p;
},
async getNumTransceivers() {
return pc.getTransceivers().length;
},
};
try {
pc.addEventListener("icecandidate", ({candidate}) => send(other,
{candidate}));
let makingOffer = false, ignoreOffer = false;
let srdAnswerPending = false;
pc.addEventListener("negotiationneeded", async () => {
try {
assert_equals(pc.signalingState, "stable", "negotiationneeded always fires in stable state");
assert_equals(makingOffer, false, "negotiationneeded not already in progress");
makingOffer = true;
await pc.setLocalDescription();
assert_equals(pc.signalingState, "have-local-offer", "negotiationneeded not racing with onmessage");
assert_equals(pc.localDescription.type, "offer", "negotiationneeded SLD worked");
send(other, {description: pc.localDescription});
} catch (e) {
fail(e);
} finally {
makingOffer = false;
}
});
window.onmessage = async ({data: {description, candidate, run}}) => {
try {
if (description) {
// If we have a setRemoteDescription() answer operation pending, then
// we will be "stable" by the time the next setRemoteDescription() is
// executed, so we count this being stable when deciding whether to
// ignore the offer.
let isStable =
pc.signalingState == "stable" ||
(pc.signalingState == "have-local-offer" && srdAnswerPending);
ignoreOffer = description.type == "offer" && !polite &&
(makingOffer || !isStable);
if (ignoreOffer) {
return;
}
if (description.type == "answer")
srdAnswerPending = true;
await pc.setRemoteDescription(description);
srdAnswerPending = false;
if (description.type == "offer") {
assert_equals(pc.signalingState, "have-remote-offer", "Remote offer");
assert_equals(pc.remoteDescription.type, "offer", "SRD worked");
await pc.setLocalDescription();
assert_equals(pc.signalingState, "stable", "onmessage not racing with negotiationneeded");
assert_equals(pc.localDescription.type, "answer", "onmessage SLD worked");
send(other, {description: pc.localDescription});
} else {
assert_equals(pc.remoteDescription.type, "answer", "Answer was set");
assert_equals(pc.signalingState, "stable", "answered");
pc.dispatchEvent(new Event("negotiated"));
}
} else if (candidate) {
try {
await pc.addIceCandidate(candidate);
} catch (e) {
if (!ignoreOffer) throw e;
}
} else if (run) {
send(window.parent, {[run.id]: await commands[run.cmd]() || 0});
}
} catch (e) {
fail(e);
}
};
} catch (e) {
fail(e);
}
return pc;
}
async function setupPeerIframe(t, polite) {
const iframe = document.createElement("iframe");
t.add_cleanup(() => iframe.remove());
iframe.srcdoc =
`<html\><script\>(${peer.toString()})(window.parent, ${polite});</script\></html\>`;
document.documentElement.appendChild(iframe);
const failCatcher = t.step_func(({data}) =>
("error" in data) && assert_unreached(`Error in iframe: ${data.error}`));
window.addEventListener("message", failCatcher);
t.add_cleanup(() => window.removeEventListener("message", failCatcher));
await new Promise(r => iframe.onload = r);
return iframe;
}
function setupPeerTopLevel(t, other, polite) {
const pc = peer(other, polite, t.step_func(e => { throw e; }));
t.add_cleanup(() => { pc.close(); window.onmessage = null; });
}
let counter = 0;
async function run(target, cmd) {
const id = `result${counter++}`;
target.postMessage({run: {cmd, id}}, "*");
return new Promise(r => window.addEventListener("message",
function listen({data}) {
if (!(id in data)) return;
window.removeEventListener("message", listen);
r(data[id]);
}));
}
let iframe;
async function setupAB(t, politeA, politeB) {
iframe = await setupPeerIframe(t, politeB);
return setupPeerTopLevel(t, iframe.contentWindow, politeA);
}
const runA = cmd => run(window, cmd);
const runB = cmd => run(iframe.contentWindow, cmd);
const runBoth = (cmdA, cmdB = cmdA) => Promise.all([runA(cmdA), runB(cmdB)]);
async function promise_test_both_roles(f, name) {
promise_test(async t => f(t, await setupAB(t, true, false)), name);
promise_test(async t => f(t, await setupAB(t, false, true)),
`${name} with roles reversed`);
}
promise_test_both_roles(async (t, pc) => { promise_test_both_roles(async (t, pc) => {
assert_equals(await runA("simpleConnect"), 1, "one transceiver"); assert_equals(await runA("simpleConnect"), 1, "one transceiver");
assert_equals(await runB("addTransceiver"), 2, "two transceivers"); assert_equals(await runB("addTransceiver"), 2, "two transceivers");
...@@ -168,30 +19,4 @@ promise_test_both_roles(async (t, pc) => { ...@@ -168,30 +19,4 @@ promise_test_both_roles(async (t, pc) => {
assert_equals(numA, 2, "two transceivers on side A"); assert_equals(numA, 2, "two transceivers on side A");
assert_equals(numB, 2, "two transceivers on side B"); assert_equals(numB, 2, "two transceivers on side B");
}, "Perfect negotiation glare"); }, "Perfect negotiation glare");
promise_test_both_roles(async (t, pc) => {
const ps = [];
for (let i = 20; i > 0; i--) {
ps.push(runBoth("addTransceiver"));
await new Promise(r => t.step_timeout(r, i - 1));
}
ps.push(runBoth("addTransceiver"));
await Promise.all(ps);
const [numA, numB] = await runBoth("getNumTransceivers");
assert_equals(numA, 42, "42 transceivers on side A");
assert_equals(numB, 42, "42 transceivers on side B");
}, "Perfect negotiation stress glare");
promise_test_both_roles(async (t, pc) => {
const ps = [];
for (let i = 20; i > 0; i--) {
ps.push(runBoth("addTransceiver"));
await new Promise(r => t.step_timeout(r, 0));
}
ps.push(runBoth("addTransceiver"));
await Promise.all(ps);
const [numA, numB] = await runBoth("getNumTransceivers");
assert_equals(numA, 42, "42 transceivers on side A");
assert_equals(numB, 42, "42 transceivers on side B");
}, "Perfect negotiation stress glare linear");
</script> </script>
This is a testharness.js-based test.
FAIL Perfect negotiation stress glare linear Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
FAIL Perfect negotiation stress glare linear with roles reversed Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
Harness: the test ran to completion.
This is a testharness.js-based test.
FAIL Perfect negotiation stress glare Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
FAIL Perfect negotiation stress glare with roles reversed Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
Harness: the test ran to completion.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment