test_http3_perf.js (6690B)
1 "use strict"; 2 3 // This test is run as part of the perf tests which require the metadata. 4 /* exported perfMetadata */ 5 var perfMetadata = { 6 owner: "Network Team", 7 name: "http3 raw", 8 description: 9 "XPCShell tests that verifies the lib integration against a local server", 10 options: { 11 default: { 12 perfherder: true, 13 perfherder_metrics: [ 14 { 15 name: "speed", 16 unit: "bps", 17 }, 18 ], 19 xpcshell_cycles: 13, 20 verbose: true, 21 try_platform: ["linux", "mac"], 22 }, 23 }, 24 tags: ["network", "http3", "quic"], 25 }; 26 27 var performance = performance || {}; 28 performance.now = (function () { 29 return ( 30 performance.now || 31 performance.mozNow || 32 performance.msNow || 33 performance.oNow || 34 performance.webkitNow || 35 Date.now 36 ); 37 })(); 38 39 let h3Route; 40 let httpsOrigin; 41 let h3AltSvc; 42 43 let prefs; 44 45 let tests = [ 46 // This test must be the first because it setsup alt-svc connection, that 47 // other tests use. 48 test_https_alt_svc, 49 test_download, 50 testsDone, 51 ]; 52 53 let current_test = 0; 54 55 function run_next_test() { 56 if (current_test < tests.length) { 57 dump("starting test number " + current_test + "\n"); 58 tests[current_test](); 59 current_test++; 60 } 61 } 62 63 // eslint-disable-next-line no-unused-vars 64 function run_test() { 65 let h2Port = Services.env.get("MOZHTTP2_PORT"); 66 Assert.notEqual(h2Port, null); 67 Assert.notEqual(h2Port, ""); 68 let h3Port = Services.env.get("MOZHTTP3_PORT"); 69 Assert.notEqual(h3Port, null); 70 Assert.notEqual(h3Port, ""); 71 h3AltSvc = ":" + h3Port; 72 73 h3Route = "foo.example.com:" + h3Port; 74 do_get_profile(); 75 prefs = Services.prefs; 76 77 prefs.setBoolPref("network.http.http3.enable", true); 78 prefs.setCharPref("network.dns.localDomains", "foo.example.com"); 79 // We always resolve elements of localDomains as it's hardcoded without the 80 // following pref: 81 prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); 82 83 // The certificate for the http3server server is for foo.example.com and 84 // is signed by http2-ca.pem so add that cert to the trust list as a 85 // signing cert. 86 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( 87 Ci.nsIX509CertDB 88 ); 89 addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); 90 httpsOrigin = "https://foo.example.com:" + h2Port + "/"; 91 92 run_next_test(); 93 } 94 95 function makeChan(uri) { 96 let chan = NetUtil.newChannel({ 97 uri, 98 loadUsingSystemPrincipal: true, 99 }).QueryInterface(Ci.nsIHttpChannel); 100 chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI; 101 return chan; 102 } 103 104 let Http3CheckListener = function () {}; 105 106 Http3CheckListener.prototype = { 107 onDataAvailableFired: false, 108 expectedRoute: "", 109 110 onStartRequest: function testOnStartRequest(request) { 111 Assert.ok(request instanceof Ci.nsIHttpChannel); 112 Assert.equal(request.status, Cr.NS_OK); 113 Assert.equal(request.responseStatus, 200); 114 }, 115 116 onDataAvailable: function testOnDataAvailable(request, stream, off, cnt) { 117 this.onDataAvailableFired = true; 118 read_stream(stream, cnt); 119 }, 120 121 onStopRequest: function testOnStopRequest(request, status) { 122 dump("status is " + status + "\n"); 123 // Assert.equal(status, Cr.NS_OK); 124 let routed = "NA"; 125 try { 126 routed = request.getRequestHeader("Alt-Used"); 127 } catch (e) {} 128 dump("routed is " + routed + "\n"); 129 130 Assert.equal(routed, this.expectedRoute); 131 132 let httpVersion = ""; 133 try { 134 httpVersion = request.protocolVersion; 135 } catch (e) {} 136 Assert.equal(httpVersion, "h3"); 137 Assert.equal(this.onDataAvailableFired, true); 138 }, 139 }; 140 141 let WaitForHttp3Listener = function () {}; 142 143 WaitForHttp3Listener.prototype = new Http3CheckListener(); 144 145 WaitForHttp3Listener.prototype.uri = ""; 146 WaitForHttp3Listener.prototype.h3AltSvc = ""; 147 148 WaitForHttp3Listener.prototype.onStopRequest = function testOnStopRequest( 149 request, 150 status 151 ) { 152 Assert.equal(status, Cr.NS_OK); 153 let routed = "NA"; 154 try { 155 routed = request.getRequestHeader("Alt-Used"); 156 } catch (e) {} 157 dump("routed is " + routed + "\n"); 158 159 if (routed == this.expectedRoute) { 160 Assert.equal(routed, this.expectedRoute); // always true, but a useful log 161 162 let httpVersion = ""; 163 try { 164 httpVersion = request.protocolVersion; 165 } catch (e) {} 166 Assert.equal(httpVersion, "h3"); 167 run_next_test(); 168 } else { 169 dump("poll later for alt svc mapping\n"); 170 do_test_pending(); 171 do_timeout(500, () => { 172 doTest(this.uri, this.expectedRoute, this.h3AltSvc); 173 }); 174 } 175 176 do_test_finished(); 177 }; 178 179 function doTest(uri, expectedRoute, altSvc) { 180 let chan = makeChan(uri); 181 let listener = new WaitForHttp3Listener(); 182 listener.uri = uri; 183 listener.expectedRoute = expectedRoute; 184 listener.h3AltSvc = altSvc; 185 chan.setRequestHeader("x-altsvc", altSvc, false); 186 chan.asyncOpen(listener); 187 } 188 189 // Test Alt-Svc for http3. 190 // H2 server returns alt-svc=h3=:h3port 191 function test_https_alt_svc() { 192 dump("test_https_alt_svc()\n"); 193 194 do_test_pending(); 195 doTest(httpsOrigin + "http3-test", h3Route, h3AltSvc); 196 } 197 198 let PerfHttp3Listener = function () {}; 199 200 PerfHttp3Listener.prototype = new Http3CheckListener(); 201 PerfHttp3Listener.prototype.amount = 0; 202 PerfHttp3Listener.prototype.bytesRead = 0; 203 PerfHttp3Listener.prototype.startTime = 0; 204 205 PerfHttp3Listener.prototype.onStartRequest = function testOnStartRequest( 206 request 207 ) { 208 this.startTime = performance.now(); 209 Http3CheckListener.prototype.onStartRequest.call(this, request); 210 }; 211 212 PerfHttp3Listener.prototype.onDataAvailable = function testOnStopRequest( 213 request, 214 stream, 215 off, 216 cnt 217 ) { 218 this.bytesRead += cnt; 219 Http3CheckListener.prototype.onDataAvailable.call( 220 this, 221 request, 222 stream, 223 off, 224 cnt 225 ); 226 }; 227 228 PerfHttp3Listener.prototype.onStopRequest = function testOnStopRequest( 229 request, 230 status 231 ) { 232 let stopTime = performance.now(); 233 Http3CheckListener.prototype.onStopRequest.call(this, request, status); 234 if (this.bytesRead != this.amount) { 235 dump("Wrong number of bytes..."); 236 } else { 237 let speed = (this.bytesRead * 1000) / (stopTime - this.startTime); 238 info("perfMetrics", { speed }); 239 } 240 run_next_test(); 241 do_test_finished(); 242 }; 243 244 function test_download() { 245 dump("test_download()\n"); 246 247 let listener = new PerfHttp3Listener(); 248 listener.expectedRoute = h3Route; 249 listener.amount = 1024 * 1024; 250 let chan = makeChan(httpsOrigin + listener.amount.toString()); 251 chan.asyncOpen(listener); 252 do_test_pending(); 253 } 254 255 function testsDone() { 256 prefs.clearUserPref("network.http.http3.enable"); 257 prefs.clearUserPref("network.dns.localDomains"); 258 prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); 259 dump("testDone\n"); 260 do_test_pending(); 261 do_test_finished(); 262 }