[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/+/2386796
Reviewed-by: Henrik Boström <hbos@chromium.org>
Commit-Queue: Henrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803431}
diff --git a/webrtc/RTCPeerConnection-perfect-negotiation-helper.js b/webrtc/RTCPeerConnection-perfect-negotiation-helper.js
new file mode 100644
index 0000000..28c476e
--- /dev/null
+++ b/webrtc/RTCPeerConnection-perfect-negotiation-helper.js
@@ -0,0 +1,151 @@
+'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`);
+}
diff --git a/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html b/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html
new file mode 100644
index 0000000..cf8bdf2
--- /dev/null
+++ b/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare-linear.https.html
@@ -0,0 +1,23 @@
+<!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>
diff --git a/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html b/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html
new file mode 100644
index 0000000..6134eb2
--- /dev/null
+++ b/webrtc/RTCPeerConnection-perfect-negotiation-stress-glare.https.html
@@ -0,0 +1,23 @@
+<!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>
diff --git a/webrtc/RTCPeerConnection-perfect-negotiation.https.html b/webrtc/RTCPeerConnection-perfect-negotiation.https.html
index bd1a7c1..d01b116 100644
--- a/webrtc/RTCPeerConnection-perfect-negotiation.https.html
+++ b/webrtc/RTCPeerConnection-perfect-negotiation.https.html
@@ -4,159 +4,10 @@
 <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';
 
-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) => {
   assert_equals(await runA("simpleConnect"), 1, "one transceiver");
   assert_equals(await runB("addTransceiver"), 2, "two transceivers");
@@ -168,30 +19,4 @@
   assert_equals(numA, 2, "two transceivers on side A");
   assert_equals(numB, 2, "two transceivers on side B");
 }, "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>