Bug 1796551 [wpt PR 36570] - WebKit export of https://bugs.webkit.org/show_bug.cgi...
[gecko.git] / netwerk / test / unit / test_dns_override.js
blobaf09beec1d2f58b722004b176e9fb2abe17bef12
1 "use strict";
3 const dns = Cc["@mozilla.org/network/dns-service;1"].getService(
4   Ci.nsIDNSService
5 );
6 const override = Cc["@mozilla.org/network/native-dns-override;1"].getService(
7   Ci.nsINativeDNSResolverOverride
8 );
9 const defaultOriginAttributes = {};
10 const mainThread = Services.tm.currentThread;
12 class Listener {
13   constructor() {
14     this.promise = new Promise(resolve => {
15       this.resolve = resolve;
16     });
17   }
19   onLookupComplete(inRequest, inRecord, inStatus) {
20     this.resolve([inRequest, inRecord, inStatus]);
21   }
23   async firstAddress() {
24     let all = await this.addresses();
25     if (all.length) {
26       return all[0];
27     }
29     return undefined;
30   }
32   async addresses() {
33     let [, inRecord] = await this.promise;
34     let addresses = [];
35     if (!inRecord) {
36       return addresses; // returns []
37     }
38     inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
39     while (inRecord.hasMore()) {
40       addresses.push(inRecord.getNextAddrAsString());
41     }
42     return addresses;
43   }
45   then() {
46     return this.promise.then.apply(this.promise, arguments);
47   }
49 Listener.prototype.QueryInterface = ChromeUtils.generateQI(["nsIDNSListener"]);
51 const DOMAIN = "example.org";
52 const OTHER = "example.com";
54 add_task(async function test_bad_IPs() {
55   Assert.throws(
56     () => override.addIPOverride(DOMAIN, DOMAIN),
57     /NS_ERROR_UNEXPECTED/,
58     "Should throw if input is not an IP address"
59   );
60   Assert.throws(
61     () => override.addIPOverride(DOMAIN, ""),
62     /NS_ERROR_UNEXPECTED/,
63     "Should throw if input is not an IP address"
64   );
65   Assert.throws(
66     () => override.addIPOverride(DOMAIN, " "),
67     /NS_ERROR_UNEXPECTED/,
68     "Should throw if input is not an IP address"
69   );
70   Assert.throws(
71     () => override.addIPOverride(DOMAIN, "1-2-3-4"),
72     /NS_ERROR_UNEXPECTED/,
73     "Should throw if input is not an IP address"
74   );
75 });
77 add_task(async function test_ipv4() {
78   let listener = new Listener();
79   override.addIPOverride(DOMAIN, "1.2.3.4");
80   dns.asyncResolve(
81     DOMAIN,
82     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
83     0,
84     null,
85     listener,
86     mainThread,
87     defaultOriginAttributes
88   );
89   Assert.equal(await listener.firstAddress(), "1.2.3.4");
91   dns.clearCache(false);
92   override.clearOverrides();
93 });
95 add_task(async function test_ipv6() {
96   let listener = new Listener();
97   override.addIPOverride(DOMAIN, "fe80::6a99:9b2b:6ccc:6e1b");
98   dns.asyncResolve(
99     DOMAIN,
100     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
101     0,
102     null,
103     listener,
104     mainThread,
105     defaultOriginAttributes
106   );
107   Assert.equal(await listener.firstAddress(), "fe80::6a99:9b2b:6ccc:6e1b");
109   dns.clearCache(false);
110   override.clearOverrides();
113 add_task(async function test_clearOverrides() {
114   let listener = new Listener();
115   override.addIPOverride(DOMAIN, "1.2.3.4");
116   dns.asyncResolve(
117     DOMAIN,
118     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
119     0,
120     null,
121     listener,
122     mainThread,
123     defaultOriginAttributes
124   );
125   Assert.equal(await listener.firstAddress(), "1.2.3.4");
127   dns.clearCache(false);
128   override.clearOverrides();
130   listener = new Listener();
131   dns.asyncResolve(
132     DOMAIN,
133     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
134     0,
135     null,
136     listener,
137     mainThread,
138     defaultOriginAttributes
139   );
140   Assert.notEqual(await listener.firstAddress(), "1.2.3.4");
142   await new Promise(resolve => do_timeout(1000, resolve));
143   dns.clearCache(false);
144   override.clearOverrides();
147 add_task(async function test_clearHostOverride() {
148   override.addIPOverride(DOMAIN, "2.2.2.2");
149   override.addIPOverride(OTHER, "2.2.2.2");
150   override.clearHostOverride(DOMAIN);
151   let listener = new Listener();
152   dns.asyncResolve(
153     DOMAIN,
154     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
155     0,
156     null,
157     listener,
158     mainThread,
159     defaultOriginAttributes
160   );
162   Assert.notEqual(await listener.firstAddress(), "2.2.2.2");
164   listener = new Listener();
165   dns.asyncResolve(
166     OTHER,
167     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
168     0,
169     null,
170     listener,
171     mainThread,
172     defaultOriginAttributes
173   );
174   Assert.equal(await listener.firstAddress(), "2.2.2.2");
176   // Note: this test will use the actual system resolver. On windows we do a
177   // second async call to the system libraries to get the TTL values, which
178   // keeps the record alive after the onLookupComplete()
179   // We need to wait for a bit, until the second call is finished before we
180   // can clear the cache to make sure we evict everything.
181   // If the next task ever starts failing, with an IP that is not in this
182   // file, then likely the timeout is too small.
183   await new Promise(resolve => do_timeout(1000, resolve));
184   dns.clearCache(false);
185   override.clearOverrides();
188 add_task(async function test_multiple_IPs() {
189   override.addIPOverride(DOMAIN, "2.2.2.2");
190   override.addIPOverride(DOMAIN, "1.1.1.1");
191   override.addIPOverride(DOMAIN, "::1");
192   override.addIPOverride(DOMAIN, "fe80::6a99:9b2b:6ccc:6e1b");
193   let listener = new Listener();
194   dns.asyncResolve(
195     DOMAIN,
196     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
197     0,
198     null,
199     listener,
200     mainThread,
201     defaultOriginAttributes
202   );
203   Assert.deepEqual(await listener.addresses(), [
204     "2.2.2.2",
205     "1.1.1.1",
206     "::1",
207     "fe80::6a99:9b2b:6ccc:6e1b",
208   ]);
210   dns.clearCache(false);
211   override.clearOverrides();
214 add_task(async function test_address_family_flags() {
215   override.addIPOverride(DOMAIN, "2.2.2.2");
216   override.addIPOverride(DOMAIN, "1.1.1.1");
217   override.addIPOverride(DOMAIN, "::1");
218   override.addIPOverride(DOMAIN, "fe80::6a99:9b2b:6ccc:6e1b");
219   let listener = new Listener();
220   dns.asyncResolve(
221     DOMAIN,
222     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
223     Ci.nsIDNSService.RESOLVE_DISABLE_IPV4,
224     null,
225     listener,
226     mainThread,
227     defaultOriginAttributes
228   );
229   Assert.deepEqual(await listener.addresses(), [
230     "::1",
231     "fe80::6a99:9b2b:6ccc:6e1b",
232   ]);
234   listener = new Listener();
235   dns.asyncResolve(
236     DOMAIN,
237     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
238     Ci.nsIDNSService.RESOLVE_DISABLE_IPV6,
239     null,
240     listener,
241     mainThread,
242     defaultOriginAttributes
243   );
244   Assert.deepEqual(await listener.addresses(), ["2.2.2.2", "1.1.1.1"]);
246   dns.clearCache(false);
247   override.clearOverrides();
250 add_task(async function test_cname_flag() {
251   override.addIPOverride(DOMAIN, "2.2.2.2");
252   let listener = new Listener();
253   dns.asyncResolve(
254     DOMAIN,
255     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
256     0,
257     null,
258     listener,
259     mainThread,
260     defaultOriginAttributes
261   );
262   let [, inRecord] = await listener;
263   inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
264   Assert.throws(
265     () => inRecord.canonicalName,
266     /NS_ERROR_NOT_AVAILABLE/,
267     "No canonical name flag"
268   );
269   Assert.equal(inRecord.getNextAddrAsString(), "2.2.2.2");
271   listener = new Listener();
272   dns.asyncResolve(
273     DOMAIN,
274     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
275     Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
276     null,
277     listener,
278     mainThread,
279     defaultOriginAttributes
280   );
281   [, inRecord] = await listener;
282   inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
283   Assert.equal(inRecord.canonicalName, DOMAIN, "No canonical name specified");
284   Assert.equal(inRecord.getNextAddrAsString(), "2.2.2.2");
286   dns.clearCache(false);
287   override.clearOverrides();
289   override.addIPOverride(DOMAIN, "2.2.2.2");
290   override.setCnameOverride(DOMAIN, OTHER);
291   listener = new Listener();
292   dns.asyncResolve(
293     DOMAIN,
294     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
295     Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
296     null,
297     listener,
298     mainThread,
299     defaultOriginAttributes
300   );
301   [, inRecord] = await listener;
302   inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
303   Assert.equal(inRecord.canonicalName, OTHER, "Must have correct CNAME");
304   Assert.equal(inRecord.getNextAddrAsString(), "2.2.2.2");
306   dns.clearCache(false);
307   override.clearOverrides();
310 add_task(async function test_nxdomain() {
311   override.addIPOverride(DOMAIN, "N/A");
312   let listener = new Listener();
313   dns.asyncResolve(
314     DOMAIN,
315     Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
316     Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
317     null,
318     listener,
319     mainThread,
320     defaultOriginAttributes
321   );
323   let [, , inStatus] = await listener;
324   equal(inStatus, Cr.NS_ERROR_UNKNOWN_HOST);