Bug 1552176 - Unit test for TRRMode for individual channels r=dragana
☠☠ backed out by 10548d5bb1cc ☠ ☠
authorValentin Gosu <valentin.gosu@gmail.com>
Sat, 02 Nov 2019 20:42:25 +0000
changeset 500273 a11ffd474c0cf99da9ab80fb6fa34def53d14b2c
parent 500272 fb90d8c061801c397ac01cb9e04cba4e83c3186a
child 500274 751b518e08faf652b48b4dd9622039896f5942af
push id114164
push useraiakab@mozilla.com
push dateTue, 05 Nov 2019 10:06:15 +0000
treeherdermozilla-inbound@4d585c7edc76 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1552176
milestone72.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1552176 - Unit test for TRRMode for individual channels r=dragana Differential Revision: https://phabricator.services.mozilla.com/D48362
netwerk/test/unit/test_trr.js
--- a/netwerk/test/unit/test_trr.js
+++ b/netwerk/test/unit/test_trr.js
@@ -1,11 +1,11 @@
 "use strict";
 
-const { NodeServer } = ChromeUtils.import("resource://testing-common/httpd.js");
+const { NodeServer, HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");
 const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
   Ci.nsIDNSService
 );
 const { MockRegistrar } = ChromeUtils.import(
   "resource://testing-common/MockRegistrar.jsm"
 );
 const mainThread = Services.tm.currentThread;
 
@@ -139,28 +139,147 @@ class DNSListener {
     throw Cr.NS_ERROR_NO_INTERFACE;
   }
 
   // Implement then so we can await this as a promise.
   then() {
     return this.promise.then.apply(this.promise, arguments);
   }
 }
-
 add_task(async function test0_nodeExecute() {
   // This test checks that moz-http2.js running in node is working.
   // This should always be the first test in this file (except for setup)
   // otherwise we may encounter random failures when the http2 server is down.
   equal(
     await NodeServer.execute(`"hello"`),
     "hello",
     "Check that moz-http2.js is running"
   );
 });
 
