Backed out 3 changesets (bug 1540656) for xpcshell failures on test_immutable.js. CLOSED TREE
authorCosmin Sabou <csabou@mozilla.com>
Thu, 04 Apr 2019 13:34:35 +0300
changeset 467950 9ce75ad03d72e70dce19997f4822bbc8dc5522f3
parent 467949 58a240bea3cfbfe088f4bdf5ca9bce8e14c0517c
child 467951 b147830dc59ed33e2cf9973e211e8547590807d3
push id35813
push useraiakab@mozilla.com
push dateThu, 04 Apr 2019 16:07:30 +0000
treeherdermozilla-central@aa623df2ae8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1540656
milestone68.0a1
backs out70a90b960aef224ca2b85718e534e7a9b8c1e5f1
631a1aae6fb0038e9f1b4b56ebf7db0e99786f07
408104f784ef610f7d1b9f12edc114fa799465ca
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
Backed out 3 changesets (bug 1540656) for xpcshell failures on test_immutable.js. CLOSED TREE Backed out changeset 70a90b960aef (bug 1540656) Backed out changeset 631a1aae6fb0 (bug 1540656) Backed out changeset 408104f784ef (bug 1540656)
.eslintignore
netwerk/test/unit/test_trr.js
testing/xpcshell/dns-packet/.editorconfig
testing/xpcshell/dns-packet/.eslintrc
testing/xpcshell/dns-packet/.gitignore
testing/xpcshell/dns-packet/.travis.yml
testing/xpcshell/dns-packet/CHANGELOG.md
testing/xpcshell/dns-packet/LICENSE
testing/xpcshell/dns-packet/README.md
testing/xpcshell/dns-packet/classes.js
testing/xpcshell/dns-packet/examples/doh.js
testing/xpcshell/dns-packet/examples/tcp.js
testing/xpcshell/dns-packet/examples/tls.js
testing/xpcshell/dns-packet/examples/udp.js
testing/xpcshell/dns-packet/index.js
testing/xpcshell/dns-packet/opcodes.js
testing/xpcshell/dns-packet/optioncodes.js
testing/xpcshell/dns-packet/package.json
testing/xpcshell/dns-packet/rcodes.js
testing/xpcshell/dns-packet/test.js
testing/xpcshell/dns-packet/types.js
testing/xpcshell/moz-http2/moz-http2.js
testing/xpcshell/node-ip/.gitignore
testing/xpcshell/node-ip/.jscsrc
testing/xpcshell/node-ip/.jshintrc
testing/xpcshell/node-ip/.travis.yml
testing/xpcshell/node-ip/README.md
testing/xpcshell/node-ip/lib/ip.js
testing/xpcshell/node-ip/package.json
testing/xpcshell/node-ip/test/api-test.js
tools/rewriting/ThirdPartyPaths.txt
--- a/.eslintignore
+++ b/.eslintignore
@@ -327,19 +327,16 @@ testing/talos/talos/tests/kraken/**
 # Runing Talos may extract data here, see bug 1435677.
 testing/talos/talos/tests/tp5n/**
 # Raptor third party
 testing/raptor/raptor/playback/scripts/catapult/**
 
 testing/web-platform/**
 testing/xpcshell/moz-http2/**
 testing/xpcshell/node-http2/**
-testing/xpcshell/dns-packet/**
-testing/xpcshell/node-ip/**
-
 
 # Third party services
 services/common/kinto-http-client.js
 services/common/kinto-offline-client.js
 
 # toolkit/ exclusions
 
 # Intentionally invalid JS
--- a/netwerk/test/unit/test_trr.js
+++ b/netwerk/test/unit/test_trr.js
@@ -1,445 +1,581 @@
-"use strict";
+Cu.import("resource://gre/modules/NetUtil.jsm");
 
-const {NetUtil} = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+var prefs;
+var origin;
+var h2Port;
 
-const dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
-const mainThread = Services.tm.currentThread;
+var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
+var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
+var mainThread = threadManager.currentThread;
 
 const defaultOriginAttributes = {};
-let h2Port = null;
 
-add_task(function setup() {
-  dump("start!\n");
+function run_test() {
+  dump ("start!\n");
 
-  let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
+  var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
   h2Port = env.get("MOZHTTP2_PORT");
   Assert.notEqual(h2Port, null);
   Assert.notEqual(h2Port, "");
 
   // Set to allow the cert presented by our H2 server
   do_get_profile();
+  prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
 
-  Services.prefs.setBoolPref("network.http.spdy.enabled", true);
-  Services.prefs.setBoolPref("network.http.spdy.enabled.http2", true);
+  prefs.setBoolPref("network.http.spdy.enabled", true);
+  prefs.setBoolPref("network.http.spdy.enabled.http2", true);
   // the TRR server is on 127.0.0.1
-  Services.prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
+  prefs.setCharPref("network.trr.bootstrapAddress", "127.0.0.1");
 
   // use the h2 server as DOH provider
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns`);
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns");
   // make all native resolve calls "secretly" resolve localhost instead
-  Services.prefs.setBoolPref("network.dns.native-is-localhost", true);
+  prefs.setBoolPref("network.dns.native-is-localhost", true);
 
   // 0 - off, 1 - race, 2 TRR first, 3 TRR only, 4 shadow
-  Services.prefs.setIntPref("network.trr.mode", 2); // TRR first
-  Services.prefs.setBoolPref("network.trr.wait-for-portal", false);
+  prefs.setIntPref("network.trr.mode", 2); // TRR first
+  prefs.setBoolPref("network.trr.wait-for-portal", false);
   // don't confirm that TRR is working, just go!
-  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
+  prefs.setCharPref("network.trr.confirmationNS", "skip");
 
   // The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem
   // so add that cert to the trust list as a signing cert.  // the foo.example.com domain name.
   let certdb = Cc["@mozilla.org/security/x509certdb;1"]
       .getService(Ci.nsIX509CertDB);
   addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
-});
+  do_test_pending();
+  run_dns_tests();
+}
+
+function resetTRRPrefs() {
+  prefs.clearUserPref("network.trr.mode");
+  prefs.clearUserPref("network.trr.uri");
+  prefs.clearUserPref("network.trr.credentials");
+  prefs.clearUserPref("network.trr.wait-for-portal");
+  prefs.clearUserPref("network.trr.allow-rfc1918");
+  prefs.clearUserPref("network.trr.useGET");
+  prefs.clearUserPref("network.trr.confirmationNS");
+  prefs.clearUserPref("network.trr.bootstrapAddress");
+  prefs.clearUserPref("network.trr.blacklist-duration");
+  prefs.clearUserPref("network.trr.request-timeout");
+  prefs.clearUserPref("network.trr.disable-ECS");
+}
 
 registerCleanupFunction(() => {
-  Services.prefs.clearUserPref("network.trr.mode");
-  Services.prefs.clearUserPref("network.trr.uri");
-  Services.prefs.clearUserPref("network.trr.credentials");
-  Services.prefs.clearUserPref("network.trr.wait-for-portal");
-  Services.prefs.clearUserPref("network.trr.allow-rfc1918");
-  Services.prefs.clearUserPref("network.trr.useGET");
-  Services.prefs.clearUserPref("network.trr.confirmationNS");
-  Services.prefs.clearUserPref("network.trr.bootstrapAddress");
-  Services.prefs.clearUserPref("network.trr.blacklist-duration");
-  Services.prefs.clearUserPref("network.trr.request-timeout");
-  Services.prefs.clearUserPref("network.trr.disable-ECS");
-  Services.prefs.clearUserPref("network.trr.excluded-domains");
-
-  Services.prefs.clearUserPref("network.http.spdy.enabled");
-  Services.prefs.clearUserPref("network.http.spdy.enabled.http2");
-  Services.prefs.clearUserPref("network.dns.localDomains");
-  Services.prefs.clearUserPref("network.dns.native-is-localhost");
+  prefs.clearUserPref("network.http.spdy.enabled");
+  prefs.clearUserPref("network.http.spdy.enabled.http2");
+  prefs.clearUserPref("network.dns.localDomains");
+  prefs.clearUserPref("network.dns.native-is-localhost");
+  resetTRRPrefs();
 });
 
-class DNSListener {
-  constructor(name, expectedAnswer, expectedSuccess = true) {
-    this.name = name;
-    this.expectedAnswer = expectedAnswer;
-    this.expectedSuccess = expectedSuccess;
-    this.promise = new Promise(resolve => { this.resolve = resolve; });
-    this.request = dns.asyncResolve(name, 0, this, mainThread, defaultOriginAttributes);
+function testsDone()
+{
+  do_test_finished();
+  do_test_finished();
+}
+
+var test_loops;
+var test_answer="127.0.0.1";
+
+// check that we do lookup the name fine
+var listenerFine = {
+  onLookupComplete: function(inRequest, inRecord, inStatus) {
+    if (inRequest == listen) {
+      Assert.equal(inStatus, Cr.NS_OK);
+      var answer = inRecord.getNextAddrAsString();
+      Assert.equal(answer, test_answer);
+      do_test_finished();
+      run_dns_tests();
+    }
+  },
+  QueryInterface: function(aIID) {
+    if (aIID.equals(Ci.nsIDNSListener) ||
+        aIID.equals(Ci.nsISupports)) {
+      return this;
+    }
+    throw Cr.NS_ERROR_NO_INTERFACE;
   }
-
-  onLookupComplete(inRequest, inRecord, inStatus) {
-    Assert.ok(inRequest == this.request);
+};
 
-    // If we don't expect success here, just resolve and the caller will
-    // decide what to do with the results.
-    if (!this.expectedSuccess) {
-      this.resolve([inRequest, inRecord, inStatus]);
-      return;
+// check that the name lookup fails
+var listenerFails = {
+  onLookupComplete: function(inRequest, inRecord, inStatus) {
+    if (inRequest == listen) {
+      Assert.ok(!Components.isSuccessCode(inStatus), `must be failure code: ${inStatus}`);
+      do_test_finished();
+      run_dns_tests();
     }
+  },
+  QueryInterface: function(aIID) {
+    if (aIID.equals(Ci.nsIDNSListener) ||
+        aIID.equals(Ci.nsISupports)) {
+      return this;
+    }
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  }
+};
 
-    Assert.equal(inStatus, Cr.NS_OK);
-    let answer = inRecord.getNextAddrAsString();
-    Assert.equal(answer, this.expectedAnswer);
-    this.resolve([inRequest, inRecord, inStatus]);
-  }
-
-  QueryInterface(aIID) {
+// check that we do lookup the name fine
+var listenerUntilFine = {
+  onLookupComplete: function(inRequest, inRecord, inStatus) {
+    if ((inRequest == listen) && (inRecord != null)) {
+      var answer = inRecord.getNextAddrAsString();
+      if (answer == test_answer) {
+        Assert.equal(answer, test_answer);
+        dump("Got what we were waiting for!\n");
+      }
+    }
+    else {
+      // not the one we want, try again
+      dump("Waiting for " + test_answer + " but got " + answer + "\n");
+      --test_loops;
+      Assert.ok(test_loops != 0);
+      current_test--;
+    }
+    do_test_finished();
+    run_dns_tests();
+  },
+  QueryInterface: function(aIID) {
     if (aIID.equals(Ci.nsIDNSListener) ||
         aIID.equals(Ci.nsISupports)) {
       return this;
     }
     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);
-  }
-}
-
+var listen;
 
 // verify basic A record
-add_task(async function test1() {
+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`);
-
-  await new DNSListener("bar.example.com", "2.2.2.2");
-});
+  prefs.setIntPref("network.trr.mode", 2); // TRR-first
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns");
+  test_answer="127.0.0.1";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // verify basic A record - without bootstrapping
-add_task(async function test1b() {
+function test1b()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=3.3.3.3`);
-  Services.prefs.clearUserPref("network.trr.bootstrapAddress");
-  Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
-
-  await new DNSListener("bar.example.com", "3.3.3.3");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns");
+  prefs.clearUserPref("network.trr.bootstrapAddress");
+  prefs.setCharPref("network.dns.localDomains", "foo.example.com");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // verify that the name was put in cache - it works with bad DNS URI
-add_task(async function test2() {
+function test2()
+{
   // Don't clear the cache. That is what we're checking.
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`);
-
-  await new DNSListener("bar.example.com", "3.3.3.3");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  //prefs.clearUserPref("network.trr.bootstrapAddress");
+  //prefs.setCharPref("network.dns.localDomains", "foo.example.com");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // verify working credentials in DOH request
-add_task(async function test3() {
+function test3()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=4.4.4.4&auth=true`);
-  Services.prefs.setCharPref("network.trr.credentials", "user:password");
-
-  await new DNSListener("bar.example.com", "4.4.4.4");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-auth");
+  prefs.setCharPref("network.trr.credentials", "user:password");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // verify failing credentials in DOH request
-add_task(async function test4() {
+function test4()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=4.4.4.4&auth=true`);
-  Services.prefs.setCharPref("network.trr.credentials", "evil:person");
-
-  let [, , inStatus] = await new DNSListener("wrong.example.com", undefined, false);
-  Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`);
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-auth");
+  prefs.setCharPref("network.trr.credentials", "evil:person");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("wrong.example.com", 0, listenerFails, mainThread, defaultOriginAttributes);
+}
 
 // verify DOH push, part A
-add_task(async function test5() {
+function test5()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=5.5.5.5&push=true`);
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-push");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("first.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
-  await new DNSListener("first.example.com", "5.5.5.5");
-});
-
-add_task(async function test5b() {
+function test5b()
+{
   // At this point the second host name should've been pushed and we can resolve it using
   // cache only. Set back the URI to a path that fails.
   // Don't clear the cache, otherwise we lose the pushed record.
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`);
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404");
   dump("test5b - resolve push.example.now please\n");
-
-  await new DNSListener("push.example.com", "2018::2018");
-});
+  test_answer = "2018::2018";
+  listen = dns.asyncResolve("push.example.com", 0, listenerUntilFine, mainThread, defaultOriginAttributes);
+}
 
 // verify AAAA entry
-add_task(async function test6() {
+function test6()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=2020:2020::2020`);
-  await new DNSListener("aaaa.example.com", "2020:2020::2020");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-aaaa");
+  test_answer = "2020:2020::2020";
+  listen = dns.asyncResolve("aaaa.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // verify RFC1918 address from the server is rejected
-add_task(async function test7() {
+function test7()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.168.0.1`);
-  let [, , inStatus] = await new DNSListener("rfc1918.example.com", undefined, false);
-  Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`);
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-rfc1918");
+  listen = dns.asyncResolve("rfc1918.example.com", 0, listenerFails, mainThread, defaultOriginAttributes);
+}
 
 // verify RFC1918 address from the server is fine when told so
-add_task(async function test8() {
+function test8()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.168.0.1`);
-  Services.prefs.setBoolPref("network.trr.allow-rfc1918", true);
-  await new DNSListener("rfc1918.example.com", "192.168.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-rfc1918");
+  prefs.setBoolPref("network.trr.allow-rfc1918", true);
+  test_answer = "192.168.0.1";
+  listen = dns.asyncResolve("rfc1918.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // use GET and disable ECS (makes a larger request)
 // verify URI template cutoff
-add_task(async function test8b() {
+function test8b()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh{?dns}`);
-  Services.prefs.clearUserPref("network.trr.allow-rfc1918");
-  Services.prefs.setBoolPref("network.trr.useGET", true);
-  Services.prefs.setBoolPref("network.trr.disable-ECS", true);
-  await new DNSListener("ecs.example.com", "5.5.5.5");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ecs{?dns}");
+  prefs.clearUserPref("network.trr.allow-rfc1918");
+  prefs.setBoolPref("network.trr.useGET", true);
+  prefs.setBoolPref("network.trr.disable-ECS", true);
+  test_answer = "5.5.5.5";
+  listen = dns.asyncResolve("ecs.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // use GET
-add_task(async function test9() {
+function test9()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh`);
-  Services.prefs.clearUserPref("network.trr.allow-rfc1918");
-  Services.prefs.setBoolPref("network.trr.useGET", true);
-  Services.prefs.setBoolPref("network.trr.disable-ECS", false);
-  await new DNSListener("get.example.com", "5.5.5.5");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-get");
+  prefs.clearUserPref("network.trr.allow-rfc1918");
+  prefs.setBoolPref("network.trr.useGET", true);
+  prefs.setBoolPref("network.trr.disable-ECS", false);
+  test_answer = "1.2.3.4";
+  listen = dns.asyncResolve("get.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // confirmationNS set without confirmed NS yet
 // NOTE: this requires test9 to run before, as the http2 server resets state there
-add_task(async function test10() {
+function test10()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.clearUserPref("network.trr.useGET");
-  Services.prefs.clearUserPref("network.trr.disable-ECS");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-confirm`);
-  Services.prefs.setCharPref("network.trr.confirmationNS", "confirm.example.com");
-
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.clearUserPref("network.trr.useGET");
+  prefs.clearUserPref("network.trr.disable-ECS");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-confirm");
+  prefs.setCharPref("network.trr.confirmationNS", "confirm.example.com");
+  test_loops = 100; // set for test10b
   try {
-    let [, , inStatus] = await new DNSListener("wrong.example.com", undefined, false);
-    Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`);
+    listen = dns.asyncResolve("wrong.example.com", 0, listenerFails,
+                              mainThread, defaultOriginAttributes);
   } catch (e) {
-    await new Promise(resolve => do_timeout(200, resolve));
+    // NS_ERROR_UNKNOWN_HOST exception is expected
+    do_test_finished();
+    do_timeout(200, run_dns_tests);
+    //run_dns_tests();
   }
-});
+}
 
 // confirmationNS, retry until the confirmed NS works
-add_task(async function test10b() {
+function test10b()
+{
   dns.clearCache(true);
-  let test_loops = 100;
   print("test confirmationNS, retry until the confirmed NS works");
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
   // same URI as in test10
-
-  // this test needs to resolve new names in every attempt since the DNS
+  test_answer = "1::ffff"
+  // this test needs to resolve new names in every attempt since the DNS cache
   // will keep the negative resolved info
-  while (test_loops > 0) {
-    print(`loops remaining: ${test_loops}`);
-    try {
-      let [, inRecord, inStatus] = await new DNSListener(`10b-${test_loops}.example.com`, undefined, false);
-      if (inRecord) {
-        Assert.equal(inStatus, Cr.NS_OK);
-        break;
-      }
-    } catch (e) {
-      dump(e);
-    }
-
+  try {
+    listen = dns.asyncResolve("10b-" + test_loops + ".example.com", 0, listenerUntilFine,
+                              mainThread, defaultOriginAttributes);
+  } catch(e) {
+    // wait a while and try again
     test_loops--;
-    await new Promise(resolve => do_timeout(0, resolve));
+    do_timeout(200, test10b);
   }
-  Assert.notEqual(test_loops, 0);
-});
-
+}
 // use a slow server and short timeout!
-add_task(async function test11() {
+function test11()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.confirmationNS", "skip");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-750ms`);
-  Services.prefs.setIntPref("network.trr.request-timeout", 10);
-  let [, , inStatus] = await new DNSListener("test11.example.com", undefined, false);
-  Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`);
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.confirmationNS", "skip");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-750ms");
+  prefs.setIntPref("network.trr.request-timeout", 10);
+  listen = dns.asyncResolve("test11.example.com", 0, listenerFails, mainThread, defaultOriginAttributes);
+}
 
 // gets an NS back from DOH
-add_task(async function test12() {
+function test12()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-ns`);
-  Services.prefs.clearUserPref("network.trr.request-timeout");
-  await new DNSListener("test12.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 2); // TRR-first
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ns");
+  prefs.clearUserPref("network.trr.request-timeout");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test12.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-first gets a 404 back from DOH
-add_task(async function test13() {
+function test13()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`);
-  await new DNSListener("test13.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 2); // TRR-first
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test13.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-shadow gets a 404 back from DOH
-add_task(async function test14() {
+function test14()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 4); // TRR-shadow
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/404`);
-  await new DNSListener("test14.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 4); // TRR-shadow
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/404");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test14.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-shadow and timed out TRR
-add_task(async function test15() {
+function test15()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 4); // TRR-shadow
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-750ms`);
-  Services.prefs.setIntPref("network.trr.request-timeout", 10);
-  await new DNSListener("test15.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 4); // TRR-shadow
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-750ms");
+  prefs.setIntPref("network.trr.request-timeout", 10);
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test15.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-first and timed out TRR
-add_task(async function test16() {
+function test16()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-750ms`);
-  Services.prefs.setIntPref("network.trr.request-timeout", 10);
-  await new DNSListener("test16.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 2); // TRR-first
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-750ms");
+  prefs.setIntPref("network.trr.request-timeout", 10);
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test16.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-only and chase CNAME
-add_task(async function test17() {
+function test17()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname`);
-  Services.prefs.clearUserPref("network.trr.request-timeout");
-  await new DNSListener("cname.example.com", "99.88.77.66");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname");
+  prefs.clearUserPref("network.trr.request-timeout");
+  test_answer = "99.88.77.66";
+  listen = dns.asyncResolve("cname.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-only and a CNAME loop
-add_task(async function test18() {
+function test18()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`);
-  let [, , inStatus] = await new DNSListener("test18.example.com", undefined, false);
-  Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`);
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop");
+  listen = dns.asyncResolve("test18.example.com", 0, listenerFails, mainThread, defaultOriginAttributes);
+}
 
 // TRR-race and a CNAME loop
-add_task(async function test19() {
+function test19()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 1); // Race them!
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`);
-  await new DNSListener("test19.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 1); // Race them!
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test19.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-first and a CNAME loop
-add_task(async function test20() {
+function test20()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`);
-  await new DNSListener("test20.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 2); // TRR-first
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test20.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-shadow and a CNAME loop
-add_task(async function test21() {
+function test21()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 4); // shadow
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-loop`);
-  await new DNSListener("test21.example.com", "127.0.0.1");
-});
+  prefs.setIntPref("network.trr.mode", 4); // shadow
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-loop");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test21.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
-// verify that basic A record name mismatch gets rejected.
-// Gets a response for bar.example.com instead of what it requested
-add_task(async function test22() {
+// verify that basic A record name mismatch gets rejected. Gets the same DOH
+// response back as test1
+function test22()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only to avoid native fallback
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns`);
-  let [, , inStatus] = await new DNSListener("mismatch.example.com", undefined, false);
-  Assert.ok(!Components.isSuccessCode(inStatus), `${inStatus} should be an error code`);
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only to avoid native fallback
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns");
+  listen = dns.asyncResolve("mismatch.example.com", 0, listenerFails, mainThread, defaultOriginAttributes);
+}
 
 // TRR-only, with a CNAME response with a bundled A record for that CNAME!
-add_task(async function test23() {
+function test23()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/dns-cname-a`);
-  await new DNSListener("cname-a.example.com", "9.8.7.6");
-});
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-cname-a");
+  test_answer = "9.8.7.6";
+  listen = dns.asyncResolve("cname-a.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-first check that TRR result is used
-add_task(async function test24() {
+function test24()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 2); // TRR-first
-  Services.prefs.setCharPref("network.trr.excluded-domains", "");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`);
-  await new DNSListener("bar.example.com", "192.192.192.192");
-});
+  prefs.setIntPref("network.trr.mode", 2); // TRR-first
+  prefs.setCharPref("network.trr.excluded-domains", "");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
+  test_answer = "192.192.192.192";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-first check that DNS result is used if domain is part of the excluded-domains pref
-add_task(async function test24b() {
+function test24b()
+{
   dns.clearCache(true);
-  Services.prefs.setCharPref("network.trr.excluded-domains", "bar.example.com");
-  await new DNSListener("bar.example.com", "127.0.0.1");
-});
+  prefs.setCharPref("network.trr.excluded-domains", "bar.example.com");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-first check that DNS result is used if domain is part of the excluded-domains pref
-add_task(async function test24c() {
+function test24c()
+{
   dns.clearCache(true);
-  Services.prefs.setCharPref("network.trr.excluded-domains", "example.com");
-  await new DNSListener("bar.example.com", "127.0.0.1");
-});
+  prefs.setCharPref("network.trr.excluded-domains", "example.com");
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("bar.example.com", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
-// TRR-only that resolving localhost with TRR-only mode will use the remote
-// resolver if it's not in the excluded domains
-add_task(async function test25() {
+// TRR-only check that localhost doesn't work if not in the excluded-domains list
+function test25()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.excluded-domains", "");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`);
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.excluded-domains", "");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
 
-  await new DNSListener("localhost", "192.192.192.192", true);
-});
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("localhost", 0, listenerFails, mainThread, defaultOriginAttributes);
+}
 
-// TRR-only check that localhost goes directly to native lookup when in the excluded-domains
-add_task(async function test25b() {
+// TRR-only check that localhost goes directly to native lookup when in the excluded-domains 
+function test25b()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.excluded-domains", "localhost");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`);
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.excluded-domains", "localhost");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
 
-  await new DNSListener("localhost", "127.0.0.1");
-});
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("localhost", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
 // TRR-only check that test.local is resolved via native DNS
-add_task(async function test25c() {
+function test25c()
+{
   dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.excluded-domains", "localhost,local");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`);
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.excluded-domains", "localhost,local");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
+
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("test.local", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
-  await new DNSListener("test.local", "127.0.0.1");
-});
+function test25d()
+{
+  dns.clearCache(true);
+  prefs.setIntPref("network.trr.mode", 3); // TRR-only
+  prefs.setCharPref("network.trr.excluded-domains", "localhost,local,other");
+  prefs.setCharPref("network.trr.uri", "https://foo.example.com:" + h2Port + "/dns-ip");
+
+  test_answer = "127.0.0.1";
+  listen = dns.asyncResolve("domain.other", 0, listenerFine, mainThread, defaultOriginAttributes);
+}
 
-// TRR-only check that .other is resolved via native DNS when the pref is set
-add_task(async function test25d() {
-  dns.clearCache(true);
-  Services.prefs.setIntPref("network.trr.mode", 3); // TRR-only
-  Services.prefs.setCharPref("network.trr.excluded-domains", "localhost,local,other");
-  Services.prefs.setCharPref("network.trr.uri", `https://foo.example.com:${h2Port}/doh?responseIP=192.192.192.192`);
+var tests = [ test1,
+              test1b,
+              test2,
+              test3,
+              test4,
+              test5,
+              test5b,
+              test6,
+              test7,
+              test8,
+              test8b,
+              test9,
+              test10,
+              test10b,
+              test11,
+              test12,
+              test13,
+              test14,
+              test15,
+              test16,
+              test17,
+              test18,
+              test19,
+              test20,
+              test21,
+              test22,
+              test23,
+              test24,
+              test24b,
+              test24c,
+              test25,
+              test25b,
+              test25c,
+              test25d,
+              testsDone
+            ];
 
-  await new DNSListener("domain.other", "127.0.0.1");
-});
+var current_test = 0;
+
+function run_dns_tests()
+{
+  if (current_test < tests.length) {
+    dump(`starting test ${tests[current_test].name}`);
+    do_test_pending();
+    tests[current_test++]();
+  }
+}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/.editorconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-root = true
-
-[*]
-indent_style = space
-indent_size = 2
-tab_width = 2
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/.eslintrc
+++ /dev/null
@@ -1,9 +0,0 @@
-root: true
-
-parserOptions:
-  ecmaVersion: 2015
-
-env:
-  node: true
-
-extends: standard
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-node_modules/
-.nyc_output/
-coverage/
-package-lock.json
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/.travis.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-language: node_js
-node_js:
-  - node
-  - lts/*
-install:
-- npm install
-- npm install coveralls
-script:
-- npm run coverage
-after_success:
-- npx nyc report --reporter=text-lcov | npx coveralls
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/CHANGELOG.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Version 5.2.0 - 2019-02-21
-
-- Feature: Added support for de/encoding certain OPT options.
-
-# Version 5.1.0 - 2019-01-22
-
-- Feature: Added support for the RP record type.
-
-# Version 5.0.0 - 2018-06-01
-
-- Breaking: Node.js 6.0.0 or greater is now required.
-- Feature: Added support for DNSSEC record types.
-
-# Version 4.1.0 - 2018-02-11
-
-- Feature: Added support for the MX record type.
-
-# Version 4.0.0 - 2018-02-04
-
-- Feature: Added `streamEncode` and `streamDecode` methods for encoding TCP packets.
-- Breaking: Changed the decoded value of TXT records to an array of Buffers. This is to accomodate DNS-SD records which rely on the individual strings record being separated.
-- Breaking: Renamed the `flag_trunc` and `flag_auth` to `flag_tc` and `flag_aa` to match the names of these in the dns standards.
-
-# Version 3.0.0 - 2018-01-12
-
-- Breaking: The `class` option has been changed from integer to string.
-
-# Version 2.0.0 - 2018-01-11
-
-- Breaking: Converted module to ES2015, now requires Node.js 4.0 or greater
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2016 Mathias Buus
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/README.md
+++ /dev/null
@@ -1,365 +0,0 @@
-# dns-packet
-[![](https://img.shields.io/npm/v/dns-packet.svg?style=flat)](https://www.npmjs.org/package/dns-packet) [![](https://img.shields.io/npm/dm/dns-packet.svg)](https://www.npmjs.org/package/dns-packet) [![](https://api.travis-ci.org/mafintosh/dns-packet.svg?style=flat)](https://travis-ci.org/mafintosh/dns-packet) [![Coverage Status](https://coveralls.io/repos/github/mafintosh/dns-packet/badge.svg?branch=master)](https://coveralls.io/github/mafintosh/dns-packet?branch=master)
-
-An [abstract-encoding](https://github.com/mafintosh/abstract-encoding) compliant module for encoding / decoding DNS packets. Lifted out of [multicast-dns](https://github.com/mafintosh/multicast-dns) as a separate module.
-
-```
-npm install dns-packet
-```
-
-## UDP Usage
-
-``` js
-const dnsPacket = require('dns-packet')
-const dgram = require('dgram')
-
-const socket = dgram.createSocket('udp4')
-
-const buf = dnsPacket.encode({
-  type: 'query',
-  id: 1,
-  flags: dnsPacket.RECURSION_DESIRED,
-  questions: [{
-    type: 'A',
-    name: 'google.com'
-  }]
-})
-
-socket.on('message', message => {
-  console.log(dnsPacket.decode(message)) // prints out a response from google dns
-})
-
-socket.send(buf, 0, buf.length, 53, '8.8.8.8')
-```
-
-Also see [the UDP example](examples/udp.js).
-
-## TCP, TLS, HTTPS
-
-While DNS has traditionally been used over a datagram transport, it is increasingly being carried over TCP for larger responses commonly including DNSSEC responses and TLS or HTTPS for enhanced security. See below examples on how to use `dns-packet` to wrap DNS packets in these protocols:
-
-- [TCP](examples/tcp.js)
-- [DNS over TLS](examples/tls.js)
-- [DNS over HTTPS](examples/doh.js)
-
-## API
-
-#### `var buf = packets.encode(packet, [buf], [offset])`
-
-Encodes a DNS packet into a buffer containing a UDP payload.
-
-#### `var packet = packets.decode(buf, [offset])`
-
-Decode a DNS packet from a buffer containing a UDP payload.
-
-#### `var buf = packets.streamEncode(packet, [buf], [offset])`
-
-Encodes a DNS packet into a buffer containing a TCP payload.
-
-#### `var packet = packets.streamDecode(buf, [offset])`
-
-Decode a DNS packet from a buffer containing a TCP payload.
-
-#### `var len = packets.encodingLength(packet)`
-
-Returns how many bytes are needed to encode the DNS packet
-
-## Packets
-
-Packets look like this
-
-``` js
-{
-  type: 'query|response',
-  id: optionalIdNumber,
-  flags: optionalBitFlags,
-  questions: [...],
-  answers: [...],
-  additionals: [...],
-  authorities: [...]
-}
-```
-
-The bit flags available are
-
-``` js
-packet.RECURSION_DESIRED
-packet.RECURSION_AVAILABLE
-packet.TRUNCATED_RESPONSE
-packet.AUTHORITATIVE_ANSWER
-packet.AUTHENTIC_DATA
-packet.CHECKING_DISABLED
-```
-
-To use more than one flag bitwise-or them together
-
-``` js
-var flags = packet.RECURSION_DESIRED | packet.RECURSION_AVAILABLE
-```
-
-And to check for a flag use bitwise-and
-
-``` js
-var isRecursive = message.flags & packet.RECURSION_DESIRED
-```
-
-A question looks like this
-
-``` js
-{
-  type: 'A', // or SRV, AAAA, etc
-  class: 'IN', // one of IN, CS, CH, HS, ANY. Default: IN
-  name: 'google.com' // which record are you looking for
-}
-```
-
-And an answer, additional, or authority looks like this
-
-``` js
-{
-  type: 'A', // or SRV, AAAA, etc
-  class: 'IN', // one of IN, CS, CH, HS
-  name: 'google.com', // which name is this record for
-  ttl: optionalTimeToLiveInSeconds,
-  (record specific data, see below)
-}
-```
-
-## Supported record types
-
-#### `A`
-
-``` js
-{
-  data: 'IPv4 address' // fx 127.0.0.1
-}
-```
-
-#### `AAAA`
-
-``` js
-{
-  data: 'IPv6 address' // fx fe80::1
-}
-```
-
-#### `CAA`
-
-``` js
-{
-  flags: 128, // octet
-  tag: 'issue|issuewild|iodef',
-  value: 'ca.example.net',
-  issuerCritical: false
-}
-```
-
-#### `CNAME`
-
-``` js
-{
-  data: 'cname.to.another.record'
-}
-```
-
-#### `DNAME`
-
-``` js
-{
-  data: 'dname.to.another.record'
-}
-```
-
-#### `DNSKEY`
-
-``` js
-{
-  flags: 257, // 16 bits
-  algorithm: 1, // octet
-  key: Buffer
-}
-```
-
-#### `DS`
-
-``` js
-{
-  keyTag: 12345,
-  algorithm: 8,
-  digestType: 1,
-  digest: Buffer
-}
-```
-
-#### `HINFO`
-
-``` js
-{
-  data: {
-    cpu: 'cpu info',
-    os: 'os info'
-  }
-}
-```
-
-#### `MX`
-
-``` js
-{
-  preference: 10,
-  exchange: 'mail.example.net'
-}
-```
-
-#### `NS`
-
-``` js
-{
-  data: nameServer
-}
-```
-
-#### `NSEC`
-
-``` js
-{
-  nextDomain: 'a.domain',
-  rrtypes: ['A', 'TXT', 'RRSIG']
-}
-```
-
-#### `NSEC3`
-
-``` js
-{
-  algorithm: 1,
-  flags: 0,
-  iterations: 2,
-  salt: Buffer,
-  nextDomain: Buffer, // Hashed per RFC5155
-  rrtypes: ['A', 'TXT', 'RRSIG']
-}
-```
-
-#### `NULL`
-
-``` js
-{
-  data: Buffer('any binary data')
-}
-```
-
-#### `OPT`
-
-[EDNS0](https://tools.ietf.org/html/rfc6891) options.
-
-``` js
-{
-  type: 'OPT',
-  name: '.',
-  udpPayloadSize: 4096,
-  flags: packet.DNSSEC_OK,
-  options: [{
-    // pass in any code/data for generic EDNS0 options
-    code: 12,
-    data: Buffer.alloc(31)
-  }, {
-    // Several EDNS0 options have enhanced support
-    code: 'PADDING',
-    length: 31,
-  }, {
-    code: 'CLIENT_SUBNET',
-    family: 2, // 1 for IPv4, 2 for IPv6
-    sourcePrefixLength: 64, // used to truncate IP address
-    scopePrefixLength: 0,
-    ip: 'fe80::',
-  }, {
-    code: 'TCP_KEEPALIVE',
-    timeout: 150 // increments of 100ms.  This means 15s.
-  }, {
-    code: 'KEY_TAG',
-    tags: [1, 2, 3],
-  }]
-}
-```
-
-The options `PADDING`, `CLIENT_SUBNET`, `TCP_KEEPALIVE` and `KEY_TAG` support enhanced de/encoding. See [optionscodes.js](https://github.com/mafintosh/dns-packet/blob/master/optioncodes.js) for all supported option codes. If the `data` property is present on a option, it takes precedence. On decoding, `data` will always be defined.
-
-#### `PTR`
-
-``` js
-{
-  data: 'points.to.another.record'
-}
-```
-
-#### `RP`
-
-``` js
-{
-  mbox: 'admin.example.com',
-  txt: 'txt.example.com'
-}
-```
-
-#### `RRSIG`
-
-``` js
-{
-  typeCovered: 'A',
-  algorithm: 8,
-  labels: 1,
-  originalTTL: 3600,
-  expiration: timestamp,
-  inception: timestamp,
-  keyTag: 12345,
-  signersName: 'a.name',
-  signature: Buffer
-}
-```
-
-#### `SOA`
-
-``` js
-{
-  data:
-    {
-      mname: domainName,
-      rname: mailbox,
-      serial: zoneSerial,
-      refresh: refreshInterval,
-      retry: retryInterval,
-      expire: expireInterval,
-      minimum: minimumTTL
-    }
-}
-```
-
-#### `SRV`
-
-``` js
-{
-  data: {
-    port: servicePort,
-    target: serviceHostName,
-    priority: optionalServicePriority,
-    weight: optionalServiceWeight
-  }
-}
-```
-
-#### `TXT`
-
-``` js
-{
-  data: 'text' || Buffer || [ Buffer || 'text' ]
-}
-```
-
-When encoding, scalar values are converted to an array and strings are converted to UTF-8 encoded Buffers. When decoding, the return value will always be an array of Buffer.
-
-If you need another record type, open an issue and we'll try to add it.
-
-## License
-
-MIT
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/classes.js
+++ /dev/null
@@ -1,23 +0,0 @@
-'use strict'
-
-exports.toString = function (klass) {
-  switch (klass) {
-    case 1: return 'IN'
-    case 2: return 'CS'
-    case 3: return 'CH'
-    case 4: return 'HS'
-    case 255: return 'ANY'
-  }
-  return 'UNKNOWN_' + klass
-}
-
-exports.toClass = function (name) {
-  switch (name.toUpperCase()) {
-    case 'IN': return 1
-    case 'CS': return 2
-    case 'CH': return 3
-    case 'HS': return 4
-    case 'ANY': return 255
-  }
-  return 0
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/examples/doh.js
+++ /dev/null
@@ -1,52 +0,0 @@
-
-'use strict'
-
-/*
- * Sample code to make DNS over HTTPS request using POST
- * AUTHOR: Tom Pusateri <pusateri@bangj.com>
- * DATE: March 17, 2018
- * LICENSE: MIT
- */
-
-const dnsPacket = require('..')
-const https = require('https')
-
-function getRandomInt (min, max) {
-  return Math.floor(Math.random() * (max - min + 1)) + min
-}
-
-const buf = dnsPacket.encode({
-  type: 'query',
-  id: getRandomInt(1, 65534),
-  flags: dnsPacket.RECURSION_DESIRED,
-  questions: [{
-    type: 'A',
-    name: 'google.com'
-  }]
-})
-
-const options = {
-  hostname: 'dns.google.com',
-  port: 443,
-  path: '/experimental',
-  method: 'POST',
-  headers: {
-    'Content-Type': 'application/dns-udpwireformat',
-    'Content-Length': Buffer.byteLength(buf)
-  }
-}
-
-const request = https.request(options, (response) => {
-  console.log('statusCode:', response.statusCode)
-  console.log('headers:', response.headers)
-
-  response.on('data', (d) => {
-    console.log(dnsPacket.decode(d))
-  })
-})
-
-request.on('error', (e) => {
-  console.error(e)
-})
-request.write(buf)
-request.end()
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/examples/tcp.js
+++ /dev/null
@@ -1,52 +0,0 @@
-'use strict'
-
-const dnsPacket = require('..')
-const net = require('net')
-
-var response = null
-var expectedLength = 0
-
-function getRandomInt (min, max) {
-  return Math.floor(Math.random() * (max - min + 1)) + min
-}
-
-const buf = dnsPacket.streamEncode({
-  type: 'query',
-  id: getRandomInt(1, 65534),
-  flags: dnsPacket.RECURSION_DESIRED,
-  questions: [{
-    type: 'A',
-    name: 'google.com'
-  }]
-})
-
-const client = new net.Socket()
-client.connect(53, '8.8.8.8', function () {
-  console.log('Connected')
-  client.write(buf)
-})
-
-client.on('data', function (data) {
-  console.log('Received response: %d bytes', data.byteLength)
-  if (response == null) {
-    if (data.byteLength > 1) {
-      const plen = data.readUInt16BE(0)
-      expectedLength = plen
-      if (plen < 12) {
-        throw new Error('below DNS minimum packet length')
-      }
-      response = Buffer.from(data)
-    }
-  } else {
-    response = Buffer.concat([response, data])
-  }
-
-  if (response.byteLength >= expectedLength) {
-    console.log(dnsPacket.streamDecode(response))
-    client.destroy()
-  }
-})
-
-client.on('close', function () {
-  console.log('Connection closed')
-})
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/examples/tls.js
+++ /dev/null
@@ -1,61 +0,0 @@
-'use strict'
-
-const tls = require('tls')
-const dnsPacket = require('..')
-
-var response = null
-var expectedLength = 0
-
-function getRandomInt (min, max) {
-  return Math.floor(Math.random() * (max - min + 1)) + min
-}
-
-const buf = dnsPacket.streamEncode({
-  type: 'query',
-  id: getRandomInt(1, 65534),
-  flags: dnsPacket.RECURSION_DESIRED,
-  questions: [{
-    type: 'A',
-    name: 'google.com'
-  }]
-})
-
-const context = tls.createSecureContext({
-  secureProtocol: 'TLSv1_2_method'
-})
-
-const options = {
-  port: 853,
-  host: 'getdnsapi.net',
-  secureContext: context
-}
-
-const client = tls.connect(options, () => {
-  console.log('client connected')
-  client.write(buf)
-})
-
-client.on('data', function (data) {
-  console.log('Received response: %d bytes', data.byteLength)
-  if (response == null) {
-    if (data.byteLength > 1) {
-      const plen = data.readUInt16BE(0)
-      expectedLength = plen
-      if (plen < 12) {
-        throw new Error('below DNS minimum packet length')
-      }
-      response = Buffer.from(data)
-    }
-  } else {
-    response = Buffer.concat([response, data])
-  }
-
-  if (response.byteLength >= expectedLength) {
-    console.log(dnsPacket.streamDecode(response))
-    client.destroy()
-  }
-})
-
-client.on('end', () => {
-  console.log('Connection ended')
-})
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/examples/udp.js
+++ /dev/null
@@ -1,28 +0,0 @@
-'use strict'
-
-const dnsPacket = require('..')
-const dgram = require('dgram')
-
-const socket = dgram.createSocket('udp4')
-
-function getRandomInt (min, max) {
-  return Math.floor(Math.random() * (max - min + 1)) + min
-}
-
-const buf = dnsPacket.encode({
-  type: 'query',
-  id: getRandomInt(1, 65534),
-  flags: dnsPacket.RECURSION_DESIRED,
-  questions: [{
-    type: 'A',
-    name: 'google.com'
-  }]
-})
-
-socket.on('message', function (message, rinfo) {
-  console.log(rinfo)
-  console.log(dnsPacket.decode(message)) // prints out a response from google dns
-  socket.close()
-})
-
-socket.send(buf, 0, buf.length, 53, '8.8.8.8')
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/index.js
+++ /dev/null
@@ -1,1541 +0,0 @@
-'use strict'
-
-const types = require('./types')
-const rcodes = require('./rcodes')
-const opcodes = require('./opcodes')
-const classes = require('./classes')
-const optioncodes = require('./optioncodes')
-const ip = require('../node-ip')
-
-const QUERY_FLAG = 0
-const RESPONSE_FLAG = 1 << 15
-const FLUSH_MASK = 1 << 15
-const NOT_FLUSH_MASK = ~FLUSH_MASK
-const QU_MASK = 1 << 15
-const NOT_QU_MASK = ~QU_MASK
-
-const name = exports.txt = exports.name = {}
-
-name.encode = function (str, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(name.encodingLength(str))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  // strip leading and trailing .
-  const n = str.replace(/^\.|\.$/gm, '')
-  if (n.length) {
-    const list = n.split('.')
-
-    for (let i = 0; i < list.length; i++) {
-      const len = buf.write(list[i], offset + 1)
-      buf[offset] = len
-      offset += len + 1
-    }
-  }
-
-  buf[offset++] = 0
-
-  name.encode.bytes = offset - oldOffset
-  return buf
-}
-
-name.encode.bytes = 0
-
-name.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const list = []
-  const oldOffset = offset
-  let len = buf[offset++]
-
-  if (len === 0) {
-    name.decode.bytes = 1
-    return '.'
-  }
-  if (len >= 0xc0) {
-    const res = name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000)
-    name.decode.bytes = 2
-    return res
-  }
-
-  while (len) {
-    if (len >= 0xc0) {
-      list.push(name.decode(buf, buf.readUInt16BE(offset - 1) - 0xc000))
-      offset++
-      break
-    }
-
-    list.push(buf.toString('utf-8', offset, offset + len))
-    offset += len
-    len = buf[offset++]
-  }
-
-  name.decode.bytes = offset - oldOffset
-  return list.join('.')
-}
-
-name.decode.bytes = 0
-
-name.encodingLength = function (n) {
-  if (n === '.') return 1
-  return Buffer.byteLength(n) + 2
-}
-
-const string = {}
-
-string.encode = function (s, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(string.encodingLength(s))
-  if (!offset) offset = 0
-
-  const len = buf.write(s, offset + 1)
-  buf[offset] = len
-  string.encode.bytes = len + 1
-  return buf
-}
-
-string.encode.bytes = 0
-
-string.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const len = buf[offset]
-  const s = buf.toString('utf-8', offset + 1, offset + 1 + len)
-  string.decode.bytes = len + 1
-  return s
-}
-
-string.decode.bytes = 0
-
-string.encodingLength = function (s) {
-  return Buffer.byteLength(s) + 1
-}
-
-const header = {}
-
-header.encode = function (h, buf, offset) {
-  if (!buf) buf = header.encodingLength(h)
-  if (!offset) offset = 0
-
-  const flags = (h.flags || 0) & 32767
-  const type = h.type === 'response' ? RESPONSE_FLAG : QUERY_FLAG
-
-  buf.writeUInt16BE(h.id || 0, offset)
-  buf.writeUInt16BE(flags | type, offset + 2)
-  buf.writeUInt16BE(h.questions.length, offset + 4)
-  buf.writeUInt16BE(h.answers.length, offset + 6)
-  buf.writeUInt16BE(h.authorities.length, offset + 8)
-  buf.writeUInt16BE(h.additionals.length, offset + 10)
-
-  return buf
-}
-
-header.encode.bytes = 12
-
-header.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  if (buf.length < 12) throw new Error('Header must be 12 bytes')
-  const flags = buf.readUInt16BE(offset + 2)
-
-  return {
-    id: buf.readUInt16BE(offset),
-    type: flags & RESPONSE_FLAG ? 'response' : 'query',
-    flags: flags & 32767,
-    flag_qr: ((flags >> 15) & 0x1) === 1,
-    opcode: opcodes.toString((flags >> 11) & 0xf),
-    flag_aa: ((flags >> 10) & 0x1) === 1,
-    flag_tc: ((flags >> 9) & 0x1) === 1,
-    flag_rd: ((flags >> 8) & 0x1) === 1,
-    flag_ra: ((flags >> 7) & 0x1) === 1,
-    flag_z: ((flags >> 6) & 0x1) === 1,
-    flag_ad: ((flags >> 5) & 0x1) === 1,
-    flag_cd: ((flags >> 4) & 0x1) === 1,
-    rcode: rcodes.toString(flags & 0xf),
-    questions: new Array(buf.readUInt16BE(offset + 4)),
-    answers: new Array(buf.readUInt16BE(offset + 6)),
-    authorities: new Array(buf.readUInt16BE(offset + 8)),
-    additionals: new Array(buf.readUInt16BE(offset + 10))
-  }
-}
-
-header.decode.bytes = 12
-
-header.encodingLength = function () {
-  return 12
-}
-
-const runknown = exports.unknown = {}
-
-runknown.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(runknown.encodingLength(data))
-  if (!offset) offset = 0
-
-  buf.writeUInt16BE(data.length, offset)
-  data.copy(buf, offset + 2)
-
-  runknown.encode.bytes = data.length + 2
-  return buf
-}
-
-runknown.encode.bytes = 0
-
-runknown.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const len = buf.readUInt16BE(offset)
-  const data = buf.slice(offset + 2, offset + 2 + len)
-  runknown.decode.bytes = len + 2
-  return data
-}
-
-runknown.decode.bytes = 0
-
-runknown.encodingLength = function (data) {
-  return data.length + 2
-}
-
-const rns = exports.ns = {}
-
-rns.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rns.encodingLength(data))
-  if (!offset) offset = 0
-
-  name.encode(data, buf, offset + 2)
-  buf.writeUInt16BE(name.encode.bytes, offset)
-  rns.encode.bytes = name.encode.bytes + 2
-  return buf
-}
-
-rns.encode.bytes = 0
-
-rns.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const len = buf.readUInt16BE(offset)
-  const dd = name.decode(buf, offset + 2)
-
-  rns.decode.bytes = len + 2
-  return dd
-}
-
-rns.decode.bytes = 0
-
-rns.encodingLength = function (data) {
-  return name.encodingLength(data) + 2
-}
-
-const rsoa = exports.soa = {}
-
-rsoa.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rsoa.encodingLength(data))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-  offset += 2
-  name.encode(data.mname, buf, offset)
-  offset += name.encode.bytes
-  name.encode(data.rname, buf, offset)
-  offset += name.encode.bytes
-  buf.writeUInt32BE(data.serial || 0, offset)
-  offset += 4
-  buf.writeUInt32BE(data.refresh || 0, offset)
-  offset += 4
-  buf.writeUInt32BE(data.retry || 0, offset)
-  offset += 4
-  buf.writeUInt32BE(data.expire || 0, offset)
-  offset += 4
-  buf.writeUInt32BE(data.minimum || 0, offset)
-  offset += 4
-
-  buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
-  rsoa.encode.bytes = offset - oldOffset
-  return buf
-}
-
-rsoa.encode.bytes = 0
-
-rsoa.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-
-  const data = {}
-  offset += 2
-  data.mname = name.decode(buf, offset)
-  offset += name.decode.bytes
-  data.rname = name.decode(buf, offset)
-  offset += name.decode.bytes
-  data.serial = buf.readUInt32BE(offset)
-  offset += 4
-  data.refresh = buf.readUInt32BE(offset)
-  offset += 4
-  data.retry = buf.readUInt32BE(offset)
-  offset += 4
-  data.expire = buf.readUInt32BE(offset)
-  offset += 4
-  data.minimum = buf.readUInt32BE(offset)
-  offset += 4
-
-  rsoa.decode.bytes = offset - oldOffset
-  return data
-}
-
-rsoa.decode.bytes = 0
-
-rsoa.encodingLength = function (data) {
-  return 22 + name.encodingLength(data.mname) + name.encodingLength(data.rname)
-}
-
-const rtxt = exports.txt = {}
-
-rtxt.encode = function (data, buf, offset) {
-  if (!Array.isArray(data)) data = [data]
-  for (let i = 0; i < data.length; i++) {
-    if (typeof data[i] === 'string') {
-      data[i] = Buffer.from(data[i])
-    }
-    if (!Buffer.isBuffer(data[i])) {
-      throw new Error('Must be a Buffer')
-    }
-  }
-
-  if (!buf) buf = Buffer.allocUnsafe(rtxt.encodingLength(data))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-  offset += 2
-
-  data.forEach(function (d) {
-    buf[offset++] = d.length
-    d.copy(buf, offset, 0, d.length)
-    offset += d.length
-  })
-
-  buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
-  rtxt.encode.bytes = offset - oldOffset
-  return buf
-}
-
-rtxt.encode.bytes = 0
-
-rtxt.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-  let remaining = buf.readUInt16BE(offset)
-  offset += 2
-
-  let data = []
-  while (remaining > 0) {
-    const len = buf[offset++]
-    --remaining
-    if (remaining < len) {
-      throw new Error('Buffer overflow')
-    }
-    data.push(buf.slice(offset, offset + len))
-    offset += len
-    remaining -= len
-  }
-
-  rtxt.decode.bytes = offset - oldOffset
-  return data
-}
-
-rtxt.decode.bytes = 0
-
-rtxt.encodingLength = function (data) {
-  if (!Array.isArray(data)) data = [data]
-  let length = 2
-  data.forEach(function (buf) {
-    if (typeof buf === 'string') {
-      length += Buffer.byteLength(buf) + 1
-    } else {
-      length += buf.length + 1
-    }
-  })
-  return length
-}
-
-const rnull = exports.null = {}
-
-rnull.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rnull.encodingLength(data))
-  if (!offset) offset = 0
-
-  if (typeof data === 'string') data = Buffer.from(data)
-  if (!data) data = Buffer.allocUnsafe(0)
-
-  const oldOffset = offset
-  offset += 2
-
-  const len = data.length
-  data.copy(buf, offset, 0, len)
-  offset += len
-
-  buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
-  rnull.encode.bytes = offset - oldOffset
-  return buf
-}
-
-rnull.encode.bytes = 0
-
-rnull.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-  const len = buf.readUInt16BE(offset)
-
-  offset += 2
-
-  const data = buf.slice(offset, offset + len)
-  offset += len
-
-  rnull.decode.bytes = offset - oldOffset
-  return data
-}
-
-rnull.decode.bytes = 0
-
-rnull.encodingLength = function (data) {
-  if (!data) return 2
-  return (Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data)) + 2
-}
-
-const rhinfo = exports.hinfo = {}
-
-rhinfo.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rhinfo.encodingLength(data))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-  offset += 2
-  string.encode(data.cpu, buf, offset)
-  offset += string.encode.bytes
-  string.encode(data.os, buf, offset)
-  offset += string.encode.bytes
-  buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
-  rhinfo.encode.bytes = offset - oldOffset
-  return buf
-}
-
-rhinfo.encode.bytes = 0
-
-rhinfo.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-
-  const data = {}
-  offset += 2
-  data.cpu = string.decode(buf, offset)
-  offset += string.decode.bytes
-  data.os = string.decode(buf, offset)
-  offset += string.decode.bytes
-  rhinfo.decode.bytes = offset - oldOffset
-  return data
-}
-
-rhinfo.decode.bytes = 0
-
-rhinfo.encodingLength = function (data) {
-  return string.encodingLength(data.cpu) + string.encodingLength(data.os) + 2
-}
-
-const rptr = exports.ptr = {}
-const rcname = exports.cname = rptr
-const rdname = exports.dname = rptr
-
-rptr.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rptr.encodingLength(data))
-  if (!offset) offset = 0
-
-  name.encode(data, buf, offset + 2)
-  buf.writeUInt16BE(name.encode.bytes, offset)
-  rptr.encode.bytes = name.encode.bytes + 2
-  return buf
-}
-
-rptr.encode.bytes = 0
-
-rptr.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const data = name.decode(buf, offset + 2)
-  rptr.decode.bytes = name.decode.bytes + 2
-  return data
-}
-
-rptr.decode.bytes = 0
-
-rptr.encodingLength = function (data) {
-  return name.encodingLength(data) + 2
-}
-
-const rsrv = exports.srv = {}
-
-rsrv.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rsrv.encodingLength(data))
-  if (!offset) offset = 0
-
-  buf.writeUInt16BE(data.priority || 0, offset + 2)
-  buf.writeUInt16BE(data.weight || 0, offset + 4)
-  buf.writeUInt16BE(data.port || 0, offset + 6)
-  name.encode(data.target, buf, offset + 8)
-
-  const len = name.encode.bytes + 6
-  buf.writeUInt16BE(len, offset)
-
-  rsrv.encode.bytes = len + 2
-  return buf
-}
-
-rsrv.encode.bytes = 0
-
-rsrv.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const len = buf.readUInt16BE(offset)
-
-  const data = {}
-  data.priority = buf.readUInt16BE(offset + 2)
-  data.weight = buf.readUInt16BE(offset + 4)
-  data.port = buf.readUInt16BE(offset + 6)
-  data.target = name.decode(buf, offset + 8)
-
-  rsrv.decode.bytes = len + 2
-  return data
-}
-
-rsrv.decode.bytes = 0
-
-rsrv.encodingLength = function (data) {
-  return 8 + name.encodingLength(data.target)
-}
-
-const rcaa = exports.caa = {}
-
-rcaa.ISSUER_CRITICAL = 1 << 7
-
-rcaa.encode = function (data, buf, offset) {
-  const len = rcaa.encodingLength(data)
-
-  if (!buf) buf = Buffer.allocUnsafe(rcaa.encodingLength(data))
-  if (!offset) offset = 0
-
-  if (data.issuerCritical) {
-    data.flags = rcaa.ISSUER_CRITICAL
-  }
-
-  buf.writeUInt16BE(len - 2, offset)
-  offset += 2
-  buf.writeUInt8(data.flags || 0, offset)
-  offset += 1
-  string.encode(data.tag, buf, offset)
-  offset += string.encode.bytes
-  buf.write(data.value, offset)
-  offset += Buffer.byteLength(data.value)
-
-  rcaa.encode.bytes = len
-  return buf
-}
-
-rcaa.encode.bytes = 0
-
-rcaa.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const len = buf.readUInt16BE(offset)
-  offset += 2
-
-  const oldOffset = offset
-  const data = {}
-  data.flags = buf.readUInt8(offset)
-  offset += 1
-  data.tag = string.decode(buf, offset)
-  offset += string.decode.bytes
-  data.value = buf.toString('utf-8', offset, oldOffset + len)
-
-  data.issuerCritical = !!(data.flags & rcaa.ISSUER_CRITICAL)
-
-  rcaa.decode.bytes = len + 2
-
-  return data
-}
-
-rcaa.decode.bytes = 0
-
-rcaa.encodingLength = function (data) {
-  return string.encodingLength(data.tag) + string.encodingLength(data.value) + 2
-}
-
-const rmx = exports.mx = {}
-
-rmx.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rmx.encodingLength(data))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-  offset += 2
-  buf.writeUInt16BE(data.preference || 0, offset)
-  offset += 2
-  name.encode(data.exchange, buf, offset)
-  offset += name.encode.bytes
-
-  buf.writeUInt16BE(offset - oldOffset - 2, oldOffset)
-  rmx.encode.bytes = offset - oldOffset
-  return buf
-}
-
-rmx.encode.bytes = 0
-
-rmx.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-
-  const data = {}
-  offset += 2
-  data.preference = buf.readUInt16BE(offset)
-  offset += 2
-  data.exchange = name.decode(buf, offset)
-  offset += name.decode.bytes
-
-  rmx.decode.bytes = offset - oldOffset
-  return data
-}
-
-rmx.encodingLength = function (data) {
-  return 4 + name.encodingLength(data.exchange)
-}
-
-const ra = exports.a = {}
-
-ra.encode = function (host, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(ra.encodingLength(host))
-  if (!offset) offset = 0
-
-  buf.writeUInt16BE(4, offset)
-  offset += 2
-  ip.toBuffer(host, buf, offset)
-  ra.encode.bytes = 6
-  return buf
-}
-
-ra.encode.bytes = 0
-
-ra.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  offset += 2
-  const host = ip.toString(buf, offset, 4)
-  ra.decode.bytes = 6
-  return host
-}
-
-ra.decode.bytes = 0
-
-ra.encodingLength = function () {
-  return 6
-}
-
-const raaaa = exports.aaaa = {}
-
-raaaa.encode = function (host, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(raaaa.encodingLength(host))
-  if (!offset) offset = 0
-
-  buf.writeUInt16BE(16, offset)
-  offset += 2
-  ip.toBuffer(host, buf, offset)
-  raaaa.encode.bytes = 18
-  return buf
-}
-
-raaaa.encode.bytes = 0
-
-raaaa.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  offset += 2
-  const host = ip.toString(buf, offset, 16)
-  raaaa.decode.bytes = 18
-  return host
-}
-
-raaaa.decode.bytes = 0
-
-raaaa.encodingLength = function () {
-  return 18
-}
-
-const roption = exports.option = {}
-
-roption.encode = function (option, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(roption.encodingLength(option))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const code = optioncodes.toCode(option.code)
-  buf.writeUInt16BE(code, offset)
-  offset += 2
-  if (option.data) {
-    buf.writeUInt16BE(option.data.length, offset)
-    offset += 2
-    option.data.copy(buf, offset)
-    offset += option.data.length
-  } else {
-    switch (code) {
-      // case 3: NSID.  No encode makes sense.
-      // case 5,6,7: Not implementable
-      case 8: // ECS
-        // note: do IP math before calling
-        const spl = option.sourcePrefixLength || 0
-        const fam = option.family || (ip.isV4Format(option.ip) ? 1 : 2)
-        const ipBuf = ip.toBuffer(option.ip)
-        const ipLen = Math.ceil(spl / 8)
-        buf.writeUInt16BE(ipLen + 4, offset)
-        offset += 2
-        buf.writeUInt16BE(fam, offset)
-        offset += 2
-        buf.writeUInt8(spl, offset++)
-        buf.writeUInt8(option.scopePrefixLength || 0, offset++)
-
-        ipBuf.copy(buf, offset, 0, ipLen)
-        offset += ipLen
-        break
-      // case 9: EXPIRE (experimental)
-      // case 10: COOKIE.  No encode makes sense.
-      case 11: // KEEP-ALIVE
-        if (option.timeout) {
-          buf.writeUInt16BE(2, offset)
-          offset += 2
-          buf.writeUInt16BE(option.timeout, offset)
-          offset += 2
-        } else {
-          buf.writeUInt16BE(0, offset)
-          offset += 2
-        }
-        break
-      case 12: // PADDING
-        const len = option.length || 0
-        buf.writeUInt16BE(len, offset)
-        offset += 2
-        buf.fill(0, offset, offset + len)
-        offset += len
-        break
-      // case 13:  CHAIN.  Experimental.
-      case 14: // KEY-TAG
-        const tagsLen = option.tags.length * 2
-        buf.writeUInt16BE(tagsLen, offset)
-        offset += 2
-        for (const tag of option.tags) {
-          buf.writeUInt16BE(tag, offset)
-          offset += 2
-        }
-        break
-      default:
-        throw new Error(`Unknown roption code: ${option.code}`)
-    }
-  }
-
-  roption.encode.bytes = offset - oldOffset
-  return buf
-}
-
-roption.encode.bytes = 0
-
-roption.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const option = {}
-  option.code = buf.readUInt16BE(offset)
-  option.type = optioncodes.toString(option.code)
-  offset += 2
-  const len = buf.readUInt16BE(offset)
-  offset += 2
-  option.data = buf.slice(offset, offset + len)
-  switch (option.code) {
-    // case 3: NSID.  No decode makes sense.
-    case 8: // ECS
-      option.family = buf.readUInt16BE(offset)
-      offset += 2
-      option.sourcePrefixLength = buf.readUInt8(offset++)
-      option.scopePrefixLength = buf.readUInt8(offset++)
-      const padded = Buffer.alloc((option.family === 1) ? 4 : 16)
-      buf.copy(padded, 0, offset, offset + len - 4)
-      option.ip = ip.toString(padded)
-      break
-    // case 12: Padding.  No decode makes sense.
-    case 11: // KEEP-ALIVE
-      if (len > 0) {
-        option.timeout = buf.readUInt16BE(offset)
-        offset += 2
-      }
-      break
-    case 14:
-      option.tags = []
-      for (let i = 0; i < len; i += 2) {
-        option.tags.push(buf.readUInt16BE(offset))
-        offset += 2
-      }
-    // don't worry about default.  caller will use data if desired
-  }
-
-  roption.decode.bytes = len + 4
-  return option
-}
-
-roption.decode.bytes = 0
-
-roption.encodingLength = function (option) {
-  if (option.data) {
-    return option.data.length + 4
-  }
-  const code = optioncodes.toCode(option.code)
-  switch (code) {
-    case 8: // ECS
-      const spl = option.sourcePrefixLength || 0
-      return Math.ceil(spl / 8) + 8
-    case 11: // KEEP-ALIVE
-      return (typeof option.timeout === 'number') ? 6 : 4
-    case 12: // PADDING
-      return option.length + 4
-    case 14: // KEY-TAG
-      return 4 + (option.tags.length * 2)
-  }
-  throw new Error(`Unknown roption code: ${option.code}`)
-}
-
-const ropt = exports.opt = {}
-
-ropt.encode = function (options, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(ropt.encodingLength(options))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const rdlen = encodingLengthList(options, roption)
-  buf.writeUInt16BE(rdlen, offset)
-  offset = encodeList(options, roption, buf, offset + 2)
-
-  ropt.encode.bytes = offset - oldOffset
-  return buf
-}
-
-ropt.encode.bytes = 0
-
-ropt.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const options = []
-  let rdlen = buf.readUInt16BE(offset)
-  offset += 2
-  let o = 0
-  while (rdlen > 0) {
-    options[o++] = roption.decode(buf, offset)
-    offset += roption.decode.bytes
-    rdlen -= roption.decode.bytes
-  }
-  ropt.decode.bytes = offset - oldOffset
-  return options
-}
-
-ropt.decode.bytes = 0
-
-ropt.encodingLength = function (options) {
-  return 2 + encodingLengthList(options || [], roption)
-}
-
-const rdnskey = exports.dnskey = {}
-
-rdnskey.PROTOCOL_DNSSEC = 3
-rdnskey.ZONE_KEY = 0x80
-rdnskey.SECURE_ENTRYPOINT = 0x8000
-
-rdnskey.encode = function (key, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rdnskey.encodingLength(key))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const keydata = key.key
-  if (!Buffer.isBuffer(keydata)) {
-    throw new Error('Key must be a Buffer')
-  }
-
-  offset += 2 // Leave space for length
-  buf.writeUInt16BE(key.flags, offset)
-  offset += 2
-  buf.writeUInt8(rdnskey.PROTOCOL_DNSSEC, offset)
-  offset += 1
-  buf.writeUInt8(key.algorithm, offset)
-  offset += 1
-  keydata.copy(buf, offset, 0, keydata.length)
-  offset += keydata.length
-
-  rdnskey.encode.bytes = offset - oldOffset
-  buf.writeUInt16BE(rdnskey.encode.bytes - 2, oldOffset)
-  return buf
-}
-
-rdnskey.encode.bytes = 0
-
-rdnskey.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var key = {}
-  var length = buf.readUInt16BE(offset)
-  offset += 2
-  key.flags = buf.readUInt16BE(offset)
-  offset += 2
-  if (buf.readUInt8(offset) !== rdnskey.PROTOCOL_DNSSEC) {
-    throw new Error('Protocol must be 3')
-  }
-  offset += 1
-  key.algorithm = buf.readUInt8(offset)
-  offset += 1
-  key.key = buf.slice(offset, oldOffset + length + 2)
-  offset += key.key.length
-  rdnskey.decode.bytes = offset - oldOffset
-  return key
-}
-
-rdnskey.decode.bytes = 0
-
-rdnskey.encodingLength = function (key) {
-  return 6 + Buffer.byteLength(key.key)
-}
-
-const rrrsig = exports.rrsig = {}
-
-rrrsig.encode = function (sig, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rrrsig.encodingLength(sig))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const signature = sig.signature
-  if (!Buffer.isBuffer(signature)) {
-    throw new Error('Signature must be a Buffer')
-  }
-
-  offset += 2 // Leave space for length
-  buf.writeUInt16BE(types.toType(sig.typeCovered), offset)
-  offset += 2
-  buf.writeUInt8(sig.algorithm, offset)
-  offset += 1
-  buf.writeUInt8(sig.labels, offset)
-  offset += 1
-  buf.writeUInt32BE(sig.originalTTL, offset)
-  offset += 4
-  buf.writeUInt32BE(sig.expiration, offset)
-  offset += 4
-  buf.writeUInt32BE(sig.inception, offset)
-  offset += 4
-  buf.writeUInt16BE(sig.keyTag, offset)
-  offset += 2
-  name.encode(sig.signersName, buf, offset)
-  offset += name.encode.bytes
-  signature.copy(buf, offset, 0, signature.length)
-  offset += signature.length
-
-  rrrsig.encode.bytes = offset - oldOffset
-  buf.writeUInt16BE(rrrsig.encode.bytes - 2, oldOffset)
-  return buf
-}
-
-rrrsig.encode.bytes = 0
-
-rrrsig.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var sig = {}
-  var length = buf.readUInt16BE(offset)
-  offset += 2
-  sig.typeCovered = types.toString(buf.readUInt16BE(offset))
-  offset += 2
-  sig.algorithm = buf.readUInt8(offset)
-  offset += 1
-  sig.labels = buf.readUInt8(offset)
-  offset += 1
-  sig.originalTTL = buf.readUInt32BE(offset)
-  offset += 4
-  sig.expiration = buf.readUInt32BE(offset)
-  offset += 4
-  sig.inception = buf.readUInt32BE(offset)
-  offset += 4
-  sig.keyTag = buf.readUInt16BE(offset)
-  offset += 2
-  sig.signersName = name.decode(buf, offset)
-  offset += name.decode.bytes
-  sig.signature = buf.slice(offset, oldOffset + length + 2)
-  offset += sig.signature.length
-  rrrsig.decode.bytes = offset - oldOffset
-  return sig
-}
-
-rrrsig.decode.bytes = 0
-
-rrrsig.encodingLength = function (sig) {
-  return 20 +
-    name.encodingLength(sig.signersName) +
-    Buffer.byteLength(sig.signature)
-}
-
-const rrp = exports.rp = {}
-
-rrp.encode = function (data, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rrp.encodingLength(data))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  offset += 2 // Leave space for length
-  name.encode(data.mbox || '.', buf, offset)
-  offset += name.encode.bytes
-  name.encode(data.txt || '.', buf, offset)
-  offset += name.encode.bytes
-  rrp.encode.bytes = offset - oldOffset
-  buf.writeUInt16BE(rrp.encode.bytes - 2, oldOffset)
-  return buf
-}
-
-rrp.encode.bytes = 0
-
-rrp.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const data = {}
-  offset += 2
-  data.mbox = name.decode(buf, offset) || '.'
-  offset += name.decode.bytes
-  data.txt = name.decode(buf, offset) || '.'
-  offset += name.decode.bytes
-  rrp.decode.bytes = offset - oldOffset
-  return data
-}
-
-rrp.decode.bytes = 0
-
-rrp.encodingLength = function (data) {
-  return 2 + name.encodingLength(data.mbox || '.') + name.encodingLength(data.txt || '.')
-}
-
-const typebitmap = {}
-
-typebitmap.encode = function (typelist, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(typebitmap.encodingLength(typelist))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var typesByWindow = []
-  for (var i = 0; i < typelist.length; i++) {
-    var typeid = types.toType(typelist[i])
-    if (typesByWindow[typeid >> 8] === undefined) {
-      typesByWindow[typeid >> 8] = []
-    }
-    typesByWindow[typeid >> 8][(typeid >> 3) & 0x1F] |= 1 << (7 - (typeid & 0x7))
-  }
-
-  for (i = 0; i < typesByWindow.length; i++) {
-    if (typesByWindow[i] !== undefined) {
-      var windowBuf = Buffer.from(typesByWindow[i])
-      buf.writeUInt8(i, offset)
-      offset += 1
-      buf.writeUInt8(windowBuf.length, offset)
-      offset += 1
-      windowBuf.copy(buf, offset)
-      offset += windowBuf.length
-    }
-  }
-
-  typebitmap.encode.bytes = offset - oldOffset
-  return buf
-}
-
-typebitmap.encode.bytes = 0
-
-typebitmap.decode = function (buf, offset, length) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var typelist = []
-  while (offset - oldOffset < length) {
-    var window = buf.readUInt8(offset)
-    offset += 1
-    var windowLength = buf.readUInt8(offset)
-    offset += 1
-    for (var i = 0; i < windowLength; i++) {
-      var b = buf.readUInt8(offset + i)
-      for (var j = 0; j < 8; j++) {
-        if (b & (1 << (7 - j))) {
-          var typeid = types.toString((window << 8) | (i << 3) | j)
-          typelist.push(typeid)
-        }
-      }
-    }
-    offset += windowLength
-  }
-
-  typebitmap.decode.bytes = offset - oldOffset
-  return typelist
-}
-
-typebitmap.decode.bytes = 0
-
-typebitmap.encodingLength = function (typelist) {
-  var extents = []
-  for (var i = 0; i < typelist.length; i++) {
-    var typeid = types.toType(typelist[i])
-    extents[typeid >> 8] = Math.max(extents[typeid >> 8] || 0, typeid & 0xFF)
-  }
-
-  var len = 0
-  for (i = 0; i < extents.length; i++) {
-    if (extents[i] !== undefined) {
-      len += 2 + Math.ceil((extents[i] + 1) / 8)
-    }
-  }
-
-  return len
-}
-
-const rnsec = exports.nsec = {}
-
-rnsec.encode = function (record, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rnsec.encodingLength(record))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  offset += 2 // Leave space for length
-  name.encode(record.nextDomain, buf, offset)
-  offset += name.encode.bytes
-  typebitmap.encode(record.rrtypes, buf, offset)
-  offset += typebitmap.encode.bytes
-
-  rnsec.encode.bytes = offset - oldOffset
-  buf.writeUInt16BE(rnsec.encode.bytes - 2, oldOffset)
-  return buf
-}
-
-rnsec.encode.bytes = 0
-
-rnsec.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var record = {}
-  var length = buf.readUInt16BE(offset)
-  offset += 2
-  record.nextDomain = name.decode(buf, offset)
-  offset += name.decode.bytes
-  record.rrtypes = typebitmap.decode(buf, offset, length - (offset - oldOffset))
-  offset += typebitmap.decode.bytes
-
-  rnsec.decode.bytes = offset - oldOffset
-  return record
-}
-
-rnsec.decode.bytes = 0
-
-rnsec.encodingLength = function (record) {
-  return 2 +
-    name.encodingLength(record.nextDomain) +
-    typebitmap.encodingLength(record.rrtypes)
-}
-
-const rnsec3 = exports.nsec3 = {}
-
-rnsec3.encode = function (record, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rnsec3.encodingLength(record))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const salt = record.salt
-  if (!Buffer.isBuffer(salt)) {
-    throw new Error('salt must be a Buffer')
-  }
-
-  const nextDomain = record.nextDomain
-  if (!Buffer.isBuffer(nextDomain)) {
-    throw new Error('nextDomain must be a Buffer')
-  }
-
-  offset += 2 // Leave space for length
-  buf.writeUInt8(record.algorithm, offset)
-  offset += 1
-  buf.writeUInt8(record.flags, offset)
-  offset += 1
-  buf.writeUInt16BE(record.iterations, offset)
-  offset += 2
-  buf.writeUInt8(salt.length, offset)
-  offset += 1
-  salt.copy(buf, offset, 0, salt.length)
-  offset += salt.length
-  buf.writeUInt8(nextDomain.length, offset)
-  offset += 1
-  nextDomain.copy(buf, offset, 0, nextDomain.length)
-  offset += nextDomain.length
-  typebitmap.encode(record.rrtypes, buf, offset)
-  offset += typebitmap.encode.bytes
-
-  rnsec3.encode.bytes = offset - oldOffset
-  buf.writeUInt16BE(rnsec3.encode.bytes - 2, oldOffset)
-  return buf
-}
-
-rnsec3.encode.bytes = 0
-
-rnsec3.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var record = {}
-  var length = buf.readUInt16BE(offset)
-  offset += 2
-  record.algorithm = buf.readUInt8(offset)
-  offset += 1
-  record.flags = buf.readUInt8(offset)
-  offset += 1
-  record.iterations = buf.readUInt16BE(offset)
-  offset += 2
-  const saltLength = buf.readUInt8(offset)
-  offset += 1
-  record.salt = buf.slice(offset, offset + saltLength)
-  offset += saltLength
-  const hashLength = buf.readUInt8(offset)
-  offset += 1
-  record.nextDomain = buf.slice(offset, offset + hashLength)
-  offset += hashLength
-  record.rrtypes = typebitmap.decode(buf, offset, length - (offset - oldOffset))
-  offset += typebitmap.decode.bytes
-
-  rnsec3.decode.bytes = offset - oldOffset
-  return record
-}
-
-rnsec3.decode.bytes = 0
-
-rnsec3.encodingLength = function (record) {
-  return 8 +
-    record.salt.length +
-    record.nextDomain.length +
-    typebitmap.encodingLength(record.rrtypes)
-}
-
-const rds = exports.ds = {}
-
-rds.encode = function (digest, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(rds.encodingLength(digest))
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  const digestdata = digest.digest
-  if (!Buffer.isBuffer(digestdata)) {
-    throw new Error('Digest must be a Buffer')
-  }
-
-  offset += 2 // Leave space for length
-  buf.writeUInt16BE(digest.keyTag, offset)
-  offset += 2
-  buf.writeUInt8(digest.algorithm, offset)
-  offset += 1
-  buf.writeUInt8(digest.digestType, offset)
-  offset += 1
-  digestdata.copy(buf, offset, 0, digestdata.length)
-  offset += digestdata.length
-
-  rds.encode.bytes = offset - oldOffset
-  buf.writeUInt16BE(rds.encode.bytes - 2, oldOffset)
-  return buf
-}
-
-rds.encode.bytes = 0
-
-rds.decode = function (buf, offset) {
-  if (!offset) offset = 0
-  const oldOffset = offset
-
-  var digest = {}
-  var length = buf.readUInt16BE(offset)
-  offset += 2
-  digest.keyTag = buf.readUInt16BE(offset)
-  offset += 2
-  digest.algorithm = buf.readUInt8(offset)
-  offset += 1
-  digest.digestType = buf.readUInt8(offset)
-  offset += 1
-  digest.digest = buf.slice(offset, oldOffset + length + 2)
-  offset += digest.digest.length
-  rds.decode.bytes = offset - oldOffset
-  return digest
-}
-
-rds.decode.bytes = 0
-
-rds.encodingLength = function (digest) {
-  return 6 + Buffer.byteLength(digest.digest)
-}
-
-const renc = exports.record = function (type) {
-  switch (type.toUpperCase()) {
-    case 'A': return ra
-    case 'PTR': return rptr
-    case 'CNAME': return rcname
-    case 'DNAME': return rdname
-    case 'TXT': return rtxt
-    case 'NULL': return rnull
-    case 'AAAA': return raaaa
-    case 'SRV': return rsrv
-    case 'HINFO': return rhinfo
-    case 'CAA': return rcaa
-    case 'NS': return rns
-    case 'SOA': return rsoa
-    case 'MX': return rmx
-    case 'OPT': return ropt
-    case 'DNSKEY': return rdnskey
-    case 'RRSIG': return rrrsig
-    case 'RP': return rrp
-    case 'NSEC': return rnsec
-    case 'NSEC3': return rnsec3
-    case 'DS': return rds
-  }
-  return runknown
-}
-
-const answer = exports.answer = {}
-
-answer.encode = function (a, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(answer.encodingLength(a))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-
-  name.encode(a.name, buf, offset)
-  offset += name.encode.bytes
-
-  buf.writeUInt16BE(types.toType(a.type), offset)
-
-  if (a.type.toUpperCase() === 'OPT') {
-    if (a.name !== '.') {
-      throw new Error('OPT name must be root.')
-    }
-    buf.writeUInt16BE(a.udpPayloadSize || 4096, offset + 2)
-    buf.writeUInt8(a.extendedRcode || 0, offset + 4)
-    buf.writeUInt8(a.ednsVersion || 0, offset + 5)
-    buf.writeUInt16BE(a.flags || 0, offset + 6)
-
-    offset += 8
-    ropt.encode(a.options || [], buf, offset)
-    offset += ropt.encode.bytes
-  } else {
-    let klass = classes.toClass(a.class === undefined ? 'IN' : a.class)
-    if (a.flush) klass |= FLUSH_MASK // the 1st bit of the class is the flush bit
-    buf.writeUInt16BE(klass, offset + 2)
-    buf.writeUInt32BE(a.ttl || 0, offset + 4)
-
-    offset += 8
-    const enc = renc(a.type)
-    enc.encode(a.data, buf, offset)
-    offset += enc.encode.bytes
-  }
-
-  answer.encode.bytes = offset - oldOffset
-  return buf
-}
-
-answer.encode.bytes = 0
-
-answer.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const a = {}
-  const oldOffset = offset
-
-  a.name = name.decode(buf, offset)
-  offset += name.decode.bytes
-  a.type = types.toString(buf.readUInt16BE(offset))
-  if (a.type === 'OPT') {
-    a.udpPayloadSize = buf.readUInt16BE(offset + 2)
-    a.extendedRcode = buf.readUInt8(offset + 4)
-    a.ednsVersion = buf.readUInt8(offset + 5)
-    a.flags = buf.readUInt16BE(offset + 6)
-    a.flag_do = ((a.flags >> 15) & 0x1) === 1
-    a.options = ropt.decode(buf, offset + 8)
-    offset += 8 + ropt.decode.bytes
-  } else {
-    const klass = buf.readUInt16BE(offset + 2)
-    a.ttl = buf.readUInt32BE(offset + 4)
-
-    a.class = classes.toString(klass & NOT_FLUSH_MASK)
-    a.flush = !!(klass & FLUSH_MASK)
-
-    const enc = renc(a.type)
-    a.data = enc.decode(buf, offset + 8)
-    offset += 8 + enc.decode.bytes
-  }
-
-  answer.decode.bytes = offset - oldOffset
-  return a
-}
-
-answer.decode.bytes = 0
-
-answer.encodingLength = function (a) {
-  const data = (a.data !== null && a.data !== undefined) ? a.data : a.options
-  return name.encodingLength(a.name) + 8 + renc(a.type).encodingLength(data)
-}
-
-const question = exports.question = {}
-
-question.encode = function (q, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(question.encodingLength(q))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-
-  name.encode(q.name, buf, offset)
-  offset += name.encode.bytes
-
-  buf.writeUInt16BE(types.toType(q.type), offset)
-  offset += 2
-
-  buf.writeUInt16BE(classes.toClass(q.class === undefined ? 'IN' : q.class), offset)
-  offset += 2
-
-  question.encode.bytes = offset - oldOffset
-  return q
-}
-
-question.encode.bytes = 0
-
-question.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-  const q = {}
-
-  q.name = name.decode(buf, offset)
-  offset += name.decode.bytes
-
-  q.type = types.toString(buf.readUInt16BE(offset))
-  offset += 2
-
-  q.class = classes.toString(buf.readUInt16BE(offset))
-  offset += 2
-
-  const qu = !!(q.class & QU_MASK)
-  if (qu) q.class &= NOT_QU_MASK
-
-  question.decode.bytes = offset - oldOffset
-  return q
-}
-
-question.decode.bytes = 0
-
-question.encodingLength = function (q) {
-  return name.encodingLength(q.name) + 4
-}
-
-exports.AUTHORITATIVE_ANSWER = 1 << 10
-exports.TRUNCATED_RESPONSE = 1 << 9
-exports.RECURSION_DESIRED = 1 << 8
-exports.RECURSION_AVAILABLE = 1 << 7
-exports.AUTHENTIC_DATA = 1 << 5
-exports.CHECKING_DISABLED = 1 << 4
-exports.DNSSEC_OK = 1 << 15
-
-exports.encode = function (result, buf, offset) {
-  if (!buf) buf = Buffer.allocUnsafe(exports.encodingLength(result))
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-
-  if (!result.questions) result.questions = []
-  if (!result.answers) result.answers = []
-  if (!result.authorities) result.authorities = []
-  if (!result.additionals) result.additionals = []
-
-  header.encode(result, buf, offset)
-  offset += header.encode.bytes
-
-  offset = encodeList(result.questions, question, buf, offset)
-  offset = encodeList(result.answers, answer, buf, offset)
-  offset = encodeList(result.authorities, answer, buf, offset)
-  offset = encodeList(result.additionals, answer, buf, offset)
-
-  exports.encode.bytes = offset - oldOffset
-
-  return buf
-}
-
-exports.encode.bytes = 0
-
-exports.decode = function (buf, offset) {
-  if (!offset) offset = 0
-
-  const oldOffset = offset
-  const result = header.decode(buf, offset)
-  offset += header.decode.bytes
-
-  offset = decodeList(result.questions, question, buf, offset)
-  offset = decodeList(result.answers, answer, buf, offset)
-  offset = decodeList(result.authorities, answer, buf, offset)
-  offset = decodeList(result.additionals, answer, buf, offset)
-
-  exports.decode.bytes = offset - oldOffset
-
-  return result
-}
-
-exports.decode.bytes = 0
-
-exports.encodingLength = function (result) {
-  return header.encodingLength(result) +
-    encodingLengthList(result.questions || [], question) +
-    encodingLengthList(result.answers || [], answer) +
-    encodingLengthList(result.authorities || [], answer) +
-    encodingLengthList(result.additionals || [], answer)
-}
-
-exports.streamEncode = function (result) {
-  const buf = exports.encode(result)
-  const sbuf = Buffer.allocUnsafe(2)
-  sbuf.writeUInt16BE(buf.byteLength)
-  const combine = Buffer.concat([sbuf, buf])
-  exports.streamEncode.bytes = combine.byteLength
-  return combine
-}
-
-exports.streamEncode.bytes = 0
-
-exports.streamDecode = function (sbuf) {
-  const len = sbuf.readUInt16BE(0)
-  if (sbuf.byteLength < len + 2) {
-    // not enough data
-    return null
-  }
-  const result = exports.decode(sbuf.slice(2))
-  exports.streamDecode.bytes = exports.decode.bytes
-  return result
-}
-
-exports.streamDecode.bytes = 0
-
-function encodingLengthList (list, enc) {
-  let len = 0
-  for (let i = 0; i < list.length; i++) len += enc.encodingLength(list[i])
-  return len
-}
-
-function encodeList (list, enc, buf, offset) {
-  for (let i = 0; i < list.length; i++) {
-    enc.encode(list[i], buf, offset)
-    offset += enc.encode.bytes
-  }
-  return offset
-}
-
-function decodeList (list, enc, buf, offset) {
-  for (let i = 0; i < list.length; i++) {
-    list[i] = enc.decode(buf, offset)
-    offset += enc.decode.bytes
-  }
-  return offset
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/opcodes.js
+++ /dev/null
@@ -1,50 +0,0 @@
-'use strict'
-
-/*
- * Traditional DNS header OPCODEs (4-bits) defined by IANA in
- * https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
- */
-
-exports.toString = function (opcode) {
-  switch (opcode) {
-    case 0: return 'QUERY'
-    case 1: return 'IQUERY'
-    case 2: return 'STATUS'
-    case 3: return 'OPCODE_3'
-    case 4: return 'NOTIFY'
-    case 5: return 'UPDATE'
-    case 6: return 'OPCODE_6'
-    case 7: return 'OPCODE_7'
-    case 8: return 'OPCODE_8'
-    case 9: return 'OPCODE_9'
-    case 10: return 'OPCODE_10'
-    case 11: return 'OPCODE_11'
-    case 12: return 'OPCODE_12'
-    case 13: return 'OPCODE_13'
-    case 14: return 'OPCODE_14'
-    case 15: return 'OPCODE_15'
-  }
-  return 'OPCODE_' + opcode
-}
-
-exports.toOpcode = function (code) {
-  switch (code.toUpperCase()) {
-    case 'QUERY': return 0
-    case 'IQUERY': return 1
-    case 'STATUS': return 2
-    case 'OPCODE_3': return 3
-    case 'NOTIFY': return 4
-    case 'UPDATE': return 5
-    case 'OPCODE_6': return 6
-    case 'OPCODE_7': return 7
-    case 'OPCODE_8': return 8
-    case 'OPCODE_9': return 9
-    case 'OPCODE_10': return 10
-    case 'OPCODE_11': return 11
-    case 'OPCODE_12': return 12
-    case 'OPCODE_13': return 13
-    case 'OPCODE_14': return 14
-    case 'OPCODE_15': return 15
-  }
-  return 0
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/optioncodes.js
+++ /dev/null
@@ -1,59 +0,0 @@
-'use strict'
-
-exports.toString = function (type) {
-  switch (type) {
-    // list at
-    // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11
-    case 1: return 'LLQ'
-    case 2: return 'UL'
-    case 3: return 'NSID'
-    case 5: return 'DAU'
-    case 6: return 'DHU'
-    case 7: return 'N3U'
-    case 8: return 'CLIENT_SUBNET'
-    case 9: return 'EXPIRE'
-    case 10: return 'COOKIE'
-    case 11: return 'TCP_KEEPALIVE'
-    case 12: return 'PADDING'
-    case 13: return 'CHAIN'
-    case 14: return 'KEY_TAG'
-    case 26946: return 'DEVICEID'
-  }
-  if (type < 0) {
-    return null
-  }
-  return `OPTION_${type}`
-}
-
-exports.toCode = function (name) {
-  if (typeof name === 'number') {
-    return name
-  }
-  if (!name) {
-    return -1
-  }
-  switch (name.toUpperCase()) {
-    case 'OPTION_0': return 0
-    case 'LLQ': return 1
-    case 'UL': return 2
-    case 'NSID': return 3
-    case 'OPTION_4': return 4
-    case 'DAU': return 5
-    case 'DHU': return 6
-    case 'N3U': return 7
-    case 'CLIENT_SUBNET': return 8
-    case 'EXPIRE': return 9
-    case 'COOKIE': return 10
-    case 'TCP_KEEPALIVE': return 11
-    case 'PADDING': return 12
-    case 'CHAIN': return 13
-    case 'KEY_TAG': return 14
-    case 'DEVICEID': return 26946
-    case 'OPTION_65535': return 65535
-  }
-  const m = name.match(/_(\d+)$/)
-  if (m) {
-    return parseInt(m[1], 10)
-  }
-  return -1
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/package.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
-  "name": "dns-packet",
-  "version": "5.2.1",
-  "description": "An abstract-encoding compliant module for encoding / decoding DNS packets",
-  "author": "Mathias Buus",
-  "license": "MIT",
-  "repository": "mafintosh/dns-packet",
-  "homepage": "https://github.com/mafintosh/dns-packet",
-  "engines": {
-    "node": ">=6"
-  },
-  "scripts": {
-    "clean": "rm -rf coverage .nyc_output/",
-    "lint": "eslint --color *.js examples/*.js",
-    "pretest": "npm run lint",
-    "test": "tape test.js",
-    "coverage": "nyc -r html npm test"
-  },
-  "dependencies": {
-    "ip": "^1.1.5"
-  },
-  "devDependencies": {
-    "eslint": "^5.14.1",
-    "eslint-config-standard": "^12.0.0",
-    "eslint-plugin-import": "^2.16.0",
-    "eslint-plugin-node": "^8.0.1",
-    "eslint-plugin-promise": "^4.0.1",
-    "eslint-plugin-standard": "^4.0.0",
-    "nyc": "^13.3.0",
-    "tape": "^4.10.1"
-  },
-  "keywords": [
-    "dns",
-    "packet",
-    "encodings",
-    "encoding",
-    "encoder",
-    "abstract-encoding"
-  ],
-  "files": [
-    "index.js",
-    "types.js",
-    "rcodes.js",
-    "opcodes.js",
-    "classes.js",
-    "optioncodes.js"
-  ]
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/rcodes.js
+++ /dev/null
@@ -1,50 +0,0 @@
-'use strict'
-
-/*
- * Traditional DNS header RCODEs (4-bits) defined by IANA in
- * https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
- */
-
-exports.toString = function (rcode) {
-  switch (rcode) {
-    case 0: return 'NOERROR'
-    case 1: return 'FORMERR'
-    case 2: return 'SERVFAIL'
-    case 3: return 'NXDOMAIN'
-    case 4: return 'NOTIMP'
-    case 5: return 'REFUSED'
-    case 6: return 'YXDOMAIN'
-    case 7: return 'YXRRSET'
-    case 8: return 'NXRRSET'
-    case 9: return 'NOTAUTH'
-    case 10: return 'NOTZONE'
-    case 11: return 'RCODE_11'
-    case 12: return 'RCODE_12'
-    case 13: return 'RCODE_13'
-    case 14: return 'RCODE_14'
-    case 15: return 'RCODE_15'
-  }
-  return 'RCODE_' + rcode
-}
-
-exports.toRcode = function (code) {
-  switch (code.toUpperCase()) {
-    case 'NOERROR': return 0
-    case 'FORMERR': return 1
-    case 'SERVFAIL': return 2
-    case 'NXDOMAIN': return 3
-    case 'NOTIMP': return 4
-    case 'REFUSED': return 5
-    case 'YXDOMAIN': return 6
-    case 'YXRRSET': return 7
-    case 'NXRRSET': return 8
-    case 'NOTAUTH': return 9
-    case 'NOTZONE': return 10
-    case 'RCODE_11': return 11
-    case 'RCODE_12': return 12
-    case 'RCODE_13': return 13
-    case 'RCODE_14': return 14
-    case 'RCODE_15': return 15
-  }
-  return 0
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/test.js
+++ /dev/null
@@ -1,613 +0,0 @@
-'use strict'
-
-const tape = require('tape')
-const packet = require('./')
-const rcodes = require('./rcodes')
-const opcodes = require('./opcodes')
-const optioncodes = require('./optioncodes')
-
-tape('unknown', function (t) {
-  testEncoder(t, packet.unknown, Buffer.from('hello world'))
-  t.end()
-})
-
-tape('txt', function (t) {
-  testEncoder(t, packet.txt, [])
-  testEncoder(t, packet.txt, ['hello world'])
-  testEncoder(t, packet.txt, ['hello', 'world'])
-  testEncoder(t, packet.txt, [Buffer.from([0, 1, 2, 3, 4, 5])])
-  testEncoder(t, packet.txt, ['a', 'b', Buffer.from([0, 1, 2, 3, 4, 5])])
-  testEncoder(t, packet.txt, ['', Buffer.allocUnsafe(0)])
-  t.end()
-})
-
-tape('txt-scalar-string', function (t) {
-  const buf = packet.txt.encode('hi')
-  const val = packet.txt.decode(buf)
-  t.ok(val.length === 1, 'array length')
-  t.ok(val[0].toString() === 'hi', 'data')
-  t.end()
-})
-
-tape('txt-scalar-buffer', function (t) {
-  const data = Buffer.from([0, 1, 2, 3, 4, 5])
-  const buf = packet.txt.encode(data)
-  const val = packet.txt.decode(buf)
-  t.ok(val.length === 1, 'array length')
-  t.ok(val[0].equals(data), 'data')
-  t.end()
-})
-
-tape('txt-invalid-data', function (t) {
-  t.throws(function () { packet.txt.encode(null) }, 'null')
-  t.throws(function () { packet.txt.encode(undefined) }, 'undefined')
-  t.throws(function () { packet.txt.encode(10) }, 'number')
-  t.end()
-})
-
-tape('null', function (t) {
-  testEncoder(t, packet.null, Buffer.from([0, 1, 2, 3, 4, 5]))
-  t.end()
-})
-
-tape('hinfo', function (t) {
-  testEncoder(t, packet.hinfo, { cpu: 'intel', os: 'best one' })
-  t.end()
-})
-
-tape('ptr', function (t) {
-  testEncoder(t, packet.ptr, 'hello.world.com')
-  t.end()
-})
-
-tape('cname', function (t) {
-  testEncoder(t, packet.cname, 'hello.cname.world.com')
-  t.end()
-})
-
-tape('dname', function (t) {
-  testEncoder(t, packet.dname, 'hello.dname.world.com')
-  t.end()
-})
-
-tape('srv', function (t) {
-  testEncoder(t, packet.srv, { port: 9999, target: 'hello.world.com' })
-  testEncoder(t, packet.srv, { port: 9999, target: 'hello.world.com', priority: 42, weight: 10 })
-  t.end()
-})
-
-tape('caa', function (t) {
-  testEncoder(t, packet.caa, { flags: 128, tag: 'issue', value: 'letsencrypt.org', issuerCritical: true })
-  testEncoder(t, packet.caa, { tag: 'issue', value: 'letsencrypt.org', issuerCritical: true })
-  testEncoder(t, packet.caa, { tag: 'issue', value: 'letsencrypt.org' })
-  t.end()
-})
-
-tape('mx', function (t) {
-  testEncoder(t, packet.mx, { preference: 10, exchange: 'mx.hello.world.com' })
-  testEncoder(t, packet.mx, { exchange: 'mx.hello.world.com' })
-  t.end()
-})
-
-tape('ns', function (t) {
-  testEncoder(t, packet.ns, 'ns.world.com')
-  t.end()
-})
-
-tape('soa', function (t) {
-  testEncoder(t, packet.soa, {
-    mname: 'hello.world.com',
-    rname: 'root.hello.world.com',
-    serial: 2018010400,
-    refresh: 14400,
-    retry: 3600,
-    expire: 604800,
-    minimum: 3600
-  })
-  t.end()
-})
-
-tape('a', function (t) {
-  testEncoder(t, packet.a, '127.0.0.1')
-  t.end()
-})
-
-tape('aaaa', function (t) {
-  testEncoder(t, packet.aaaa, 'fe80::1')
-  t.end()
-})
-
-tape('query', function (t) {
-  testEncoder(t, packet, {
-    type: 'query',
-    questions: [{
-      type: 'A',
-      name: 'hello.a.com'
-    }, {
-      type: 'SRV',
-      name: 'hello.srv.com'
-    }]
-  })
-
-  testEncoder(t, packet, {
-    type: 'query',
-    id: 42,
-    questions: [{
-      type: 'A',
-      class: 'IN',
-      name: 'hello.a.com'
-    }, {
-      type: 'SRV',
-      name: 'hello.srv.com'
-    }]
-  })
-
-  testEncoder(t, packet, {
-    type: 'query',
-    id: 42,
-    questions: [{
-      type: 'A',
-      class: 'CH',
-      name: 'hello.a.com'
-    }, {
-      type: 'SRV',
-      name: 'hello.srv.com'
-    }]
-  })
-
-  t.end()
-})
-
-tape('response', function (t) {
-  testEncoder(t, packet, {
-    type: 'response',
-    answers: [{
-      type: 'A',
-      class: 'IN',
-      flush: true,
-      name: 'hello.a.com',
-      data: '127.0.0.1'
-    }]
-  })
-
-  testEncoder(t, packet, {
-    type: 'response',
-    flags: packet.TRUNCATED_RESPONSE,
-    answers: [{
-      type: 'A',
-      class: 'IN',
-      name: 'hello.a.com',
-      data: '127.0.0.1'
-    }, {
-      type: 'SRV',
-      class: 'IN',
-      name: 'hello.srv.com',
-      data: {
-        port: 9090,
-        target: 'hello.target.com'
-      }
-    }, {
-      type: 'CNAME',
-      class: 'IN',
-      name: 'hello.cname.com',
-      data: 'hello.other.domain.com'
-    }]
-  })
-
-  testEncoder(t, packet, {
-    type: 'response',
-    id: 100,
-    flags: 0,
-    additionals: [{
-      type: 'AAAA',
-      name: 'hello.a.com',
-      data: 'fe80::1'
-    }, {
-      type: 'PTR',
-      name: 'hello.ptr.com',
-      data: 'hello.other.ptr.com'
-    }, {
-      type: 'SRV',
-      name: 'hello.srv.com',
-      ttl: 42,
-      data: {
-        port: 9090,
-        target: 'hello.target.com'
-      }
-    }],
-    answers: [{
-      type: 'NULL',
-      name: 'hello.null.com',
-      data: Buffer.from([1, 2, 3, 4, 5])
-    }]
-  })
-
-  testEncoder(t, packet, {
-    type: 'response',
-    answers: [{
-      type: 'TXT',
-      name: 'emptytxt.com',
-      data: ''
-    }]
-  })
-
-  t.end()
-})
-
-tape('rcode', function (t) {
-  const errors = ['NOERROR', 'FORMERR', 'SERVFAIL', 'NXDOMAIN', 'NOTIMP', 'REFUSED', 'YXDOMAIN', 'YXRRSET', 'NXRRSET', 'NOTAUTH', 'NOTZONE', 'RCODE_11', 'RCODE_12', 'RCODE_13', 'RCODE_14', 'RCODE_15']
-  for (const i in errors) {
-    const code = rcodes.toRcode(errors[i])
-    t.ok(errors[i] === rcodes.toString(code), 'rcode conversion from/to string matches: ' + rcodes.toString(code))
-  }
-
-  const ops = ['QUERY', 'IQUERY', 'STATUS', 'OPCODE_3', 'NOTIFY', 'UPDATE', 'OPCODE_6', 'OPCODE_7', 'OPCODE_8', 'OPCODE_9', 'OPCODE_10', 'OPCODE_11', 'OPCODE_12', 'OPCODE_13', 'OPCODE_14', 'OPCODE_15']
-  for (const j in ops) {
-    const ocode = opcodes.toOpcode(ops[j])
-    t.ok(ops[j] === opcodes.toString(ocode), 'opcode conversion from/to string matches: ' + opcodes.toString(ocode))
-  }
-
-  const buf = packet.encode({
-    type: 'response',
-    id: 45632,
-    flags: 0x8480,
-    answers: [{
-      type: 'A',
-      name: 'hello.example.net',
-      data: '127.0.0.1'
-    }]
-  })
-  const val = packet.decode(buf)
-  t.ok(val.type === 'response', 'decode type')
-  t.ok(val.opcode === 'QUERY', 'decode opcode')
-  t.ok(val.flag_qr === true, 'decode flag_qr')
-  t.ok(val.flag_aa === true, 'decode flag_aa')
-  t.ok(val.flag_tc === false, 'decode flag_tc')
-  t.ok(val.flag_rd === false, 'decode flag_rd')
-  t.ok(val.flag_ra === true, 'decode flag_ra')
-  t.ok(val.flag_z === false, 'decode flag_z')
-  t.ok(val.flag_ad === false, 'decode flag_ad')
-  t.ok(val.flag_cd === false, 'decode flag_cd')
-  t.ok(val.rcode === 'NOERROR', 'decode rcode')
-  t.end()
-})
-
-tape('name_encoding', function (t) {
-  let data = 'foo.example.com'
-  const buf = Buffer.allocUnsafe(255)
-  let offset = 0
-  packet.name.encode(data, buf, offset)
-  t.ok(packet.name.encode.bytes === 17, 'name encoding length matches')
-  let dd = packet.name.decode(buf, offset)
-  t.ok(data === dd, 'encode/decode matches')
-  offset += packet.name.encode.bytes
-
-  data = 'com'
-  packet.name.encode(data, buf, offset)
-  t.ok(packet.name.encode.bytes === 5, 'name encoding length matches')
-  dd = packet.name.decode(buf, offset)
-  t.ok(data === dd, 'encode/decode matches')
-  offset += packet.name.encode.bytes
-
-  data = 'example.com.'
-  packet.name.encode(data, buf, offset)
-  t.ok(packet.name.encode.bytes === 13, 'name encoding length matches')
-  dd = packet.name.decode(buf, offset)
-  t.ok(data.slice(0, -1) === dd, 'encode/decode matches')
-  offset += packet.name.encode.bytes
-
-  data = '.'
-  packet.name.encode(data, buf, offset)
-  t.ok(packet.name.encode.bytes === 1, 'name encoding length matches')
-  dd = packet.name.decode(buf, offset)
-  t.ok(data === dd, 'encode/decode matches')
-  t.end()
-})
-
-tape('stream', function (t) {
-  const val = {
-    type: 'query',
-    id: 45632,
-    flags: 0x8480,
-    answers: [{
-      type: 'A',
-      name: 'test2.example.net',
-      data: '198.51.100.1'
-    }]
-  }
-  const buf = packet.streamEncode(val)
-  const val2 = packet.streamDecode(buf)
-
-  t.same(buf.length, packet.streamEncode.bytes, 'streamEncode.bytes was set correctly')
-  t.ok(compare(t, val2.type, val.type), 'streamDecoded type match')
-  t.ok(compare(t, val2.id, val.id), 'streamDecoded id match')
-  t.ok(parseInt(val2.flags) === parseInt(val.flags & 0x7FFF), 'streamDecoded flags match')
-  const answer = val.answers[0]
-  const answer2 = val2.answers[0]
-  t.ok(compare(t, answer.type, answer2.type), 'streamDecoded RR type match')
-  t.ok(compare(t, answer.name, answer2.name), 'streamDecoded RR name match')
-  t.ok(compare(t, answer.data, answer2.data), 'streamDecoded RR rdata match')
-  t.end()
-})
-
-tape('opt', function (t) {
-  const val = {
-    type: 'query',
-    questions: [{
-      type: 'A',
-      name: 'hello.a.com'
-    }],
-    additionals: [{
-      type: 'OPT',
-      name: '.',
-      udpPayloadSize: 1024
-    }]
-  }
-  testEncoder(t, packet, val)
-  let buf = packet.encode(val)
-  let val2 = packet.decode(buf)
-  const additional1 = val.additionals[0]
-  let additional2 = val2.additionals[0]
-  t.ok(compare(t, additional1.name, additional2.name), 'name matches')
-  t.ok(compare(t, additional1.udpPayloadSize, additional2.udpPayloadSize), 'udp payload size matches')
-  t.ok(compare(t, 0, additional2.flags), 'flags match')
-  additional1.flags = packet.DNSSEC_OK
-  additional1.extendedRcode = 0x80
-  additional1.options = [ {
-    code: 'CLIENT_SUBNET', // edns-client-subnet, see RFC 7871
-    ip: 'fe80::',
-    sourcePrefixLength: 64
-  }, {
-    code: 8, // still ECS
-    ip: '5.6.0.0',
-    sourcePrefixLength: 16,
-    scopePrefixLength: 16
-  }, {
-    code: 'padding',
-    length: 31
-  }, {
-    code: 'TCP_KEEPALIVE'
-  }, {
-    code: 'tcp_keepalive',
-    timeout: 150
-  }, {
-    code: 'KEY_TAG',
-    tags: [1, 82, 987]
-  }]
-  buf = packet.encode(val)
-  val2 = packet.decode(buf)
-  additional2 = val2.additionals[0]
-  t.ok(compare(t, 1 << 15, additional2.flags), 'DO bit set in flags')
-  t.ok(compare(t, true, additional2.flag_do), 'DO bit set')
-  t.ok(compare(t, additional1.extendedRcode, additional2.extendedRcode), 'extended rcode matches')
-  t.ok(compare(t, 8, additional2.options[0].code))
-  t.ok(compare(t, 'fe80::', additional2.options[0].ip))
-  t.ok(compare(t, 64, additional2.options[0].sourcePrefixLength))
-  t.ok(compare(t, '5.6.0.0', additional2.options[1].ip))
-  t.ok(compare(t, 16, additional2.options[1].sourcePrefixLength))
-  t.ok(compare(t, 16, additional2.options[1].scopePrefixLength))
-  t.ok(compare(t, additional1.options[2].length, additional2.options[2].data.length))
-  t.ok(compare(t, additional1.options[3].timeout, undefined))
-  t.ok(compare(t, additional1.options[4].timeout, additional2.options[4].timeout))
-  t.ok(compare(t, additional1.options[5].tags, additional2.options[5].tags))
-  t.end()
-})
-
-tape('dnskey', function (t) {
-  testEncoder(t, packet.dnskey, {
-    flags: packet.dnskey.SECURE_ENTRYPOINT | packet.dnskey.ZONE_KEY,
-    algorithm: 1,
-    key: Buffer.from([0, 1, 2, 3, 4, 5])
-  })
-  t.end()
-})
-
-tape('rrsig', function (t) {
-  const testRRSIG = {
-    typeCovered: 'A',
-    algorithm: 1,
-    labels: 2,
-    originalTTL: 3600,
-    expiration: 1234,
-    inception: 1233,
-    keyTag: 2345,
-    signersName: 'foo.com',
-    signature: Buffer.from([0, 1, 2, 3, 4, 5])
-  }
-  testEncoder(t, packet.rrsig, testRRSIG)
-
-  // Check the signature length is correct with extra junk at the end
-  const buf = Buffer.allocUnsafe(packet.rrsig.encodingLength(testRRSIG) + 4)
-  packet.rrsig.encode(testRRSIG, buf)
-  const val2 = packet.rrsig.decode(buf)
-  t.ok(compare(t, testRRSIG, val2))
-
-  t.end()
-})
-
-tape('rrp', function (t) {
-  testEncoder(t, packet.rp, {
-    mbox: 'foo.bar.com',
-    txt: 'baz.bar.com'
-  })
-  testEncoder(t, packet.rp, {
-    mbox: 'foo.bar.com'
-  })
-  testEncoder(t, packet.rp, {
-    txt: 'baz.bar.com'
-  })
-  testEncoder(t, packet.rp, {})
-  t.end()
-})
-
-tape('nsec', function (t) {
-  testEncoder(t, packet.nsec, {
-    nextDomain: 'foo.com',
-    rrtypes: ['A', 'DNSKEY', 'CAA', 'DLV']
-  })
-  testEncoder(t, packet.nsec, {
-    nextDomain: 'foo.com',
-    rrtypes: ['TXT'] // 16
-  })
-  testEncoder(t, packet.nsec, {
-    nextDomain: 'foo.com',
-    rrtypes: ['TKEY'] // 249
-  })
-  testEncoder(t, packet.nsec, {
-    nextDomain: 'foo.com',
-    rrtypes: ['RRSIG', 'NSEC']
-  })
-  testEncoder(t, packet.nsec, {
-    nextDomain: 'foo.com',
-    rrtypes: ['TXT', 'RRSIG']
-  })
-  testEncoder(t, packet.nsec, {
-    nextDomain: 'foo.com',
-    rrtypes: ['TXT', 'NSEC']
-  })
-
-  // Test with the sample NSEC from https://tools.ietf.org/html/rfc4034#section-4.3
-  var sampleNSEC = Buffer.from('003704686f7374076578616d706c6503636f6d00' +
-      '0006400100000003041b000000000000000000000000000000000000000000000' +
-      '000000020', 'hex')
-  var decoded = packet.nsec.decode(sampleNSEC)
-  t.ok(compare(t, decoded, {
-    nextDomain: 'host.example.com',
-    rrtypes: ['A', 'MX', 'RRSIG', 'NSEC', 'UNKNOWN_1234']
-  }))
-  var reencoded = packet.nsec.encode(decoded)
-  t.same(sampleNSEC.length, reencoded.length)
-  t.same(sampleNSEC, reencoded)
-  t.end()
-})
-
-tape('nsec3', function (t) {
-  testEncoder(t, packet.nsec3, {
-    algorithm: 1,
-    flags: 0,
-    iterations: 257,
-    salt: Buffer.from([42, 42, 42]),
-    nextDomain: Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),
-    rrtypes: ['A', 'DNSKEY', 'CAA', 'DLV']
-  })
-  t.end()
-})
-
-tape('ds', function (t) {
-  testEncoder(t, packet.ds, {
-    keyTag: 1234,
-    algorithm: 1,
-    digestType: 1,
-    digest: Buffer.from([0, 1, 2, 3, 4, 5])
-  })
-  t.end()
-})
-
-tape('unpack', function (t) {
-  const buf = Buffer.from([
-    0x00, 0x79,
-    0xde, 0xad, 0x85, 0x00, 0x00, 0x01, 0x00, 0x01,
-    0x00, 0x02, 0x00, 0x02, 0x02, 0x6f, 0x6a, 0x05,
-    0x62, 0x61, 0x6e, 0x67, 0x6a, 0x03, 0x63, 0x6f,
-    0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c,
-    0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10,
-    0x00, 0x04, 0x81, 0xfa, 0x0b, 0xaa, 0xc0, 0x0f,
-    0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10,
-    0x00, 0x05, 0x02, 0x63, 0x6a, 0xc0, 0x0f, 0xc0,
-    0x0f, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x0e,
-    0x10, 0x00, 0x02, 0xc0, 0x0c, 0xc0, 0x3a, 0x00,
-    0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00,
-    0x04, 0x45, 0x4d, 0x9b, 0x9c, 0xc0, 0x0c, 0x00,
-    0x1c, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 0x00,
-    0x10, 0x20, 0x01, 0x04, 0x18, 0x00, 0x00, 0x50,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf9
-  ])
-  const val = packet.streamDecode(buf)
-  const answer = val.answers[0]
-  const authority = val.authorities[1]
-  t.ok(val.rcode === 'NOERROR', 'decode rcode')
-  t.ok(compare(t, answer.type, 'A'), 'streamDecoded RR type match')
-  t.ok(compare(t, answer.name, 'oj.bangj.com'), 'streamDecoded RR name match')
-  t.ok(compare(t, answer.data, '129.250.11.170'), 'streamDecoded RR rdata match')
-  t.ok(compare(t, authority.type, 'NS'), 'streamDecoded RR type match')
-  t.ok(compare(t, authority.name, 'bangj.com'), 'streamDecoded RR name match')
-  t.ok(compare(t, authority.data, 'oj.bangj.com'), 'streamDecoded RR rdata match')
-  t.end()
-})
-
-tape('optioncodes', function (t) {
-  const opts = [
-    [0, 'OPTION_0'],
-    [1, 'LLQ'],
-    [2, 'UL'],
-    [3, 'NSID'],
-    [4, 'OPTION_4'],
-    [5, 'DAU'],
-    [6, 'DHU'],
-    [7, 'N3U'],
-    [8, 'CLIENT_SUBNET'],
-    [9, 'EXPIRE'],
-    [10, 'COOKIE'],
-    [11, 'TCP_KEEPALIVE'],
-    [12, 'PADDING'],
-    [13, 'CHAIN'],
-    [14, 'KEY_TAG'],
-    [26946, 'DEVICEID'],
-    [65535, 'OPTION_65535'],
-    [64000, 'OPTION_64000'],
-    [65002, 'OPTION_65002'],
-    [-1, null]
-  ]
-  for (const [code, str] of opts) {
-    const s = optioncodes.toString(code)
-    t.ok(compare(t, s, str), `${code} => ${str}`)
-    t.ok(compare(t, optioncodes.toCode(s), code), `${str} => ${code}`)
-  }
-  t.ok(compare(t, optioncodes.toCode('INVALIDINVALID'), -1))
-  t.end()
-})
-
-function testEncoder (t, rpacket, val) {
-  const buf = rpacket.encode(val)
-  const val2 = rpacket.decode(buf)
-
-  t.same(buf.length, rpacket.encode.bytes, 'encode.bytes was set correctly')
-  t.same(buf.length, rpacket.encodingLength(val), 'encoding length matches')
-  t.ok(compare(t, val, val2), 'decoded object match')
-
-  const buf2 = rpacket.encode(val2)
-  const val3 = rpacket.decode(buf2)
-
-  t.same(buf2.length, rpacket.encode.bytes, 'encode.bytes was set correctly on re-encode')
-  t.same(buf2.length, rpacket.encodingLength(val), 'encoding length matches on re-encode')
-
-  t.ok(compare(t, val, val3), 'decoded object match on re-encode')
-  t.ok(compare(t, val2, val3), 're-encoded decoded object match on re-encode')
-
-  const bigger = Buffer.allocUnsafe(buf2.length + 10)
-
-  const buf3 = rpacket.encode(val, bigger, 10)
-  const val4 = rpacket.decode(buf3, 10)
-
-  t.ok(buf3 === bigger, 'echoes buffer on external buffer')
-  t.same(rpacket.encode.bytes, buf.length, 'encode.bytes is the same on external buffer')
-  t.ok(compare(t, val, val4), 'decoded object match on external buffer')
-}
-
-function compare (t, a, b) {
-  if (Buffer.isBuffer(a)) return a.toString('hex') === b.toString('hex')
-  if (typeof a === 'object' && a && b) {
-    const keys = Object.keys(a)
-    for (let i = 0; i < keys.length; i++) {
-      if (!compare(t, a[keys[i]], b[keys[i]])) {
-        return false
-      }
-    }
-  } else if (Array.isArray(b) && !Array.isArray(a)) {
-    // TXT always decode as array
-    return a.toString() === b[0].toString()
-  } else {
-    return a === b
-  }
-  return true
-}
deleted file mode 100644
--- a/testing/xpcshell/dns-packet/types.js
+++ /dev/null
@@ -1,103 +0,0 @@
-'use strict'
-
-exports.toString = function (type) {
-  switch (type) {
-    case 1: return 'A'
-    case 10: return 'NULL'
-    case 28: return 'AAAA'
-    case 18: return 'AFSDB'
-    case 42: return 'APL'
-    case 257: return 'CAA'
-    case 60: return 'CDNSKEY'
-    case 59: return 'CDS'
-    case 37: return 'CERT'
-    case 5: return 'CNAME'
-    case 49: return 'DHCID'
-    case 32769: return 'DLV'
-    case 39: return 'DNAME'
-    case 48: return 'DNSKEY'
-    case 43: return 'DS'
-    case 55: return 'HIP'
-    case 13: return 'HINFO'
-    case 45: return 'IPSECKEY'
-    case 25: return 'KEY'
-    case 36: return 'KX'
-    case 29: return 'LOC'
-    case 15: return 'MX'
-    case 35: return 'NAPTR'
-    case 2: return 'NS'
-    case 47: return 'NSEC'
-    case 50: return 'NSEC3'
-    case 51: return 'NSEC3PARAM'
-    case 12: return 'PTR'
-    case 46: return 'RRSIG'
-    case 17: return 'RP'
-    case 24: return 'SIG'
-    case 6: return 'SOA'
-    case 99: return 'SPF'
-    case 33: return 'SRV'
-    case 44: return 'SSHFP'
-    case 32768: return 'TA'
-    case 249: return 'TKEY'
-    case 52: return 'TLSA'
-    case 250: return 'TSIG'
-    case 16: return 'TXT'
-    case 252: return 'AXFR'
-    case 251: return 'IXFR'
-    case 41: return 'OPT'
-    case 255: return 'ANY'
-  }
-  return 'UNKNOWN_' + type
-}
-
-exports.toType = function (name) {
-  switch (name.toUpperCase()) {
-    case 'A': return 1
-    case 'NULL': return 10
-    case 'AAAA': return 28
-    case 'AFSDB': return 18
-    case 'APL': return 42
-    case 'CAA': return 257
-    case 'CDNSKEY': return 60
-    case 'CDS': return 59
-    case 'CERT': return 37
-    case 'CNAME': return 5
-    case 'DHCID': return 49
-    case 'DLV': return 32769
-    case 'DNAME': return 39
-    case 'DNSKEY': return 48
-    case 'DS': return 43
-    case 'HIP': return 55
-    case 'HINFO': return 13
-    case 'IPSECKEY': return 45
-    case 'KEY': return 25
-    case 'KX': return 36
-    case 'LOC': return 29
-    case 'MX': return 15
-    case 'NAPTR': return 35
-    case 'NS': return 2
-    case 'NSEC': return 47
-    case 'NSEC3': return 50
-    case 'NSEC3PARAM': return 51
-    case 'PTR': return 12
-    case 'RRSIG': return 46
-    case 'RP': return 17
-    case 'SIG': return 24
-    case 'SOA': return 6
-    case 'SPF': return 99
-    case 'SRV': return 33
-    case 'SSHFP': return 44
-    case 'TA': return 32768
-    case 'TKEY': return 249
-    case 'TLSA': return 52
-    case 'TSIG': return 250
-    case 'TXT': return 16
-    case 'AXFR': return 252
-    case 'IXFR': return 251
-    case 'OPT': return 41
-    case 'ANY': return 255
-    case '*': return 255
-  }
-  if (name.toUpperCase().startsWith('UNKNOWN_')) return parseInt(name.slice(8))
-  return 0
-}
--- a/testing/xpcshell/moz-http2/moz-http2.js
+++ b/testing/xpcshell/moz-http2/moz-http2.js
@@ -8,18 +8,16 @@
 var node_http2_root = '../node-http2';
 if (process.env.NODE_HTTP2_ROOT) {
   node_http2_root = process.env.NODE_HTTP2_ROOT;
 }
 var http2 = require(node_http2_root);
 var fs = require('fs');
 var url = require('url');
 var crypto = require('crypto');
-const dnsPacket = require('../dns-packet');
-const ip = require('../node-ip');
 
 // Hook into the decompression code to log the decompressed name-value pairs
 var compression_module = node_http2_root + "/lib/protocol/compressor";
 var http2_compression = require(compression_module);
 var HeaderSetDecompressor = http2_compression.HeaderSetDecompressor;
 var originalRead = HeaderSetDecompressor.prototype.read;
 var lastDecompressor;
 var decompressedPairs;
@@ -547,107 +545,16 @@ function handleRequest(req, res) {
     res.setHeader('Content-Type', 'application/dns-message');
     res.setHeader('Content-Length', content.length);
     res.writeHead(200);
     res.write(content);
     res.end("");
     return;
 
   }
-  else if (u.pathname == "/doh") {
-    ns_confirm = 0; // back to first reply for dns-confirm
-    cname_confirm = 0; // back to first reply for dns-cname
-
-    let params = new url.URL(`http://localhost${req.url}`).searchParams;
-    let responseIP = params.get("responseIP");
-    if (!responseIP) {
-      responseIP = "5.5.5.5";
-    }
-
-    if (params.get("auth")) {
-      // There's a Set-Cookie: header in the response for "/dns" , which this
-      // request subsequently would include if the http channel wasn't
-      // anonymous. Thus, if there's a cookie in this request, we know Firefox
-      // mishaved. If there's not, we're fine.
-      if (req.headers['cookie']) {
-        res.writeHead(403);
-        res.end("cookie for me, not for you");
-        return;
-      }
-      if (req.headers['authorization'] != "user:password") {
-        res.writeHead(401);
-        res.end("bad boy!");
-        return;
-      }
-    }
-
-    if (params.get("push")) {
-      // push.example.com has AAAA entry 2018::2018
-      var pcontent= new Buffer("0000010000010001000000000470757368076578616D706C6503636F6D00001C0001C00C001C000100000037001020180000000000000000000000002018", "hex");
-      push = res.push({
-        hostname: 'foo.example.com:' + serverPort,
-        port: serverPort,
-        path: '/dns-pushed-response?dns=AAAAAAABAAAAAAAABHB1c2gHZXhhbXBsZQNjb20AABwAAQ',
-        method: 'GET',
-        headers: {
-          'accept' : 'application/dns-message'
-        }
-      });
-      push.writeHead(200, {
-        'content-type': 'application/dns-message',
-        'pushed' : 'yes',
-        'content-length' : pcontent.length,
-        'X-Connection-Http2': 'yes'
-      });
-      push.end(pcontent);
-    }
-
-    let payload = new Buffer("");
-
-    function emitResponse(response, requestPayload) {
-      let packet = dnsPacket.decode(requestPayload);
-
-      let buf = dnsPacket.encode({
-        type: 'query',
-        id: packet.id,
-        flags: dnsPacket.RECURSION_DESIRED,
-        questions: packet.questions,
-        answers: [{
-          name: packet.questions[0].name,
-          ttl: 55,
-          type: ip.isV4Format(responseIP) ? "A" : "AAAA",
-          flush: false,
-          data: responseIP,
-        }],
-      });
-
-      response.setHeader('Content-Length', buf.length);
-      response.setHeader('Set-Cookie', 'trackyou=yes; path=/; max-age=100000;');
-      response.setHeader('Content-Type', 'application/dns-message');
-      response.writeHead(200);
-      response.write(buf);
-      response.end("");
-      return;
-    }
-
-    if (params.get("dns")) {
-      payload = Buffer.from(params.get("dns"), 'base64');
-      emitResponse(res, payload);
-      return;
-    }
-
-    req.on('data', function receiveData(chunk) {
-      payload = Buffer.concat([payload, chunk]);
-    });
-    req.on('end', function finishedData() {
-      emitResponse(res, payload);
-      return;
-    });
-    return;
-  }
   else if (u.pathname === "/dns-cname-a") {
     // test23 asks for cname-a.example.com
     // this responds with a CNAME to here.example.com *and* an A record
     // for here.example.com
     var content;
 
     content = new Buffer("0000" +
                          "0100" +
@@ -692,16 +599,67 @@ function handleRequest(req, res) {
     res.setHeader('Content-Type', 'application/dns-message');
     res.setHeader('Content-Length', content.length);
     res.writeHead(200);
     res.write(content);
     res.end("");
     return;
 
   }
+    // for use with test_trr.js, test8b
+  else if (u.path === "/dns-ecs?dns=AAABAAABAAAAAAABA2VjcwdleGFtcGxlA2NvbQAAAQABAAApEAAAAAAAAAgACAAEAAEAAA") {
+    // the query string asks for an A entry for ecs.example.com
+    // ecs.example.com has A entry 5.5.5.5
+    var content= new Buffer("00000100000100010000000003656373076578616D706C6503636F6D0000010001C00C0001000100000037000405050505", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
+  // for use with test_trr.js
+  else if (u.path === "/dns-get?dns=AAABAAABAAAAAAAAA2dldAdleGFtcGxlA2NvbQAAAQAB") {
+    // the query string asks for an A entry for get.example.com
+    // get.example.com has A entry 1.2.3.4
+    var content= new Buffer("00000100000100010000000003676574076578616D706C6503636F6D0000010001C00C0001000100000037000401020304", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    ns_confirm = 0; // back to first reply for dns-confirm
+    cname_confirm = 0; // back to first reply for dns-cname
+    return;
+  }
+  // for use with test_trr.js
+  else if (u.pathname === "/dns") {
+    // bar.example.com has A entry 127.0.0.1
+    var content= new Buffer("00000100000100010000000003626172076578616D706C6503636F6D0000010001C00C000100010000003700047F000001", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    // pass back a cookie here, check it in /dns-auth
+    res.setHeader('Set-Cookie', 'trackyou=yes; path=/; max-age=100000;');
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
+  else if (u.pathname === "/dns-ip") {
+    // bar.example.com has A entry 192.192.192.192
+    var content= new Buffer("00000100000100010000000003626172076578616D706C6503636F6D0000010001C00C00010001000000370004C0C0C0C0", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    // pass back a cookie here, check it in /dns-auth
+    res.setHeader('Set-Cookie', 'trackyou=yes; path=/; max-age=100000;');
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
   else if (u.pathname === "/dns-ns") {
     // confirm.example.com has NS entry ns.example.com
     var content= new Buffer("00000100000100010000000007636F6E6669726D076578616D706C6503636F6D0000020001C00C00020001000000370012026E73076578616D706C6503636F6D010A00", "hex");
     res.setHeader('Content-Type', 'application/dns-message');
     res.setHeader('Content-Length', content.length);
     res.writeHead(200);
     res.write(content);
     res.end("");
@@ -731,16 +689,92 @@ function handleRequest(req, res) {
     }
     res.setHeader('Content-Type', 'application/dns-message');
     res.setHeader('Content-Length', content.length);
     res.writeHead(200);
     res.write(content);
     res.end("");
     return;
   }
+  // for use with test_trr.js
+  else if (u.pathname === "/dns-aaaa") {
+    // aaaa.example.com has AAAA entry 2020:2020::2020
+    var content= new Buffer("0000010000010001000000000461616161076578616D706C6503636F6D00001C0001C00C001C000100000037001020202020000000000000000000002020", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
+  else if (u.pathname === "/dns-rfc1918") {
+    // rfc1918.example.com has A entry 192.168.0.1
+    var content= new Buffer("0000010000010001000000000772666331393138076578616D706C6503636F6D0000010001C00C00010001000000370004C0A80001", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
+  // for use with test_trr.js
+  else if (u.pathname === "/dns-push") {
+    // first.example.com has A entry 127.0.0.1
+    var content= new Buffer("000001000001000100000000056669727374076578616D706C6503636F6D0000010001C00C000100010000003700047F000001", "hex");
+    // push.example.com has AAAA entry 2018::2018
+    var pcontent= new Buffer("0000010000010001000000000470757368076578616D706C6503636F6D00001C0001C00C001C000100000037001020180000000000000000000000002018", "hex");
+    push = res.push({
+      hostname: 'foo.example.com:' + serverPort,
+      port: serverPort,
+      path: '/dns-pushed-response?dns=AAAAAAABAAAAAAAABHB1c2gHZXhhbXBsZQNjb20AABwAAQ',
+      method: 'GET',
+      headers: {
+        'accept' : 'application/dns-message'
+      }
+    });
+    push.writeHead(200, {
+      'content-type': 'application/dns-message',
+      'pushed' : 'yes',
+      'content-length' : pcontent.length,
+      'X-Connection-Http2': 'yes'
+    });
+    push.end(pcontent);
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
+  // for use with test_trr.js
+  else if (u.pathname === "/dns-auth") {
+    // There's a Set-Cookie: header in the response for "/dns" , which this
+    // request subsequently would include if the http channel wasn't
+    // anonymous. Thus, if there's a cookie in this request, we know Firefox
+    // mishaved. If there's not, we're fine.
+    if (req.headers['cookie']) {
+      res.writeHead(403);
+      res.end("cookie for me, not for you");
+      return;
+    }
+    if (req.headers['authorization'] != "user:password") {
+      res.writeHead(401);
+      res.end("bad boy!");
+      return;
+    }
+    // bar.example.com has A entry 127.0.0.1
+    var content= new Buffer("00000100000100010000000003626172076578616D706C6503636F6D0000010001C00C000100010000003700047F000001", "hex");
+    res.setHeader('Content-Type', 'application/dns-message');
+    res.setHeader('Content-Length', content.length);
+    res.writeHead(200);
+    res.write(content);
+    res.end("");
+    return;
+  }
+
   // for use with test_esni_dns_fetch.js
   else if (u.pathname === "/esni-dns") {
     content = new Buffer("0000" +
                          "8180" +
                          "0001" + // QDCOUNT
                          "0001" + // ANCOUNT
                          "00000000" + // NSCOUNT + ARCOUNT
                          "055F65736E69076578616D706C6503636F6D00" + // _esni.example.com
deleted file mode 100644
--- a/testing/xpcshell/node-ip/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules/
-npm-debug.log
deleted file mode 100644
--- a/testing/xpcshell/node-ip/.jscsrc
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "disallowKeywordsOnNewLine": [ "else" ],
-  "disallowMixedSpacesAndTabs": true,
-  "disallowMultipleLineStrings": true,
-  "disallowMultipleVarDecl": true,
-  "disallowNewlineBeforeBlockStatements": true,
-  "disallowQuotedKeysInObjects": true,
-  "disallowSpaceAfterObjectKeys": true,
-  "disallowSpaceAfterPrefixUnaryOperators": true,
-  "disallowSpaceBeforePostfixUnaryOperators": true,
-  "disallowSpacesInCallExpression": true,
-  "disallowTrailingComma": true,
-  "disallowTrailingWhitespace": true,
-  "disallowYodaConditions": true,
-
-  "requireCommaBeforeLineBreak": true,
-  "requireOperatorBeforeLineBreak": true,
-  "requireSpaceAfterBinaryOperators": true,
-  "requireSpaceAfterKeywords": [ "if", "for", "while", "else", "try", "catch" ],
-  "requireSpaceAfterLineComment": true,
-  "requireSpaceBeforeBinaryOperators": true,
-  "requireSpaceBeforeBlockStatements": true,
-  "requireSpaceBeforeKeywords": [ "else", "catch" ],
-  "requireSpaceBeforeObjectValues": true,
-  "requireSpaceBetweenArguments": true,
-  "requireSpacesInAnonymousFunctionExpression": {
-    "beforeOpeningCurlyBrace": true
-  },
-  "requireSpacesInFunctionDeclaration": {
-    "beforeOpeningCurlyBrace": true
-  },
-  "requireSpacesInFunctionExpression": {
-    "beforeOpeningCurlyBrace": true
-  },
-  "requireSpacesInConditionalExpression": true,
-  "requireSpacesInForStatement": true,
-  "requireSpacesInsideArrayBrackets": "all",
-  "requireSpacesInsideObjectBrackets": "all",
-  "requireDotNotation": true,
-
-  "maximumLineLength": 80,
-  "validateIndentation": 2,
-  "validateLineBreaks": "LF",
-  "validateParameterSeparator": ", ",
-  "validateQuoteMarks": "'"
-}
deleted file mode 100644
--- a/testing/xpcshell/node-ip/.jshintrc
+++ /dev/null
@@ -1,89 +0,0 @@
-{
-    // JSHint Default Configuration File (as on JSHint website)
-    // See http://jshint.com/docs/ for more details
-
-    "maxerr"        : 50,       // {int} Maximum error before stopping
-
-    // Enforcing
-    "bitwise"       : false,     // true: Prohibit bitwise operators (&, |, ^, etc.)
-    "camelcase"     : false,     // true: Identifiers must be in camelCase
-    "curly"         : false,     // true: Require {} for every new block or scope
-    "eqeqeq"        : true,     // true: Require triple equals (===) for comparison
-    "forin"         : true,     // true: Require filtering for..in loops with obj.hasOwnProperty()
-    "freeze"        : true,     // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
-    "immed"         : false,    // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
-    "indent"        : 2,        // {int} Number of spaces to use for indentation
-    "latedef"       : true,     // true: Require variables/functions to be defined before being used
-    "newcap"        : true,     // true: Require capitalization of all constructor functions e.g. `new F()`
-    "noarg"         : true,     // true: Prohibit use of `arguments.caller` and `arguments.callee`
-    "noempty"       : false,    // true: Prohibit use of empty blocks
-    "nonbsp"        : true,     // true: Prohibit "non-breaking whitespace" characters.
-    "nonew"         : false,    // true: Prohibit use of constructors for side-effects (without assignment)
-    "plusplus"      : false,    // true: Prohibit use of `++` & `--`
-    "quotmark"      : "single", // Quotation mark consistency:
-                                //   false    : do nothing (default)
-                                //   true     : ensure whatever is used is consistent
-                                //   "single" : require single quotes
-                                //   "double" : require double quotes
-    "undef"         : true,     // true: Require all non-global variables to be declared (prevents global leaks)
-    "unused"        : true,     // true: Require all defined variables be used
-    "strict"        : true,     // true: Requires all functions run in ES5 Strict Mode
-    "maxparams"     : false,    // {int} Max number of formal params allowed per function
-    "maxdepth"      : 3,        // {int} Max depth of nested blocks (within functions)
-    "maxstatements" : false,    // {int} Max number statements per function
-    "maxcomplexity" : false,    // {int} Max cyclomatic complexity per function
-    "maxlen"        : false,    // {int} Max number of characters per line
-
-    // Relaxing
-    "asi"           : false,     // true: Tolerate Automatic Semicolon Insertion (no semicolons)
-    "boss"          : false,     // true: Tolerate assignments where comparisons would be expected
-    "debug"         : false,     // true: Allow debugger statements e.g. browser breakpoints.
-    "eqnull"        : false,     // true: Tolerate use of `== null`
-    "es5"           : false,     // true: Allow ES5 syntax (ex: getters and setters)
-    "esnext"        : false,     // true: Allow ES.next (ES6) syntax (ex: `const`)
-    "moz"           : false,     // true: Allow Mozilla specific syntax (extends and overrides esnext features)
-                                 // (ex: `for each`, multiple try/catch, function expression…)
-    "evil"          : false,     // true: Tolerate use of `eval` and `new Function()`
-    "expr"          : false,     // true: Tolerate `ExpressionStatement` as Programs
-    "funcscope"     : false,     // true: Tolerate defining variables inside control statements
-    "globalstrict"  : false,     // true: Allow global "use strict" (also enables 'strict')
-    "iterator"      : false,     // true: Tolerate using the `__iterator__` property
-    "lastsemic"     : false,     // true: Tolerate omitting a semicolon for the last statement of a 1-line block
-    "laxbreak"      : false,     // true: Tolerate possibly unsafe line breakings
-    "laxcomma"      : false,     // true: Tolerate comma-first style coding
-    "loopfunc"      : false,     // true: Tolerate functions being defined in loops
-    "multistr"      : false,     // true: Tolerate multi-line strings
-    "noyield"       : false,     // true: Tolerate generator functions with no yield statement in them.
-    "notypeof"      : false,     // true: Tolerate invalid typeof operator values
-    "proto"         : false,     // true: Tolerate using the `__proto__` property
-    "scripturl"     : false,     // true: Tolerate script-targeted URLs
-    "shadow"        : true,      // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
-    "sub"           : false,     // true: Tolerate using `[]` notation when it can still be expressed in dot notation
-    "supernew"      : false,     // true: Tolerate `new function () { ... };` and `new Object;`
-    "validthis"     : false,     // true: Tolerate using this in a non-constructor function
-
-    // Environments
-    "browser"       : true,     // Web Browser (window, document, etc)
-    "browserify"    : true,     // Browserify (node.js code in the browser)
-    "couch"         : false,    // CouchDB
-    "devel"         : true,     // Development/debugging (alert, confirm, etc)
-    "dojo"          : false,    // Dojo Toolkit
-    "jasmine"       : false,    // Jasmine
-    "jquery"        : false,    // jQuery
-    "mocha"         : true,     // Mocha
-    "mootools"      : false,    // MooTools
-    "node"          : true,     // Node.js
-    "nonstandard"   : false,    // Widely adopted globals (escape, unescape, etc)
-    "prototypejs"   : false,    // Prototype and Scriptaculous
-    "qunit"         : false,    // QUnit
-    "rhino"         : false,    // Rhino
-    "shelljs"       : false,    // ShellJS
-    "worker"        : false,    // Web Workers
-    "wsh"           : false,    // Windows Scripting Host
-    "yui"           : false,    // Yahoo User Interface
-
-    // Custom Globals
-    "globals"       : {
-        "module": true
-    }        // additional predefined global variables
-}
deleted file mode 100644
--- a/testing/xpcshell/node-ip/.travis.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-sudo: false
-language: node_js
-node_js:
-  - "0.8"
-  - "0.10"
-  - "0.12"
-  - "4"
-  - "6"
-
-before_install:
-  - travis_retry npm install -g npm@2.14.5
-  - travis_retry npm install
-
-script:
-  - npm test
deleted file mode 100644
--- a/testing/xpcshell/node-ip/README.md
+++ /dev/null
@@ -1,90 +0,0 @@
-# IP  
-[![](https://badge.fury.io/js/ip.svg)](https://www.npmjs.com/package/ip)  
-
-IP address utilities for node.js
-
-## Installation
-
-###  npm
-```shell
-npm install ip
-```
-
-### git
-
-```shell
-git clone https://github.com/indutny/node-ip.git
-```
-  
-## Usage
-Get your ip address, compare ip addresses, validate ip addresses, etc.
-
-```js
-var ip = require('ip');
-
-ip.address() // my ip address
-ip.isEqual('::1', '::0:1'); // true
-ip.toBuffer('127.0.0.1') // Buffer([127, 0, 0, 1])
-ip.toString(new Buffer([127, 0, 0, 1])) // 127.0.0.1
-ip.fromPrefixLen(24) // 255.255.255.0
-ip.mask('192.168.1.134', '255.255.255.0') // 192.168.1.0
-ip.cidr('192.168.1.134/26') // 192.168.1.128
-ip.not('255.255.255.0') // 0.0.0.255
-ip.or('192.168.1.134', '0.0.0.255') // 192.168.1.255
-ip.isPrivate('127.0.0.1') // true
-ip.isV4Format('127.0.0.1'); // true
-ip.isV6Format('::ffff:127.0.0.1'); // true
-
-// operate on buffers in-place
-var buf = new Buffer(128);
-var offset = 64;
-ip.toBuffer('127.0.0.1', buf, offset);  // [127, 0, 0, 1] at offset 64
-ip.toString(buf, offset, 4);            // '127.0.0.1'
-
-// subnet information
-ip.subnet('192.168.1.134', '255.255.255.192')
-// { networkAddress: '192.168.1.128',
-//   firstAddress: '192.168.1.129',
-//   lastAddress: '192.168.1.190',
-//   broadcastAddress: '192.168.1.191',
-//   subnetMask: '255.255.255.192',
-//   subnetMaskLength: 26,
-//   numHosts: 62,
-//   length: 64,
-//   contains: function(addr){...} }
-ip.cidrSubnet('192.168.1.134/26')
-// Same as previous.
-
-// range checking
-ip.cidrSubnet('192.168.1.134/26').contains('192.168.1.190') // true
-
-
-// ipv4 long conversion
-ip.toLong('127.0.0.1'); // 2130706433
-ip.fromLong(2130706433); // '127.0.0.1'
-```
-
-### License
-
-This software is licensed under the MIT License.
-
-Copyright Fedor Indutny, 2012.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to permit
-persons to whom the Software is furnished to do so, subject to the
-following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
deleted file mode 100644
--- a/testing/xpcshell/node-ip/lib/ip.js
+++ /dev/null
@@ -1,416 +0,0 @@
-'use strict';
-
-var ip = exports;
-var Buffer = require('buffer').Buffer;
-var os = require('os');
-
-ip.toBuffer = function(ip, buff, offset) {
-  offset = ~~offset;
-
-  var result;
-
-  if (this.isV4Format(ip)) {
-    result = buff || new Buffer(offset + 4);
-    ip.split(/\./g).map(function(byte) {
-      result[offset++] = parseInt(byte, 10) & 0xff;
-    });
-  } else if (this.isV6Format(ip)) {
-    var sections = ip.split(':', 8);
-
-    var i;
-    for (i = 0; i < sections.length; i++) {
-      var isv4 = this.isV4Format(sections[i]);
-      var v4Buffer;
-
-      if (isv4) {
-        v4Buffer = this.toBuffer(sections[i]);
-        sections[i] = v4Buffer.slice(0, 2).toString('hex');
-      }
-
-      if (v4Buffer && ++i < 8) {
-        sections.splice(i, 0, v4Buffer.slice(2, 4).toString('hex'));
-      }
-    }
-
-    if (sections[0] === '') {
-      while (sections.length < 8) sections.unshift('0');
-    } else if (sections[sections.length - 1] === '') {
-      while (sections.length < 8) sections.push('0');
-    } else if (sections.length < 8) {
-      for (i = 0; i < sections.length && sections[i] !== ''; i++);
-      var argv = [ i, 1 ];
-      for (i = 9 - sections.length; i > 0; i--) {
-        argv.push('0');
-      }
-      sections.splice.apply(sections, argv);
-    }
-
-    result = buff || new Buffer(offset + 16);
-    for (i = 0; i < sections.length; i++) {
-      var word = parseInt(sections[i], 16);
-      result[offset++] = (word >> 8) & 0xff;
-      result[offset++] = word & 0xff;
-    }
-  }
-
-  if (!result) {
-    throw Error('Invalid ip address: ' + ip);
-  }
-
-  return result;
-};
-
-ip.toString = function(buff, offset, length) {
-  offset = ~~offset;
-  length = length || (buff.length - offset);
-
-  var result = [];
-  if (length === 4) {
-    // IPv4
-    for (var i = 0; i < length; i++) {
-      result.push(buff[offset + i]);
-    }
-    result = result.join('.');
-  } else if (length === 16) {
-    // IPv6
-    for (var i = 0; i < length; i += 2) {
-      result.push(buff.readUInt16BE(offset + i).toString(16));
-    }
-    result = result.join(':');
-    result = result.replace(/(^|:)0(:0)*:0(:|$)/, '$1::$3');
-    result = result.replace(/:{3,4}/, '::');
-  }
-
-  return result;
-};
-
-var ipv4Regex = /^(\d{1,3}\.){3,3}\d{1,3}$/;
-var ipv6Regex =
-    /^(::)?(((\d{1,3}\.){3}(\d{1,3}){1})?([0-9a-f]){0,4}:{0,2}){1,8}(::)?$/i;
-
-ip.isV4Format = function(ip) {
-  return ipv4Regex.test(ip);
-};
-
-ip.isV6Format = function(ip) {
-  return ipv6Regex.test(ip);
-};
-function _normalizeFamily(family) {
-  return family ? family.toLowerCase() : 'ipv4';
-}
-
-ip.fromPrefixLen = function(prefixlen, family) {
-  if (prefixlen > 32) {
-    family = 'ipv6';
-  } else {
-    family = _normalizeFamily(family);
-  }
-
-  var len = 4;
-  if (family === 'ipv6') {
-    len = 16;
-  }
-  var buff = new Buffer(len);
-
-  for (var i = 0, n = buff.length; i < n; ++i) {
-    var bits = 8;
-    if (prefixlen < 8) {
-      bits = prefixlen;
-    }
-    prefixlen -= bits;
-
-    buff[i] = ~(0xff >> bits) & 0xff;
-  }
-
-  return ip.toString(buff);
-};
-
-ip.mask = function(addr, mask) {
-  addr = ip.toBuffer(addr);
-  mask = ip.toBuffer(mask);
-
-  var result = new Buffer(Math.max(addr.length, mask.length));
-
-  var i = 0;
-  // Same protocol - do bitwise and
-  if (addr.length === mask.length) {
-    for (i = 0; i < addr.length; i++) {
-      result[i] = addr[i] & mask[i];
-    }
-  } else if (mask.length === 4) {
-    // IPv6 address and IPv4 mask
-    // (Mask low bits)
-    for (i = 0; i < mask.length; i++) {
-      result[i] = addr[addr.length - 4  + i] & mask[i];
-    }
-  } else {
-    // IPv6 mask and IPv4 addr
-    for (var i = 0; i < result.length - 6; i++) {
-      result[i] = 0;
-    }
-
-    // ::ffff:ipv4
-    result[10] = 0xff;
-    result[11] = 0xff;
-    for (i = 0; i < addr.length; i++) {
-      result[i + 12] = addr[i] & mask[i + 12];
-    }
-    i = i + 12;
-  }
-  for (; i < result.length; i++)
-    result[i] = 0;
-
-  return ip.toString(result);
-};
-
-ip.cidr = function(cidrString) {
-  var cidrParts = cidrString.split('/');
-
-  var addr = cidrParts[0];
-  if (cidrParts.length !== 2)
-    throw new Error('invalid CIDR subnet: ' + addr);
-
-  var mask = ip.fromPrefixLen(parseInt(cidrParts[1], 10));
-
-  return ip.mask(addr, mask);
-};
-
-ip.subnet = function(addr, mask) {
-  var networkAddress = ip.toLong(ip.mask(addr, mask));
-
-  // Calculate the mask's length.
-  var maskBuffer = ip.toBuffer(mask);
-  var maskLength = 0;
-
-  for (var i = 0; i < maskBuffer.length; i++) {
-    if (maskBuffer[i] === 0xff) {
-      maskLength += 8;
-    } else {
-      var octet = maskBuffer[i] & 0xff;
-      while (octet) {
-        octet = (octet << 1) & 0xff;
-        maskLength++;
-      }
-    }
-  }
-
-  var numberOfAddresses = Math.pow(2, 32 - maskLength);
-
-  return {
-    networkAddress: ip.fromLong(networkAddress),
-    firstAddress: numberOfAddresses <= 2 ?
-                    ip.fromLong(networkAddress) :
-                    ip.fromLong(networkAddress + 1),
-    lastAddress: numberOfAddresses <= 2 ?
-                    ip.fromLong(networkAddress + numberOfAddresses - 1) :
-                    ip.fromLong(networkAddress + numberOfAddresses - 2),
-    broadcastAddress: ip.fromLong(networkAddress + numberOfAddresses - 1),
-    subnetMask: mask,
-    subnetMaskLength: maskLength,
-    numHosts: numberOfAddresses <= 2 ?
-                numberOfAddresses : numberOfAddresses - 2,
-    length: numberOfAddresses,
-    contains: function(other) {
-      return networkAddress === ip.toLong(ip.mask(other, mask));
-    }
-  };
-};
-
-ip.cidrSubnet = function(cidrString) {
-  var cidrParts = cidrString.split('/');
-
-  var addr = cidrParts[0];
-  if (cidrParts.length !== 2)
-    throw new Error('invalid CIDR subnet: ' + addr);
-
-  var mask = ip.fromPrefixLen(parseInt(cidrParts[1], 10));
-
-  return ip.subnet(addr, mask);
-};
-
-ip.not = function(addr) {
-  var buff = ip.toBuffer(addr);
-  for (var i = 0; i < buff.length; i++) {
-    buff[i] = 0xff ^ buff[i];
-  }
-  return ip.toString(buff);
-};
-
-ip.or = function(a, b) {
-  a = ip.toBuffer(a);
-  b = ip.toBuffer(b);
-
-  // same protocol
-  if (a.length === b.length) {
-    for (var i = 0; i < a.length; ++i) {
-      a[i] |= b[i];
-    }
-    return ip.toString(a);
-
-  // mixed protocols
-  } else {
-    var buff = a;
-    var other = b;
-    if (b.length > a.length) {
-      buff = b;
-      other = a;
-    }
-
-    var offset = buff.length - other.length;
-    for (var i = offset; i < buff.length; ++i) {
-      buff[i] |= other[i - offset];
-    }
-
-    return ip.toString(buff);
-  }
-};
-
-ip.isEqual = function(a, b) {
-  a = ip.toBuffer(a);
-  b = ip.toBuffer(b);
-
-  // Same protocol
-  if (a.length === b.length) {
-    for (var i = 0; i < a.length; i++) {
-      if (a[i] !== b[i]) return false;
-    }
-    return true;
-  }
-
-  // Swap
-  if (b.length === 4) {
-    var t = b;
-    b = a;
-    a = t;
-  }
-
-  // a - IPv4, b - IPv6
-  for (var i = 0; i < 10; i++) {
-    if (b[i] !== 0) return false;
-  }
-
-  var word = b.readUInt16BE(10);
-  if (word !== 0 && word !== 0xffff) return false;
-
-  for (var i = 0; i < 4; i++) {
-    if (a[i] !== b[i + 12]) return false;
-  }
-
-  return true;
-};
-
-ip.isPrivate = function(addr) {
-  return /^(::f{4}:)?10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i
-      .test(addr) ||
-    /^(::f{4}:)?192\.168\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
-    /^(::f{4}:)?172\.(1[6-9]|2\d|30|31)\.([0-9]{1,3})\.([0-9]{1,3})$/i
-      .test(addr) ||
-    /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
-    /^(::f{4}:)?169\.254\.([0-9]{1,3})\.([0-9]{1,3})$/i.test(addr) ||
-    /^f[cd][0-9a-f]{2}:/i.test(addr) ||
-    /^fe80:/i.test(addr) ||
-    /^::1$/.test(addr) ||
-    /^::$/.test(addr);
-};
-
-ip.isPublic = function(addr) {
-  return !ip.isPrivate(addr);
-};
-
-ip.isLoopback = function(addr) {
-  return /^(::f{4}:)?127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/
-      .test(addr) ||
-    /^fe80::1$/.test(addr) ||
-    /^::1$/.test(addr) ||
-    /^::$/.test(addr);
-};
-
-ip.loopback = function(family) {
-  //
-  // Default to `ipv4`
-  //
-  family = _normalizeFamily(family);
-
-  if (family !== 'ipv4' && family !== 'ipv6') {
-    throw new Error('family must be ipv4 or ipv6');
-  }
-
-  return family === 'ipv4' ? '127.0.0.1' : 'fe80::1';
-};
-
-//
-// ### function address (name, family)
-// #### @name {string|'public'|'private'} **Optional** Name or security
-//      of the network interface.
-// #### @family {ipv4|ipv6} **Optional** IP family of the address (defaults
-//      to ipv4).
-//
-// Returns the address for the network interface on the current system with
-// the specified `name`:
-//   * String: First `family` address of the interface.
-//             If not found see `undefined`.
-//   * 'public': the first public ip address of family.
-//   * 'private': the first private ip address of family.
-//   * undefined: First address with `ipv4` or loopback address `127.0.0.1`.
-//
-ip.address = function(name, family) {
-  var interfaces = os.networkInterfaces();
-  var all;
-
-  //
-  // Default to `ipv4`
-  //
-  family = _normalizeFamily(family);
-
-  //
-  // If a specific network interface has been named,
-  // return the address.
-  //
-  if (name && name !== 'private' && name !== 'public') {
-    var res = interfaces[name].filter(function(details) {
-      var itemFamily = details.family.toLowerCase();
-      return itemFamily === family;
-    });
-    if (res.length === 0)
-      return undefined;
-    return res[0].address;
-  }
-
-  var all = Object.keys(interfaces).map(function (nic) {
-    //
-    // Note: name will only be `public` or `private`
-    // when this is called.
-    //
-    var addresses = interfaces[nic].filter(function (details) {
-      details.family = details.family.toLowerCase();
-      if (details.family !== family || ip.isLoopback(details.address)) {
-        return false;
-      } else if (!name) {
-        return true;
-      }
-
-      return name === 'public' ? ip.isPrivate(details.address) :
-          ip.isPublic(details.address);
-    });
-
-    return addresses.length ? addresses[0].address : undefined;
-  }).filter(Boolean);
-
-  return !all.length ? ip.loopback(family) : all[0];
-};
-
-ip.toLong = function(ip) {
-  var ipl = 0;
-  ip.split('.').forEach(function(octet) {
-    ipl <<= 8;
-    ipl += parseInt(octet);
-  });
-  return(ipl >>> 0);
-};
-
-ip.fromLong = function(ipl) {
-  return ((ipl >>> 24) + '.' +
-      (ipl >> 16 & 255) + '.' +
-      (ipl >> 8 & 255) + '.' +
-      (ipl & 255) );
-};
deleted file mode 100644
--- a/testing/xpcshell/node-ip/package.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "name": "ip",
-  "version": "1.1.5",
-  "author": "Fedor Indutny <fedor@indutny.com>",
-  "homepage": "https://github.com/indutny/node-ip",
-  "repository": {
-    "type": "git",
-    "url": "http://github.com/indutny/node-ip.git"
-  },
-  "main": "lib/ip",
-  "devDependencies": {
-    "jscs": "^2.1.1",
-    "jshint": "^2.8.0",
-    "mocha": "~1.3.2"
-  },
-  "scripts": {
-    "test": "jscs lib/*.js test/*.js && jshint lib/*.js && mocha --reporter spec test/*-test.js",
-    "fix": "jscs lib/*.js test/*.js --fix"
-  },
-  "license": "MIT"
-}
deleted file mode 100644
--- a/testing/xpcshell/node-ip/test/api-test.js
+++ /dev/null
@@ -1,407 +0,0 @@
-'use strict';
-
-var ip = require('..');
-var assert = require('assert');
-var net = require('net');
-var os = require('os');
-
-describe('IP library for node.js', function() {
-  describe('toBuffer()/toString() methods', function() {
-    it('should convert to buffer IPv4 address', function() {
-      var buf = ip.toBuffer('127.0.0.1');
-      assert.equal(buf.toString('hex'), '7f000001');
-      assert.equal(ip.toString(buf), '127.0.0.1');
-    });
-
-    it('should convert to buffer IPv4 address in-place', function() {
-      var buf = new Buffer(128);
-      var offset = 64;
-      ip.toBuffer('127.0.0.1', buf, offset);
-      assert.equal(buf.toString('hex', offset, offset + 4), '7f000001');
-      assert.equal(ip.toString(buf, offset, 4), '127.0.0.1');
-    });
-
-    it('should convert to buffer IPv6 address', function() {
-      var buf = ip.toBuffer('::1');
-      assert(/(00){15,15}01/.test(buf.toString('hex')));
-      assert.equal(ip.toString(buf), '::1');
-      assert.equal(ip.toString(ip.toBuffer('1::')), '1::');
-      assert.equal(ip.toString(ip.toBuffer('abcd::dcba')), 'abcd::dcba');
-    });
-
-    it('should convert to buffer IPv6 address in-place', function() {
-      var buf = new Buffer(128);
-      var offset = 64;
-      ip.toBuffer('::1', buf, offset);
-      assert(/(00){15,15}01/.test(buf.toString('hex', offset, offset + 16)));
-      assert.equal(ip.toString(buf, offset, 16), '::1');
-      assert.equal(ip.toString(ip.toBuffer('1::', buf, offset),
-                               offset, 16), '1::');
-      assert.equal(ip.toString(ip.toBuffer('abcd::dcba', buf, offset),
-                               offset, 16), 'abcd::dcba');
-    });
-
-    it('should convert to buffer IPv6 mapped IPv4 address', function() {
-      var buf = ip.toBuffer('::ffff:127.0.0.1');
-      assert.equal(buf.toString('hex'), '00000000000000000000ffff7f000001');
-      assert.equal(ip.toString(buf), '::ffff:7f00:1');
-
-      buf = ip.toBuffer('ffff::127.0.0.1');
-      assert.equal(buf.toString('hex'), 'ffff000000000000000000007f000001');
-      assert.equal(ip.toString(buf), 'ffff::7f00:1');
-
-      buf = ip.toBuffer('0:0:0:0:0:ffff:127.0.0.1');
-      assert.equal(buf.toString('hex'), '00000000000000000000ffff7f000001');
-      assert.equal(ip.toString(buf), '::ffff:7f00:1');
-    });
-  });
-
-  describe('fromPrefixLen() method', function() {
-    it('should create IPv4 mask', function() {
-      assert.equal(ip.fromPrefixLen(24), '255.255.255.0');
-    });
-    it('should create IPv6 mask', function() {
-      assert.equal(ip.fromPrefixLen(64), 'ffff:ffff:ffff:ffff::');
-    });
-    it('should create IPv6 mask explicitly', function() {
-      assert.equal(ip.fromPrefixLen(24, 'IPV6'), 'ffff:ff00::');
-    });
-  });
-
-  describe('not() method', function() {
-    it('should reverse bits in address', function() {
-      assert.equal(ip.not('255.255.255.0'), '0.0.0.255');
-    });
-  });
-
-  describe('or() method', function() {
-    it('should or bits in ipv4 addresses', function() {
-      assert.equal(ip.or('0.0.0.255', '192.168.1.10'), '192.168.1.255');
-    });
-    it('should or bits in ipv6 addresses', function() {
-      assert.equal(ip.or('::ff', '::abcd:dcba:abcd:dcba'),
-                   '::abcd:dcba:abcd:dcff');
-    });
-    it('should or bits in mixed addresses', function() {
-      assert.equal(ip.or('0.0.0.255', '::abcd:dcba:abcd:dcba'),
-                   '::abcd:dcba:abcd:dcff');
-    });
-  });
-
-  describe('mask() method', function() {
-    it('should mask bits in address', function() {
-      assert.equal(ip.mask('192.168.1.134', '255.255.255.0'), '192.168.1.0');
-      assert.equal(ip.mask('192.168.1.134', '::ffff:ff00'), '::ffff:c0a8:100');
-    });
-
-    it('should not leak data', function() {
-      for (var i = 0; i < 10; i++)
-        assert.equal(ip.mask('::1', '0.0.0.0'), '::');
-    });
-  });
-
-  describe('subnet() method', function() {
-    // Test cases calculated with http://www.subnet-calculator.com/
-    var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.192');
-
-    it('should compute ipv4 network address', function() {
-      assert.equal(ipv4Subnet.networkAddress, '192.168.1.128');
-    });
-
-    it('should compute ipv4 network\'s first address', function() {
-      assert.equal(ipv4Subnet.firstAddress, '192.168.1.129');
-    });
-
-    it('should compute ipv4 network\'s last address', function() {
-      assert.equal(ipv4Subnet.lastAddress, '192.168.1.190');
-    });
-
-    it('should compute ipv4 broadcast address', function() {
-      assert.equal(ipv4Subnet.broadcastAddress, '192.168.1.191');
-    });
-
-    it('should compute ipv4 subnet number of addresses', function() {
-      assert.equal(ipv4Subnet.length, 64);
-    });
-
-    it('should compute ipv4 subnet number of addressable hosts', function() {
-      assert.equal(ipv4Subnet.numHosts, 62);
-    });
-
-    it('should compute ipv4 subnet mask', function() {
-      assert.equal(ipv4Subnet.subnetMask, '255.255.255.192');
-    });
-
-    it('should compute ipv4 subnet mask\'s length', function() {
-      assert.equal(ipv4Subnet.subnetMaskLength, 26);
-    });
-
-    it('should know whether a subnet contains an address', function() {
-      assert.equal(ipv4Subnet.contains('192.168.1.180'), true);
-    });
-
-    it('should know whether a subnet does not contain an address', function() {
-      assert.equal(ipv4Subnet.contains('192.168.1.195'), false);
-    });
-  });
-
-  describe('subnet() method with mask length 32', function() {
-    // Test cases calculated with http://www.subnet-calculator.com/
-    var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.255');
-    it('should compute ipv4 network\'s first address', function() {
-      assert.equal(ipv4Subnet.firstAddress, '192.168.1.134');
-    });
-
-    it('should compute ipv4 network\'s last address', function() {
-      assert.equal(ipv4Subnet.lastAddress, '192.168.1.134');
-    });
-
-    it('should compute ipv4 subnet number of addressable hosts', function() {
-      assert.equal(ipv4Subnet.numHosts, 1);
-    });
-  });
-
-  describe('subnet() method with mask length 31', function() {
-    // Test cases calculated with http://www.subnet-calculator.com/
-    var ipv4Subnet = ip.subnet('192.168.1.134', '255.255.255.254');
-    it('should compute ipv4 network\'s first address', function() {
-      assert.equal(ipv4Subnet.firstAddress, '192.168.1.134');
-    });
-
-    it('should compute ipv4 network\'s last address', function() {
-      assert.equal(ipv4Subnet.lastAddress, '192.168.1.135');
-    });
-
-    it('should compute ipv4 subnet number of addressable hosts', function() {
-      assert.equal(ipv4Subnet.numHosts, 2);
-    });
-  });
-
-  describe('cidrSubnet() method', function() {
-    // Test cases calculated with http://www.subnet-calculator.com/
-    var ipv4Subnet = ip.cidrSubnet('192.168.1.134/26');
-
-    it('should compute an ipv4 network address', function() {
-      assert.equal(ipv4Subnet.networkAddress, '192.168.1.128');
-    });
-
-    it('should compute an ipv4 network\'s first address', function() {
-      assert.equal(ipv4Subnet.firstAddress, '192.168.1.129');
-    });
-
-    it('should compute an ipv4 network\'s last address', function() {
-      assert.equal(ipv4Subnet.lastAddress, '192.168.1.190');
-    });
-
-    it('should compute an ipv4 broadcast address', function() {
-      assert.equal(ipv4Subnet.broadcastAddress, '192.168.1.191');
-    });
-
-    it('should compute an ipv4 subnet number of addresses', function() {
-      assert.equal(ipv4Subnet.length, 64);
-    });
-
-    it('should compute an ipv4 subnet number of addressable hosts', function() {
-      assert.equal(ipv4Subnet.numHosts, 62);
-    });
-
-    it('should compute an ipv4 subnet mask', function() {
-      assert.equal(ipv4Subnet.subnetMask, '255.255.255.192');
-    });
-
-    it('should compute an ipv4 subnet mask\'s length', function() {
-      assert.equal(ipv4Subnet.subnetMaskLength, 26);
-    });
-
-    it('should know whether a subnet contains an address', function() {
-      assert.equal(ipv4Subnet.contains('192.168.1.180'), true);
-    });
-
-    it('should know whether a subnet contains an address', function() {
-      assert.equal(ipv4Subnet.contains('192.168.1.195'), false);
-    });
-
-  });
-
-  describe('cidr() method', function() {
-    it('should mask address in CIDR notation', function() {
-      assert.equal(ip.cidr('192.168.1.134/26'), '192.168.1.128');
-      assert.equal(ip.cidr('2607:f0d0:1002:51::4/56'), '2607:f0d0:1002::');
-    });
-  });
-
-  describe('isEqual() method', function() {
-    it('should check if addresses are equal', function() {
-      assert(ip.isEqual('127.0.0.1', '::7f00:1'));
-      assert(!ip.isEqual('127.0.0.1', '::7f00:2'));
-      assert(ip.isEqual('127.0.0.1', '::ffff:7f00:1'));
-      assert(!ip.isEqual('127.0.0.1', '::ffaf:7f00:1'));
-      assert(ip.isEqual('::ffff:127.0.0.1', '::ffff:127.0.0.1'));
-      assert(ip.isEqual('::ffff:127.0.0.1', '127.0.0.1'));
-    });
-  });
-
-
-  describe('isPrivate() method', function() {
-    it('should check if an address is localhost', function() {
-      assert.equal(ip.isPrivate('127.0.0.1'), true);
-    });
-
-    it('should check if an address is from a 192.168.x.x network', function() {
-      assert.equal(ip.isPrivate('192.168.0.123'), true);
-      assert.equal(ip.isPrivate('192.168.122.123'), true);
-      assert.equal(ip.isPrivate('192.162.1.2'), false);
-    });
-
-    it('should check if an address is from a 172.16.x.x network', function() {
-      assert.equal(ip.isPrivate('172.16.0.5'), true);
-      assert.equal(ip.isPrivate('172.16.123.254'), true);
-      assert.equal(ip.isPrivate('171.16.0.5'), false);
-      assert.equal(ip.isPrivate('172.25.232.15'), true);
-      assert.equal(ip.isPrivate('172.15.0.5'), false);
-      assert.equal(ip.isPrivate('172.32.0.5'), false);
-    });
-
-    it('should check if an address is from a 169.254.x.x network', function() {
-      assert.equal(ip.isPrivate('169.254.2.3'), true);
-      assert.equal(ip.isPrivate('169.254.221.9'), true);
-      assert.equal(ip.isPrivate('168.254.2.3'), false);
-    });
-
-    it('should check if an address is from a 10.x.x.x network', function() {
-      assert.equal(ip.isPrivate('10.0.2.3'), true);
-      assert.equal(ip.isPrivate('10.1.23.45'), true);
-      assert.equal(ip.isPrivate('12.1.2.3'), false);
-    });
-
-    it('should check if an address is from a private IPv6 network', function() {
-      assert.equal(ip.isPrivate('fd12:3456:789a:1::1'), true);
-      assert.equal(ip.isPrivate('fe80::f2de:f1ff:fe3f:307e'), true);
-      assert.equal(ip.isPrivate('::ffff:10.100.1.42'), true);
-      assert.equal(ip.isPrivate('::FFFF:172.16.200.1'), true);
-      assert.equal(ip.isPrivate('::ffff:192.168.0.1'), true);
-    });
-
-    it('should check if an address is from the internet', function() {
-      assert.equal(ip.isPrivate('165.225.132.33'), false); // joyent.com
-    });
-
-    it('should check if an address is a loopback IPv6 address', function() {
-      assert.equal(ip.isPrivate('::'), true);
-      assert.equal(ip.isPrivate('::1'), true);
-      assert.equal(ip.isPrivate('fe80::1'), true);
-    });
-  });
-
-  describe('loopback() method', function() {
-    describe('undefined', function() {
-      it('should respond with 127.0.0.1', function() {
-        assert.equal(ip.loopback(), '127.0.0.1')
-      });
-    });
-
-    describe('ipv4', function() {
-      it('should respond with 127.0.0.1', function() {
-        assert.equal(ip.loopback('ipv4'), '127.0.0.1')
-      });
-    });
-
-    describe('ipv6', function() {
-      it('should respond with fe80::1', function() {
-        assert.equal(ip.loopback('ipv6'), 'fe80::1')
-      });
-    });
-  });
-
-  describe('isLoopback() method', function() {
-    describe('127.0.0.1', function() {
-      it('should respond with true', function() {
-        assert.ok(ip.isLoopback('127.0.0.1'))
-      });
-    });
-
-    describe('127.8.8.8', function () {
-      it('should respond with true', function () {
-        assert.ok(ip.isLoopback('127.8.8.8'))
-      });
-    });
-
-    describe('8.8.8.8', function () {
-      it('should respond with false', function () {
-        assert.equal(ip.isLoopback('8.8.8.8'), false);
-      });
-    });
-
-    describe('fe80::1', function() {
-      it('should respond with true', function() {
-        assert.ok(ip.isLoopback('fe80::1'))
-      });
-    });
-
-    describe('::1', function() {
-      it('should respond with true', function() {
-        assert.ok(ip.isLoopback('::1'))
-      });
-    });
-
-    describe('::', function() {
-      it('should respond with true', function() {
-        assert.ok(ip.isLoopback('::'))
-      });
-    });
-  });
-
-  describe('address() method', function() {
-    describe('undefined', function() {
-      it('should respond with a private ip', function() {
-        assert.ok(ip.isPrivate(ip.address()));
-      });
-    });
-
-    describe('private', function() {
-      [ undefined, 'ipv4', 'ipv6' ].forEach(function(family) {
-        describe(family, function() {
-          it('should respond with a private ip', function() {
-            assert.ok(ip.isPrivate(ip.address('private', family)));
-          });
-        });
-      });
-    });
-
-    var interfaces = os.networkInterfaces();
-
-    Object.keys(interfaces).forEach(function(nic) {
-      describe(nic, function() {
-        [ undefined, 'ipv4' ].forEach(function(family) {
-          describe(family, function() {
-            it('should respond with an ipv4 address', function() {
-              var addr = ip.address(nic, family);
-              assert.ok(!addr || net.isIPv4(addr));
-            });
-          });
-        });
-
-        describe('ipv6', function() {
-          it('should respond with an ipv6 address', function() {
-            var addr = ip.address(nic, 'ipv6');
-            assert.ok(!addr || net.isIPv6(addr));
-          });
-        })
-      });
-    });
-  });
-
-  describe('toLong() method', function() {
-    it('should respond with a int', function() {
-      assert.equal(ip.toLong('127.0.0.1'), 2130706433);
-      assert.equal(ip.toLong('255.255.255.255'), 4294967295);
-    });
-  });
-
-  describe('fromLong() method', function() {
-    it('should repond with ipv4 address', function() {
-      assert.equal(ip.fromLong(2130706433), '127.0.0.1');
-      assert.equal(ip.fromLong(4294967295), '255.255.255.255');
-    });
-  })
-});
--- a/tools/rewriting/ThirdPartyPaths.txt
+++ b/tools/rewriting/ThirdPartyPaths.txt
@@ -100,18 +100,16 @@ security/sandbox/chromium/
 security/sandbox/chromium-shim/
 testing/gtest/gmock/
 testing/gtest/gtest/
 testing/talos/talos/tests/dromaeo/
 testing/talos/talos/tests/kraken/
 testing/talos/talos/tests/v8_7/
 testing/web-platform/tests/resources/webidl2/
 testing/web-platform/tests/tools/third_party/
-testing/xpcshell/node-ip/
-testing/xpcshell/dns-packet/
 third_party/
 toolkit/components/jsoncpp/
 toolkit/components/protobuf/
 toolkit/components/url-classifier/chromium/
 toolkit/components/url-classifier/protobuf/
 toolkit/crashreporter/breakpad-client/
 toolkit/crashreporter/google-breakpad/
 toolkit/recordreplay/udis86/