summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_connection_coalescing.js
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/unit/test_connection_coalescing.js')
-rw-r--r--netwerk/test/unit/test_connection_coalescing.js194
1 files changed, 194 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_connection_coalescing.js b/netwerk/test/unit/test_connection_coalescing.js
new file mode 100644
index 0000000000..a61098e73e
--- /dev/null
+++ b/netwerk/test/unit/test_connection_coalescing.js
@@ -0,0 +1,194 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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/. */
+
+"use strict";
+
+const override = Cc["@mozilla.org/network/native-dns-override;1"].getService(
+ Ci.nsINativeDNSResolverOverride
+);
+
+let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
+ Ci.nsIX509CertDB
+);
+addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
+
+async function createServer() {
+ let server = new NodeHTTP2Server();
+ await server.start();
+ registerCleanupFunction(async () => {
+ await server.stop();
+ });
+ await server.registerPathHandler("/", (req, resp) => {
+ let content = `hello from ${req.authority} | ${req.socket.remotePort}`;
+ resp.writeHead(200, {
+ "Content-Type": "text/plain",
+ "Content-Length": `${content.length}`,
+ });
+ resp.end(content);
+ });
+ return server;
+}
+
+let IP1 = "127.0.0.1";
+let IP2 = "127.0.0.2";
+if (AppConstants.platform == "macosx") {
+ // OSX doesn't use 127.0.0.2 as a local interface
+ IP2 = "::1";
+} else if (AppConstants.platform == "android") {
+ IP2 = "10.0.2.2";
+}
+
+async function openChan(uri) {
+ let chan = NetUtil.newChannel({
+ uri,
+ loadUsingSystemPrincipal: true,
+ }).QueryInterface(Ci.nsIHttpChannel);
+ chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
+
+ let { req, buffer } = await new Promise(resolve => {
+ function finish(r, b) {
+ resolve({ req: r, buffer: b });
+ }
+ chan.asyncOpen(new ChannelListener(finish, null, CL_ALLOW_UNKNOWN_CL));
+ });
+
+ return {
+ buffer,
+ port: buffer.split("|")[1],
+ addr: req.QueryInterface(Ci.nsIHttpChannelInternal).remoteAddress,
+ status: req.QueryInterface(Ci.nsIHttpChannel).responseStatus,
+ };
+}
+
+add_task(async function test_dontCoalesce() {
+ let server = await createServer();
+ Services.prefs.setBoolPref("network.http.http2.aggressive_coalescing", false);
+ override.clearOverrides();
+ Services.dns.clearCache(true);
+
+ override.addIPOverride("foo.example.com", IP1);
+ override.addIPOverride("foo.example.com", IP2);
+ override.addIPOverride("alt1.example.com", IP2);
+
+ let { addr: addr1 } = await openChan(
+ `https://foo.example.com:${server.port()}/`
+ );
+ let { addr: addr2 } = await openChan(
+ `https://alt1.example.com:${server.port()}/`
+ );
+
+ Assert.notEqual(addr1, addr2);
+ await server.stop();
+});
+
+add_task(async function test_doCoalesce() {
+ let server = await createServer();
+ Services.prefs.setBoolPref("network.http.http2.aggressive_coalescing", false);
+ override.clearOverrides();
+ Services.dns.clearCache(true);
+
+ override.addIPOverride("foo.example.com", IP1);
+ override.addIPOverride("foo.example.com", IP2);
+ override.addIPOverride("alt2.example.com", IP1);
+ override.addIPOverride("alt2.example.com", IP2);
+
+ let { port: port1, addr: addr1 } = await openChan(
+ `https://foo.example.com:${server.port()}/`
+ );
+ let { port: port2, addr: addr2 } = await openChan(
+ `https://alt2.example.com:${server.port()}/`
+ );
+
+ Assert.equal(addr1, addr2);
+ Assert.equal(port1, port2);
+ await server.stop();
+});
+
+add_task(async function test_doCoalesceAggresive() {
+ let server = await createServer();
+
+ Services.prefs.setBoolPref("network.http.http2.aggressive_coalescing", true);
+ override.clearOverrides();
+ Services.dns.clearCache(true);
+
+ override.addIPOverride("foo.example.com", IP1);
+ override.addIPOverride("foo.example.com", IP2);
+ override.addIPOverride("alt1.example.com", IP2);
+
+ let { port: port1, addr: addr1 } = await openChan(
+ `https://foo.example.com:${server.port()}/`
+ );
+ let { port: port2, addr: addr2 } = await openChan(
+ `https://alt1.example.com:${server.port()}/`
+ );
+
+ Assert.equal(addr1, addr2);
+ Assert.equal(port1, port2);
+ await server.stop();
+});
+
+// On android because of the way networking is set up the
+// localAddress is always ::ffff:127.0.0.1 so it can't be
+// used to make a decision.
+add_task(
+ { skip_if: () => AppConstants.platform == "android" },
+ async function test_doCoalesceAggresive421() {
+ let server = await createServer();
+
+ await server.execute(`global.rightIP = "${IP2}"`);
+
+ await server.registerPathHandler("/", (req, resp) => {
+ let content = `hello from ${req.authority} | ${req.socket.remotePort}`;
+ // Check that returning 421 when aggresively coalescing
+ // makes Firefox not coalesce the connections.
+ if (
+ req.authority.startsWith("alt1.example.com") &&
+ req.socket.localAddress != global.rightIP &&
+ req.socket.localAddress != `::ffff:${global.rightIP}`
+ ) {
+ resp.writeHead(421, {
+ "Content-Type": "text/plain",
+ "Content-Length": `${content.length}`,
+ });
+ resp.end(content);
+ return;
+ }
+ resp.writeHead(200, {
+ "Content-Type": "text/plain",
+ "Content-Length": `${content.length}`,
+ });
+ resp.end(content);
+ });
+
+ Services.prefs.setBoolPref(
+ "network.http.http2.aggressive_coalescing",
+ true
+ );
+ override.clearOverrides();
+ Services.dns.clearCache(true);
+
+ override.addIPOverride("foo.example.com", IP1);
+ override.addIPOverride("foo.example.com", IP2);
+ override.addIPOverride("alt1.example.com", IP2);
+
+ let {
+ addr: addr1,
+ status: status1,
+ port: port1,
+ } = await openChan(`https://foo.example.com:${server.port()}/`);
+ Assert.equal(status1, 200);
+ Assert.equal(addr1, IP1);
+ let {
+ addr: addr2,
+ status: status2,
+ port: port2,
+ } = await openChan(`https://alt1.example.com:${server.port()}/`);
+
+ Assert.equal(status2, 200);
+ Assert.equal(addr2, IP2);
+ Assert.notEqual(port1, port2);
+ await server.stop();
+ }
+);