+function makeChan(url, mode) {
+  let chan = NetUtil.newChannel({
+    uri: url,
+    loadUsingSystemPrincipal: true,
+  }).QueryInterface(Ci.nsIHttpChannel);
+  chan.setTRRMode(mode);
+  return chan;
+}
+
+add_task(async function test_trr_flags() {
+  let httpserv = new HttpServer();
+  httpserv.registerPathHandler("/", function handler(metadata, response) {
+    let content = "ok";
+    response.setHeader("Content-Length", `${content.length}`);
+    response.bodyOutputStream.write(content, content.length);
+  });
+  httpserv.start(-1);
+  const URL = `http://example.com:${httpserv.identity.primaryPort}/`;
+
+  dns.clearCache(true);
+  Services.prefs.setCharPref(
+    "network.trr.uri",
+    `https://localhost:${h2Port}/doh?responseIP=127.9.0.9`
+  );
+
+  Services.prefs.setIntPref("network.trr.mode", 0);
+  dns.clearCache(true);
+  let chan = makeChan(URL, Ci.nsIRequest.TRR_DEFAULT_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  equal(chan.getTRRMode(), Ci.nsIRequest.TRR_DEFAULT_MODE);
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DISABLED_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  equal(chan.getTRRMode(), Ci.nsIRequest.TRR_DISABLED_MODE);
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_FIRST_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  equal(chan.getTRRMode(), Ci.nsIRequest.TRR_FIRST_MODE);
+  dns.clearCache(true);
+  chan = makeChan(
+    `http://example.com:${httpserv.identity.primaryPort}/`,
+    Ci.nsIRequest.TRR_ONLY_MODE
+  );
+  // Should fail as it tries to connect to local but unavailable IP
+  await new Promise(resolve =>
+    chan.asyncOpen(new ChannelListener(resolve, null, CL_EXPECT_FAILURE))
+  );
+  equal(chan.getTRRMode(), Ci.nsIRequest.TRR_ONLY_MODE);
+
+  dns.clearCache(true);
+  Services.prefs.setCharPref(
+    "network.trr.uri",
+    `https://localhost:${h2Port}/doh?responseIP=127.9.2.9`
+  );
+  Services.prefs.setIntPref("network.trr.mode", 2);
+
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DEFAULT_MODE);
+  // Does get the IP from TRR, but failure means it falls back to DNS.
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DISABLED_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  // Does get the IP from TRR, but failure means it falls back to DNS.
+  chan = makeChan(URL, Ci.nsIRequest.TRR_FIRST_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_ONLY_MODE);
+  await new Promise(resolve =>
+    chan.asyncOpen(new ChannelListener(resolve, null, CL_EXPECT_FAILURE))
+  );
+
+  dns.clearCache(true);
+  Services.prefs.setCharPref(
+    "network.trr.uri",
+    `https://localhost:${h2Port}/doh?responseIP=127.9.3.9`
+  );
+  Services.prefs.setIntPref("network.trr.mode", 3);
+
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DEFAULT_MODE);
+  await new Promise(resolve =>
+    chan.asyncOpen(new ChannelListener(resolve, null, CL_EXPECT_FAILURE))
+  );
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DISABLED_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_FIRST_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_ONLY_MODE);
+  await new Promise(resolve =>
+    chan.asyncOpen(new ChannelListener(resolve, null, CL_EXPECT_FAILURE))
+  );
+
+  dns.clearCache(true);
+  Services.prefs.setIntPref("network.trr.mode", 5);
+  Services.prefs.setCharPref(
+    "network.trr.uri",
+    `https://localhost:${h2Port}/doh?responseIP=1.1.1.1`
+  );
+
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DEFAULT_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_DISABLED_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_FIRST_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+  dns.clearCache(true);
+  chan = makeChan(URL, Ci.nsIRequest.TRR_ONLY_MODE);
+  await new Promise(resolve => chan.asyncOpen(new ChannelListener(resolve)));
+
+  await new Promise(resolve => httpserv.stop(resolve));
+});
+
 // verify basic A record
 add_task(async function test1() {
   dns.clearCache(true);
   Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first
   Services.prefs.setCharPref(
     "network.trr.uri",
     `https://foo.example.com:${h2Port}/doh?responseIP=2.2.2.2`
   );
@@ -1004,19 +1123,19 @@ add_task(async function test_connection_
   Assert.ok(
     !Components.isSuccessCode(inStatus),
     `${inStatus} should be an error code`
   );
   await new DNSListener("bar2.example.com", "3.3.3.3");
 });
 
 add_task(async function test_connection_closed_no_bootstrap_no_excluded() {
-  // This test exists to document what happens when we're in TRR only mode
-  // and we don't set a bootstrap address. We use DNS to resolve the
-  // initial URI, but if the connection fails, we don't fallback to DNS
+  // This test makes sure that even in mode 3 without a bootstrap address
+  // we are able to restart the TRR connection if it drops - the TRR service
+  // channel will use regular DNS to resolve the TRR address.
   dns.clearCache(true);
   Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
   Services.prefs.setCharPref("network.trr.excluded-domains", "");
   Services.prefs.setCharPref("network.trr.builtin-excluded-domains", "");
   Services.prefs.setCharPref(
     "network.trr.uri",
     `https://localhost:${h2Port}/doh?responseIP=3.3.3.3`
   );
@@ -1026,21 +1145,18 @@ add_task(async function test_connection_
   await new DNSListener("bar.example.com", "3.3.3.3");
 
   // makes the TRR connection shut down.
   let [, , inStatus] = await new DNSListener("closeme.com", undefined, false);
   Assert.ok(
     !Components.isSuccessCode(inStatus),
     `${inStatus} should be an error code`
   );
-  [, , inStatus] = await new DNSListener("bar2.example.com", undefined, false);
-  Assert.ok(
-    !Components.isSuccessCode(inStatus),
-    `${inStatus} should be an error code`
-  );
+  dns.clearCache(true);
+  await new DNSListener("bar2.example.com", "3.3.3.3");
 });
 
 add_task(async function test_connection_closed_trr_first() {
   // This test exists to document what happens when we're in TRR only mode
   // and we don't set a bootstrap address. We use DNS to resolve the
   // initial URI, but if the connection fails, we don't fallback to DNS
   dns.clearCache(true);
   Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first