1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 registerCleanupFunction(async () => {
9 add_task(async
function setup() {
10 await
http3_setup_tests("h3");
13 let Http3Listener = function (amount
) {
17 Http3Listener
.prototype = {
18 expectedStatus
: Cr
.NS_OK
,
20 onProgressMaxNotificationCount
: 0,
21 onProgressNotificationCount
: 0,
23 QueryInterface
: ChromeUtils
.generateQI(["nsIProgressEventSink"]),
26 if (iid
.equals(Ci
.nsIProgressEventSink
)) {
29 throw Components
.Exception("", Cr
.NS_ERROR_NO_INTERFACE
);
32 onProgress(request
, progress
, progressMax
) {
33 // we will get notifications for the request and the response.
34 if (progress
=== progressMax
) {
35 this.onProgressMaxNotificationCount
+= 1;
37 // For a large upload there should be a multiple notifications.
38 this.onProgressNotificationCount
+= 1;
43 onStartRequest
: function testOnStartRequest(request
) {
44 Assert
.equal(request
.status
, this.expectedStatus
);
45 if (Components
.isSuccessCode(this.expectedStatus
)) {
46 Assert
.equal(request
.responseStatus
, 200);
50 request
.getResponseHeader("x-data-received-length")
54 onDataAvailable
: function testOnDataAvailable(request
, stream
, off
, cnt
) {
55 read_stream(stream
, cnt
);
58 onStopRequest
: function testOnStopRequest(request
) {
61 httpVersion
= request
.protocolVersion
;
63 Assert
.equal(httpVersion
, "h3");
64 // We should get 2 correctOnProgress, i.e. one for request and one for the response.
65 Assert
.equal(this.onProgressMaxNotificationCount
, 2);
66 if (this.amount
> 500000) {
67 // 10 is an arbitrary number, but we cannot calculate exact number
68 // because it depends on timing.
69 Assert
.ok(this.onProgressNotificationCount
> 10);
75 function chanPromise(chan
, listener
) {
76 return new Promise(resolve
=> {
77 function finish(result
) {
80 listener
.finish
= finish
;
81 chan
.asyncOpen(listener
);
85 function makeChan(uri
, amount
) {
86 let chan
= NetUtil
.newChannel({
88 loadUsingSystemPrincipal
: true,
89 }).QueryInterface(Ci
.nsIHttpChannel
);
90 chan
.loadFlags
= Ci
.nsIChannel
.LOAD_INITIAL_DOCUMENT_URI
;
92 let stream
= Cc
["@mozilla.org/io/string-input-stream;1"].createInstance(
93 Ci
.nsIStringInputStream
95 stream
.setByteStringData(generateContent(amount
));
96 let uchan
= chan
.QueryInterface(Ci
.nsIUploadChannel
);
97 uchan
.setUploadStream(stream
, "text/plain", stream
.available());
98 chan
.requestMethod
= "POST";
103 function generateContent(size
) {
105 for (let i
= 0; i
< size
; i
++) {
111 // Send a large post that can fit into a neqo stream buffer at once.
112 // But the amount of data is larger than the necko's default stream
113 // buffer side, therefore ReadSegments will be called multiple times.
114 add_task(async
function test_large_post() {
115 let amount
= 1 << 16;
116 let listener
= new Http3Listener(amount
);
117 let chan
= makeChan("https://foo.example.com/post", amount
);
118 chan
.notificationCallbacks
= listener
;
119 await
chanPromise(chan
, listener
);
122 // Send a large post that cannot fit into a neqo stream buffer at once.
123 // StreamWritable events will trigger sending more data when the buffer
125 add_task(async
function test_large_post2() {
126 let amount
= 1 << 23;
127 let listener
= new Http3Listener(amount
);
128 let chan
= makeChan("https://foo.example.com/post", amount
);
129 chan
.notificationCallbacks
= listener
;
130 await
chanPromise(chan
, listener
);
133 // Send a post in the same way viaduct does in bug 1749957.
134 add_task(async
function test_bug1749957_bug1750056() {
135 let amount
= 200; // Tests the bug as long as it's non-zero.
136 let uri
= "https://foo.example.com/post";
137 let listener
= new Http3Listener(amount
);
139 let chan
= NetUtil
.newChannel({
141 loadUsingSystemPrincipal
: true,
142 }).QueryInterface(Ci
.nsIHttpChannel
);
144 // https://searchfox.org/mozilla-central/rev/1920b17ac5988fcfec4e45e2a94478ebfbfc6f88/toolkit/components/viaduct/ViaductRequest.cpp#120-152
146 chan
.requestMethod
= "POST";
147 chan
.setRequestHeader("content-length", "" + amount
, /* aMerge = */ false);
149 let stream
= Cc
["@mozilla.org/io/string-input-stream;1"].createInstance(
150 Ci
.nsIStringInputStream
152 stream
.setByteStringData(generateContent(amount
));
153 let uchan
= chan
.QueryInterface(Ci
.nsIUploadChannel2
);
154 uchan
.explicitSetUploadStream(
156 /* aContentType = */ "",
157 /* aContentLength = */ -1,
159 /* aStreamHasHeaders = */ false
163 chan
.notificationCallbacks
= listener
;
164 await
chanPromise(chan
, listener
);