Bug 1647892 - Improve the reliability of test_double_submit.html, r=farre

Unlike the previous implementation, this new version performs the
waiting before sending response headers, meaning that it delays
OnStartRequest rather than just delaying the response body. As the
double-submission prevention currently only waits for OnStartRequest,
this should improve the reliability of the test.

Because the test no longer requires large amounts of data for delay
purposes, it has also been simplified to not generate random large
payloads anymore.

Differential Revision: https://phabricator.services.mozilla.com/D141427
This commit is contained in:
Nika Layzell 2022-03-21 20:19:45 +00:00
Родитель 08b1e68cb1
Коммит c14c6bb509
2 изменённых файлов: 22 добавлений и 84 удалений

Просмотреть файл

@ -12,35 +12,10 @@ const BinaryInputStream = CC(
"setInputStream"
);
const BinaryOutputStream = CC(
"@mozilla.org/binaryoutputstream;1",
"nsIBinaryOutputStream",
"setOutputStream"
);
function log(str) {
// dump(`LOG: ${str}\n`);
}
function* generateBody(fragments, size) {
let result = [];
let chunkSize = (size / fragments) | 0;
let remaining = size;
log(`Chunk size ${chunkSize}`);
while (remaining > 0) {
let data = new Uint8Array(Math.min(remaining, chunkSize));
for (let i = 0; i < data.length; ++i) {
// Generate a character in the [a-z] range.
data[i] = 97 + Math.random() * (123 - 97);
}
yield data;
log(`Remaining to chunk ${remaining}`);
remaining -= data.length;
}
}
function readStream(inputStream) {
let available = 0;
let result = [];
@ -60,9 +35,9 @@ async function handleRequest(request, response) {
Cu.importGlobalProperties(["URLSearchParams"]);
let params = new URLSearchParams(request.queryString);
let start = now();
let delay = parseInt(params.get("delay")) || 0;
let delayUntil = now() + delay;
log(`Delay until ${delayUntil}`);
log(`Delay for ${delay}`);
let message = "good";
if (request.method !== "POST") {
@ -76,54 +51,28 @@ async function handleRequest(request, response) {
log(`The result was ${message}`);
}
let fragments = parseInt(params.get("fragments")) || 1;
let size = parseInt(params.get("size")) || 1024;
let body = `<!doctype html>
<script>
"use strict";
let target = (opener || parent);
target.postMessage(${JSON.stringify(message)}, '*');
</script>`;
let outputStream = new BinaryOutputStream(response.bodyOutputStream);
// Sieze power from the response to allow manually transmitting data at any
// rate we want, so we can delay transmitting headers.
response.seizePower();
let header = "<!doctype html><!-- ";
let footer = ` --><script>"use strict"; let target = (opener || parent); target.postMessage('${message}', '*');</script>`;
log(`Writing HTTP status line at ${now() - start}`);
response.write("HTTP/1.1 200 OK\r\n");
log("Set headers");
response.setHeader("Content-Type", "text/html", false);
response.setHeader(
"Content-Length",
`${size + header.length + footer.length}`,
false
);
response.setStatusLine(request.httpVersion, "200", "OK");
response.processAsync();
log("Write header");
response.write(header);
log("Write body");
for (let data of generateBody(fragments, size)) {
delay = Math.max(0, delayUntil - now());
log(`Delay sending fragment for ${delay / fragments}`);
let failed = false;
await new Promise(resolve => {
setTimeout(() => {
try {
outputStream.writeByteArray(data, data.length);
} catch (e) {
log(e.message);
failed = true;
}
resolve();
}, delay / fragments);
});
if (failed) {
log("Stopped sending data");
break;
}
fragments = Math.max(--fragments, 1);
log(`Fragments left ${fragments}`);
}
log("Write footer");
response.write(footer);
await new Promise(resolve => setTimeout(() => resolve(), delay));
log(`Delay completed at ${now() - start}`);
response.write("Content-Type: text/html\r\n");
response.write(`Content-Length: ${body.length}\r\n`);
response.write("\r\n");
response.write(body);
response.finish();
log("Finished");
}

Просмотреть файл

@ -8,8 +8,7 @@
</head>
<body>
<iframe name="targetFrame" id="targetFrame"></iframe>
<form id="form" action="double_submit.sjs?size=4096&fragments=10&delay=1000" method="POST" target="targetFrame">
<input id="input" type="text" name="text" value="value">
<form id="form" action="double_submit.sjs?delay=1000" method="POST" target="targetFrame">
<input id="token" type="text" name="token" value="">
<input id="button" type="submit">
</form>
@ -18,15 +17,6 @@
const CROSS_ORIGIN_URI = "http://test1.example.com/tests/docshell/test/mochitest/ping.html";
function generateBody(size) {
let data = new Uint8Array(size);
for (let i = 0; i < size; ++i) {
data[i] = 97 + Math.random() * (123 - 97);
}
return new TextDecoder().decode(data);
}
function asyncClick(counts) {
let frame = document.createElement('iframe');
frame.addEventListener(
@ -59,7 +49,6 @@
let form = document.getElementById('form');
let button = document.getElementById('button');
document.getElementById('input').value = generateBody(1024*1024);
let token = document.getElementById('token');
token.value = "first";