test_http2_proxy_concurrent_stream.js (4238B)
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/. */ 4 5 "use strict"; 6 7 /* import-globals-from head_cache.js */ 8 /* import-globals-from head_cookies.js */ 9 /* import-globals-from head_channels.js */ 10 11 const { setTimeout } = ChromeUtils.importESModule( 12 "resource://gre/modules/Timer.sys.mjs" 13 ); 14 15 const { 16 NodeHTTPServer, 17 NodeHTTPSServer, 18 NodeHTTP2Server, 19 NodeHTTP2ProxyServer, 20 with_node_servers, 21 } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs"); 22 23 add_setup(async function () { 24 Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); 25 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( 26 Ci.nsIX509CertDB 27 ); 28 addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); 29 addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u"); 30 registerCleanupFunction(() => { 31 Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); 32 Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); 33 }); 34 }); 35 36 function makeChan(uri) { 37 let chan = NetUtil.newChannel({ 38 uri, 39 loadUsingSystemPrincipal: true, 40 }).QueryInterface(Ci.nsIHttpChannel); 41 chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI; 42 return chan; 43 } 44 45 function channelOpenPromise(chan, flags) { 46 return new Promise(resolve => { 47 function finish(req, buffer) { 48 resolve([req, buffer]); 49 } 50 chan.asyncOpen(new ChannelListener(finish, null, flags)); 51 }); 52 } 53 54 function registerServerNamePathHandler(server, path) { 55 return server.registerPathHandler(path, (req, resp) => { 56 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 57 setTimeout(() => { 58 resp.writeHead(200); 59 resp.end(global.server_name); 60 }, 1000); 61 }); 62 } 63 64 async function run_http2_proxy_test( 65 maxConcurrentStreams, 66 maxStreamId, 67 testId = "" 68 ) { 69 Services.obs.notifyObservers(null, "net:prune-all-connections"); 70 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 71 await new Promise(resolve => setTimeout(resolve, 1000)); 72 73 Services.prefs.setIntPref("network.http.http2.max_stream_id", maxStreamId); 74 75 let proxy = new NodeHTTP2ProxyServer(); 76 await proxy.start(0, false, maxConcurrentStreams); 77 registerCleanupFunction(async () => { 78 await proxy.stop(); 79 }); 80 81 await with_node_servers( 82 [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server], 83 async server => { 84 await server.execute( 85 `global.server_name = "${server.constructor.name}";` 86 ); 87 await registerServerNamePathHandler(server, "/test"); 88 89 await channelOpenPromise( 90 makeChan(`${server.origin()}/test`), 91 CL_ALLOW_UNKNOWN_CL 92 ); 93 94 // Wait a bit to ensure the first proxy connection is established. 95 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 96 await new Promise(resolve => setTimeout(resolve, 1000)); 97 98 let promises = []; 99 for (let i = 0; i < 20; i++) { 100 let promise = channelOpenPromise( 101 makeChan(`${server.origin()}/test?test=${testId}&id=${i}`), 102 CL_ALLOW_UNKNOWN_CL 103 ); 104 105 promises.push(promise); 106 } 107 108 let results = await Promise.all(promises); 109 for (let [req, buff] of results) { 110 equal(req.status, Cr.NS_OK); 111 equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200); 112 equal(buff, server.constructor.name); 113 } 114 await server.stop(); 115 } 116 ); 117 118 await proxy.stop(); 119 } 120 121 // Test case 1: High concurrency, high stream ID limit 122 add_task(async function test_high_concurrency_high_stream_id() { 123 await run_http2_proxy_test(100, 0x7800000, "t1"); 124 }); 125 126 // Test case 2: Low concurrency, high stream ID limit 127 add_task(async function test_low_concurrency_high_stream_id() { 128 await run_http2_proxy_test(3, 0x7800000, "t2"); 129 }); 130 131 // Test case 3: High concurrency, low stream ID limit 132 add_task(async function test_high_concurrency_low_stream_id() { 133 await run_http2_proxy_test(100, 10, "t3"); 134 }); 135 136 // Test case 4: Low concurrency, low stream ID limit 137 add_task(async function test_low_concurrency_low_stream_id() { 138 await run_http2_proxy_test(3, 10, "t4"); 139 });