Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android'
- Manifest: netwerk/test/unit/xpcshell.toml
/* 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
"use strict";
/* import-globals-from head_cache.js */
/* import-globals-from head_cookies.js */
/* import-globals-from head_channels.js */
/* import-globals-from head_servers.js */
var { setTimeout } = ChromeUtils.importESModule(
"resource://gre/modules/Timer.sys.mjs"
);
add_setup(async function () {
Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u");
registerCleanupFunction(() => {
Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
});
});
function makeChan(uri) {
let chan = NetUtil.newChannel({
uri,
loadUsingSystemPrincipal: true,
}).QueryInterface(Ci.nsIHttpChannel);
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
return chan;
}
function channelOpenPromise(chan, flags) {
return new Promise(resolve => {
function finish(req, buffer) {
resolve([req, buffer]);
}
chan.asyncOpen(new ChannelListener(finish, null, flags));
});
}
function regiisterServerNamePathHandler(server, path) {
return server.registerPathHandler(path, (req, resp) => {
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(() => {
resp.writeHead(200);
resp.end(global.server_name);
}, 1000);
});
}
async function run_http2_proxy_test(maxConcurrentStreams, maxStreamId) {
Services.obs.notifyObservers(null, "net:prune-all-connections");
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 1000));
Services.prefs.setIntPref("network.http.http2.max_stream_id", maxStreamId);
let proxy = new NodeHTTP2ProxyServer();
await proxy.start(0, false, maxConcurrentStreams);
registerCleanupFunction(async () => {
await proxy.stop();
});
await with_node_servers(
[NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server],
async server => {
await server.execute(
`global.server_name = "${server.constructor.name}";`
);
await regiisterServerNamePathHandler(server, "/test");
await channelOpenPromise(
makeChan(`${server.origin()}/test`),
CL_ALLOW_UNKNOWN_CL
);
// Wait a bit to ensure the first proxy connection is established.
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 1000));
let promises = [];
for (let i = 0; i < 20; i++) {
let promise = channelOpenPromise(
makeChan(`${server.origin()}/test`),
CL_ALLOW_UNKNOWN_CL
);
promises.push(promise);
}
let results = await Promise.all(promises);
for (let [req, buff] of results) {
equal(req.status, Cr.NS_OK);
equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
equal(buff, server.constructor.name);
}
await server.stop();
}
);
await proxy.stop();
}
// Test case 1: High concurrency, high stream ID limit
add_task(async function test_high_concurrency_high_stream_id() {
await run_http2_proxy_test(100, 0x7800000);
});
// Test case 2: Low concurrency, high stream ID limit
add_task(async function test_low_concurrency_high_stream_id() {
await run_http2_proxy_test(3, 0x7800000);
});
// Test case 3: High concurrency, low stream ID limit
add_task(async function test_high_concurrency_low_stream_id() {
await run_http2_proxy_test(100, 10);
});
// Test case 4: Low concurrency, low stream ID limit
add_task(async function test_low_concurrency_low_stream_id() {
await run_http2_proxy_test(3, 10);
});