165 lines
4.9 KiB
JavaScript
165 lines
4.9 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
registerCleanupFunction(async () => {
|
|
http3_clear_prefs();
|
|
});
|
|
|
|
add_task(async function setup() {
|
|
await http3_setup_tests("h3");
|
|
});
|
|
|
|
let Http3Listener = function (amount) {
|
|
this.amount = amount;
|
|
};
|
|
|
|
Http3Listener.prototype = {
|
|
expectedStatus: Cr.NS_OK,
|
|
amount: 0,
|
|
onProgressMaxNotificationCount: 0,
|
|
onProgressNotificationCount: 0,
|
|
|
|
QueryInterface: ChromeUtils.generateQI(["nsIProgressEventSink"]),
|
|
|
|
getInterface(iid) {
|
|
if (iid.equals(Ci.nsIProgressEventSink)) {
|
|
return this;
|
|
}
|
|
throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
|
|
},
|
|
|
|
onProgress(request, progress, progressMax) {
|
|
// we will get notifications for the request and the response.
|
|
if (progress === progressMax) {
|
|
this.onProgressMaxNotificationCount += 1;
|
|
}
|
|
// For a large upload there should be a multiple notifications.
|
|
this.onProgressNotificationCount += 1;
|
|
},
|
|
|
|
onStatus() {},
|
|
|
|
onStartRequest: function testOnStartRequest(request) {
|
|
Assert.equal(request.status, this.expectedStatus);
|
|
if (Components.isSuccessCode(this.expectedStatus)) {
|
|
Assert.equal(request.responseStatus, 200);
|
|
}
|
|
Assert.equal(
|
|
this.amount,
|
|
request.getResponseHeader("x-data-received-length")
|
|
);
|
|
},
|
|
|
|
onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) {
|
|
read_stream(stream, cnt);
|
|
},
|
|
|
|
onStopRequest: function testOnStopRequest(request) {
|
|
let httpVersion = "";
|
|
try {
|
|
httpVersion = request.protocolVersion;
|
|
} catch (e) {}
|
|
Assert.equal(httpVersion, "h3");
|
|
// We should get 2 correctOnProgress, i.e. one for request and one for the response.
|
|
Assert.equal(this.onProgressMaxNotificationCount, 2);
|
|
if (this.amount > 500000) {
|
|
// 10 is an arbitrary number, but we cannot calculate exact number
|
|
// because it depends on timing.
|
|
Assert.ok(this.onProgressNotificationCount > 10);
|
|
}
|
|
this.finish();
|
|
},
|
|
};
|
|
|
|
function chanPromise(chan, listener) {
|
|
return new Promise(resolve => {
|
|
function finish(result) {
|
|
resolve(result);
|
|
}
|
|
listener.finish = finish;
|
|
chan.asyncOpen(listener);
|
|
});
|
|
}
|
|
|
|
function makeChan(uri, amount) {
|
|
let chan = NetUtil.newChannel({
|
|
uri,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
|
|
|
let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
|
|
Ci.nsIStringInputStream
|
|
);
|
|
stream.setByteStringData(generateContent(amount));
|
|
let uchan = chan.QueryInterface(Ci.nsIUploadChannel);
|
|
uchan.setUploadStream(stream, "text/plain", stream.available());
|
|
chan.requestMethod = "POST";
|
|
return chan;
|
|
}
|
|
|
|
// Generate a post.
|
|
function generateContent(size) {
|
|
let content = "";
|
|
for (let i = 0; i < size; i++) {
|
|
content += "0";
|
|
}
|
|
return content;
|
|
}
|
|
|
|
// Send a large post that can fit into a neqo stream buffer at once.
|
|
// But the amount of data is larger than the necko's default stream
|
|
// buffer side, therefore ReadSegments will be called multiple times.
|
|
add_task(async function test_large_post() {
|
|
let amount = 1 << 16;
|
|
let listener = new Http3Listener(amount);
|
|
let chan = makeChan("https://foo.example.com/post", amount);
|
|
chan.notificationCallbacks = listener;
|
|
await chanPromise(chan, listener);
|
|
});
|
|
|
|
// Send a large post that cannot fit into a neqo stream buffer at once.
|
|
// StreamWritable events will trigger sending more data when the buffer
|
|
// space is freed
|
|
add_task(async function test_large_post2() {
|
|
let amount = 1 << 23;
|
|
let listener = new Http3Listener(amount);
|
|
let chan = makeChan("https://foo.example.com/post", amount);
|
|
chan.notificationCallbacks = listener;
|
|
await chanPromise(chan, listener);
|
|
});
|
|
|
|
// Send a post in the same way viaduct does in bug 1749957.
|
|
add_task(async function test_bug1749957_bug1750056() {
|
|
let amount = 200; // Tests the bug as long as it's non-zero.
|
|
let uri = "https://foo.example.com/post";
|
|
let listener = new Http3Listener(amount);
|
|
|
|
let chan = NetUtil.newChannel({
|
|
uri,
|
|
loadUsingSystemPrincipal: true,
|
|
}).QueryInterface(Ci.nsIHttpChannel);
|
|
|
|
// https://searchfox.org/mozilla-central/rev/1920b17ac5988fcfec4e45e2a94478ebfbfc6f88/toolkit/components/viaduct/ViaductRequest.cpp#120-152
|
|
{
|
|
chan.requestMethod = "POST";
|
|
chan.setRequestHeader("content-length", "" + amount, /* aMerge = */ false);
|
|
|
|
let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
|
|
Ci.nsIStringInputStream
|
|
);
|
|
stream.setByteStringData(generateContent(amount));
|
|
let uchan = chan.QueryInterface(Ci.nsIUploadChannel2);
|
|
uchan.explicitSetUploadStream(
|
|
stream,
|
|
/* aContentType = */ "",
|
|
/* aContentLength = */ -1,
|
|
"POST",
|
|
/* aStreamHasHeaders = */ false
|
|
);
|
|
}
|
|
|
|
chan.notificationCallbacks = listener;
|
|
await chanPromise(chan, listener);
|
|
});
|