Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / netwerk / test / unit / test_dns_override.js
blob7e5a5246d1e60724d8d7826515c2533517f4bffe
1 "use strict";
3 const override = Cc["@mozilla.org/network/native-dns-override;1"].getService(
4 Ci.nsINativeDNSResolverOverride
5 );
6 const defaultOriginAttributes = {};
7 const mainThread = Services.tm.currentThread;
9 class Listener {
10 constructor() {
11 this.promise = new Promise(resolve => {
12 this.resolve = resolve;
13 });
16 onLookupComplete(inRequest, inRecord, inStatus) {
17 this.resolve([inRequest, inRecord, inStatus]);
20 async firstAddress() {
21 let all = await this.addresses();
22 if (all.length) {
23 return all[0];
26 return undefined;
29 async addresses() {
30 let [, inRecord] = await this.promise;
31 let addresses = [];
32 if (!inRecord) {
33 return addresses; // returns []
35 inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
36 while (inRecord.hasMore()) {
37 addresses.push(inRecord.getNextAddrAsString());
39 return addresses;
42 then() {
43 return this.promise.then.apply(this.promise, arguments);
46 Listener.prototype.QueryInterface = ChromeUtils.generateQI(["nsIDNSListener"]);
48 const DOMAIN = "example.org";
49 const OTHER = "example.com";
51 add_setup(async function setup() {
52 trr_test_setup();
54 registerCleanupFunction(async () => {
55 trr_clear_prefs();
56 });
57 });
59 add_task(async function test_bad_IPs() {
60 Assert.throws(
61 () => override.addIPOverride(DOMAIN, DOMAIN),
62 /NS_ERROR_UNEXPECTED/,
63 "Should throw if input is not an IP address"
65 Assert.throws(
66 () => override.addIPOverride(DOMAIN, ""),
67 /NS_ERROR_UNEXPECTED/,
68 "Should throw if input is not an IP address"
70 Assert.throws(
71 () => override.addIPOverride(DOMAIN, " "),
72 /NS_ERROR_UNEXPECTED/,
73 "Should throw if input is not an IP address"
75 Assert.throws(
76 () => override.addIPOverride(DOMAIN, "1-2-3-4"),
77 /NS_ERROR_UNEXPECTED/,
78 "Should throw if input is not an IP address"
80 });
82 add_task(async function test_ipv4() {
83 let listener = new Listener();
84 override.addIPOverride(DOMAIN, "1.2.3.4");
85 Services.dns.asyncResolve(
86 DOMAIN,
87 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
89 null,
90 listener,
91 mainThread,
92 defaultOriginAttributes
94 Assert.equal(await listener.firstAddress(), "1.2.3.4");
96 Services.dns.clearCache(false);
97 override.clearOverrides();
98 });
100 add_task(async function test_ipv6() {
101 let listener = new Listener();
102 override.addIPOverride(DOMAIN, "fe80::6a99:9b2b:6ccc:6e1b");
103 Services.dns.asyncResolve(
104 DOMAIN,
105 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
107 null,
108 listener,
109 mainThread,
110 defaultOriginAttributes
112 Assert.equal(await listener.firstAddress(), "fe80::6a99:9b2b:6ccc:6e1b");
114 Services.dns.clearCache(false);
115 override.clearOverrides();
118 add_task(async function test_clearOverrides() {
119 let listener = new Listener();
120 override.addIPOverride(DOMAIN, "1.2.3.4");
121 Services.dns.asyncResolve(
122 DOMAIN,
123 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
125 null,
126 listener,
127 mainThread,
128 defaultOriginAttributes
130 Assert.equal(await listener.firstAddress(), "1.2.3.4");
132 Services.dns.clearCache(false);
133 override.clearOverrides();
135 listener = new Listener();
136 Services.dns.asyncResolve(
137 DOMAIN,
138 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
140 null,
141 listener,
142 mainThread,
143 defaultOriginAttributes
145 Assert.notEqual(await listener.firstAddress(), "1.2.3.4");
147 await new Promise(resolve => do_timeout(1000, resolve));
148 Services.dns.clearCache(false);
149 override.clearOverrides();
152 add_task(async function test_clearHostOverride() {
153 override.addIPOverride(DOMAIN, "2.2.2.2");
154 override.addIPOverride(OTHER, "2.2.2.2");
155 override.clearHostOverride(DOMAIN);
156 let listener = new Listener();
157 Services.dns.asyncResolve(
158 DOMAIN,
159 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
161 null,
162 listener,
163 mainThread,
164 defaultOriginAttributes
167 Assert.notEqual(await listener.firstAddress(), "2.2.2.2");
169 listener = new Listener();
170 Services.dns.asyncResolve(
171 OTHER,
172 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
174 null,
175 listener,
176 mainThread,
177 defaultOriginAttributes
179 Assert.equal(await listener.firstAddress(), "2.2.2.2");
181 // Note: this test will use the actual system resolver. On windows we do a
182 // second async call to the system libraries to get the TTL values, which
183 // keeps the record alive after the onLookupComplete()
184 // We need to wait for a bit, until the second call is finished before we
185 // can clear the cache to make sure we evict everything.
186 // If the next task ever starts failing, with an IP that is not in this
187 // file, then likely the timeout is too small.
188 await new Promise(resolve => do_timeout(1000, resolve));
189 Services.dns.clearCache(false);
190 override.clearOverrides();
193 add_task(async function test_multiple_IPs() {
194 override.addIPOverride(DOMAIN, "2.2.2.2");
195 override.addIPOverride(DOMAIN, "1.1.1.1");
196 override.addIPOverride(DOMAIN, "::1");
197 override.addIPOverride(DOMAIN, "fe80::6a99:9b2b:6ccc:6e1b");
198 let listener = new Listener();
199 Services.dns.asyncResolve(
200 DOMAIN,
201 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
203 null,
204 listener,
205 mainThread,
206 defaultOriginAttributes
208 Assert.deepEqual(await listener.addresses(), [
209 "2.2.2.2",
210 "1.1.1.1",
211 "::1",
212 "fe80::6a99:9b2b:6ccc:6e1b",
215 Services.dns.clearCache(false);
216 override.clearOverrides();
219 add_task(async function test_address_family_flags() {
220 override.addIPOverride(DOMAIN, "2.2.2.2");
221 override.addIPOverride(DOMAIN, "1.1.1.1");
222 override.addIPOverride(DOMAIN, "::1");
223 override.addIPOverride(DOMAIN, "fe80::6a99:9b2b:6ccc:6e1b");
224 let listener = new Listener();
225 Services.dns.asyncResolve(
226 DOMAIN,
227 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
228 Ci.nsIDNSService.RESOLVE_DISABLE_IPV4,
229 null,
230 listener,
231 mainThread,
232 defaultOriginAttributes
234 Assert.deepEqual(await listener.addresses(), [
235 "::1",
236 "fe80::6a99:9b2b:6ccc:6e1b",
239 listener = new Listener();
240 Services.dns.asyncResolve(
241 DOMAIN,
242 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
243 Ci.nsIDNSService.RESOLVE_DISABLE_IPV6,
244 null,
245 listener,
246 mainThread,
247 defaultOriginAttributes
249 Assert.deepEqual(await listener.addresses(), ["2.2.2.2", "1.1.1.1"]);
251 Services.dns.clearCache(false);
252 override.clearOverrides();
255 add_task(async function test_cname_flag() {
256 override.addIPOverride(DOMAIN, "2.2.2.2");
257 let listener = new Listener();
258 Services.dns.asyncResolve(
259 DOMAIN,
260 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
262 null,
263 listener,
264 mainThread,
265 defaultOriginAttributes
267 let [, inRecord] = await listener;
268 inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
269 Assert.throws(
270 () => inRecord.canonicalName,
271 /NS_ERROR_NOT_AVAILABLE/,
272 "No canonical name flag"
274 Assert.equal(inRecord.getNextAddrAsString(), "2.2.2.2");
276 listener = new Listener();
277 Services.dns.asyncResolve(
278 DOMAIN,
279 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
280 Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
281 null,
282 listener,
283 mainThread,
284 defaultOriginAttributes
286 [, inRecord] = await listener;
287 inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
288 Assert.equal(inRecord.canonicalName, DOMAIN, "No canonical name specified");
289 Assert.equal(inRecord.getNextAddrAsString(), "2.2.2.2");
291 Services.dns.clearCache(false);
292 override.clearOverrides();
294 override.addIPOverride(DOMAIN, "2.2.2.2");
295 override.setCnameOverride(DOMAIN, OTHER);
296 listener = new Listener();
297 Services.dns.asyncResolve(
298 DOMAIN,
299 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
300 Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
301 null,
302 listener,
303 mainThread,
304 defaultOriginAttributes
306 [, inRecord] = await listener;
307 inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
308 Assert.equal(inRecord.canonicalName, OTHER, "Must have correct CNAME");
309 Assert.equal(inRecord.getNextAddrAsString(), "2.2.2.2");
311 Services.dns.clearCache(false);
312 override.clearOverrides();
315 add_task(async function test_nxdomain() {
316 override.addIPOverride(DOMAIN, "N/A");
317 let listener = new Listener();
318 Services.dns.asyncResolve(
319 DOMAIN,
320 Ci.nsIDNSService.RESOLVE_TYPE_DEFAULT,
321 Ci.nsIDNSService.RESOLVE_CANONICAL_NAME,
322 null,
323 listener,
324 mainThread,
325 defaultOriginAttributes
328 let [, , inStatus] = await listener;
329 equal(inStatus, Cr.NS_ERROR_UNKNOWN_HOST);
332 function makeChan(url) {
333 let chan = NetUtil.newChannel({
334 uri: url,
335 loadUsingSystemPrincipal: true,
336 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
337 }).QueryInterface(Ci.nsIHttpChannel);
338 return chan;
341 function channelOpenPromise(chan, flags) {
342 return new Promise(resolve => {
343 function finish(req, buffer) {
344 resolve([req, buffer]);
346 chan.asyncOpen(new ChannelListener(finish, null, flags));
350 function hexToUint8Array(hex) {
351 return new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
354 add_task(
356 skip_if: () =>
357 mozinfo.os == "win" ||
358 mozinfo.os == "android" ||
359 mozinfo.socketprocess_networking,
361 async function test_https_record_override() {
362 let trrServer = new TRRServer();
363 await trrServer.start();
364 registerCleanupFunction(async () => {
365 await trrServer.stop();
368 await trrServer.registerDoHAnswers("service.com", "HTTPS", {
369 answers: [
371 name: "service.com",
372 ttl: 55,
373 type: "HTTPS",
374 flush: false,
375 data: {
376 priority: 1,
377 name: ".",
378 values: [
379 { key: "alpn", value: ["h2", "h3"] },
380 { key: "no-default-alpn" },
381 { key: "port", value: 8888 },
382 { key: "ipv4hint", value: "1.2.3.4" },
383 { key: "echconfig", value: "123..." },
384 { key: "ipv6hint", value: "::1" },
385 { key: "odoh", value: "456..." },
390 name: "service.com",
391 ttl: 55,
392 type: "HTTPS",
393 flush: false,
394 data: {
395 priority: 2,
396 name: "test.com",
397 values: [
398 { key: "alpn", value: "h2" },
399 { key: "ipv4hint", value: ["1.2.3.4", "5.6.7.8"] },
400 { key: "echconfig", value: "abc..." },
401 { key: "ipv6hint", value: ["::1", "fe80::794f:6d2c:3d5e:7836"] },
402 { key: "odoh", value: "def..." },
409 let chan = makeChan(
410 `https://foo.example.com:${trrServer.port()}/dnsAnswer?host=service.com&type=HTTPS`
412 let [, buf] = await channelOpenPromise(chan);
413 let rawBuffer = hexToUint8Array(buf);
415 override.addHTTPSRecordOverride("service.com", rawBuffer, rawBuffer.length);
417 Services.prefs.setBoolPref("network.dns.native_https_query", true);
418 registerCleanupFunction(async () => {
419 Services.prefs.clearUserPref("network.dns.native_https_query");
420 Services.prefs.clearUserPref("network.trr.excluded-domains");
423 let listener = new Listener();
424 Services.dns.asyncResolve(
425 "service.com",
426 Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
428 null,
429 listener,
430 mainThread,
431 defaultOriginAttributes
434 let [, inRecord, inStatus] = await listener;
435 equal(inStatus, Cr.NS_OK);
436 Assert.ok(
437 !inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).IsTRR(),
438 "resolved by Native"
440 let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
441 equal(answer[0].priority, 1);
442 equal(answer[0].name, "service.com");
443 Assert.deepEqual(
444 answer[0].values[0].QueryInterface(Ci.nsISVCParamAlpn).alpn,
445 ["h2", "h3"],
446 "got correct answer"
448 Assert.ok(
449 answer[0].values[1].QueryInterface(Ci.nsISVCParamNoDefaultAlpn),
450 "got correct answer"
452 Assert.equal(
453 answer[0].values[2].QueryInterface(Ci.nsISVCParamPort).port,
454 8888,
455 "got correct answer"
457 Assert.equal(
458 answer[0].values[3].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[0]
459 .address,
460 "1.2.3.4",
461 "got correct answer"
463 Assert.equal(
464 answer[0].values[4].QueryInterface(Ci.nsISVCParamEchConfig).echconfig,
465 "123...",
466 "got correct answer"
468 Assert.equal(
469 answer[0].values[5].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[0]
470 .address,
471 "::1",
472 "got correct answer"
474 Assert.equal(
475 answer[0].values[6].QueryInterface(Ci.nsISVCParamODoHConfig).ODoHConfig,
476 "456...",
477 "got correct answer"
480 Assert.equal(answer[1].priority, 2);
481 Assert.equal(answer[1].name, "test.com");
482 Assert.equal(answer[1].values.length, 5);
483 Assert.deepEqual(
484 answer[1].values[0].QueryInterface(Ci.nsISVCParamAlpn).alpn,
485 ["h2"],
486 "got correct answer"
488 Assert.equal(
489 answer[1].values[1].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[0]
490 .address,
491 "1.2.3.4",
492 "got correct answer"
494 Assert.equal(
495 answer[1].values[1].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[1]
496 .address,
497 "5.6.7.8",
498 "got correct answer"
500 Assert.equal(
501 answer[1].values[2].QueryInterface(Ci.nsISVCParamEchConfig).echconfig,
502 "abc...",
503 "got correct answer"
505 Assert.equal(
506 answer[1].values[3].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[0]
507 .address,
508 "::1",
509 "got correct answer"
511 Assert.equal(
512 answer[1].values[3].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[1]
513 .address,
514 "fe80::794f:6d2c:3d5e:7836",
515 "got correct answer"
517 Assert.equal(
518 answer[1].values[4].QueryInterface(Ci.nsISVCParamODoHConfig).ODoHConfig,
519 "def...",
520 "got correct answer"
523 // Adding "service.com" into excluded-domains should fail
524 // native HTTPS query.
525 Services.prefs.setCharPref("network.trr.excluded-domains", "service.com");
526 listener = new Listener();
527 try {
528 Services.dns.asyncResolve(
529 "service.com",
530 Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
532 null,
533 listener,
534 mainThread,
535 defaultOriginAttributes
537 Assert.ok(false, "asyncResolve should fail");
538 } catch (e) {
539 Assert.equal(e.result, Cr.NS_ERROR_UNKNOWN_HOST);