// This test checks that connection is cycled on every failure when network.trr.retry_on_recoverable_errors is true.
add_task(async function test_connection_reuse_and_cycling() {
Services.prefs.setCharPref( "network.trr.confirmationNS", "confirm.example.com"
);
setLocalModeAndURI( 2,
`https://foo.example.com:${trrServer.port()}/dns-query`
);
Services.prefs.setBoolPref("network.trr.strict_native_fallback", true);
Services.prefs.setBoolPref("network.trr.retry_on_recoverable_errors", true);
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
);
// Setting conncycle=true in the URI. Server will start logging reqs. // We will do a specific sequence of lookups, then fetch the log from // the server and check that it matches what we'd expect.
setLocalModeAndURI( 2,
`https://foo.example.com:${trrServer.port()}/dns-query?conncycle=true`
);
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
); // Confirmation upon uri-change will have created one req.
for (let i = 1; i <= 6; i++) {
await registerDomain(`bar${i}.example.org`);
}
await registerDomain("newconn.example.org");
await registerDomain("newconn2.example.org");
// Two reqs for each bar1 and bar2 - A + AAAA.
await new TRRDNSListener("bar1.example.org", "9.8.7.6");
await new TRRDNSListener("bar2.example.org", "9.8.7.6"); // Total so far: (1) + 2 + 2 = 5
// Two reqs that fail, one Confirmation req, two retried reqs that succeed.
await new TRRDNSListener("newconn.example.org", "9.8.7.6");
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
); // Total so far: (5) + 2 + 1 + 2 = 10
// Two reqs for each bar3 and bar4 .
await new TRRDNSListener("bar3.example.org", "9.8.7.6");
await new TRRDNSListener("bar4.example.org", "9.8.7.6"); // Total so far: (10) + 2 + 2 = 14.
// Two reqs that fail, one Confirmation req, two retried reqs that succeed.
await new TRRDNSListener("newconn2.example.org", "9.8.7.6");
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
); // Total so far: (14) + 2 + 1 + 2 = 19
// Two reqs for each bar5 and bar6 .
await new TRRDNSListener("bar5.example.org", "9.8.7.6");
await new TRRDNSListener("bar6.example.org", "9.8.7.6"); // Total so far: (19) + 2 + 2 = 23
let dohReqPortLog = await trrServer.execute(`global.gDoHPortsLog`);
info(JSON.stringify(dohReqPortLog));
// Since the actual ports seen will vary at runtime, we use placeholders // instead in our expected output definition. For example, if two entries // both have "port1", it means they both should have the same port in the // server's log. // For reqs that fail and trigger a Confirmation + retry, the retried reqs // might not re-use the new connection created for Confirmation due to a // race, so we have an extra alternate expected port for them. This lets // us test that they use *a* new port even if it's not *the* new port. // Subsequent lookups are not affected, they will use the same conn as // the Confirmation req.
let expectedLogTemplate = [
["confirm.example.com", "port1"],
["bar1.example.org", "port1"],
["bar1.example.org", "port1"],
["bar2.example.org", "port1"],
["bar2.example.org", "port1"],
["newconn.example.org", "port1"],
["newconn.example.org", "port1"],
["confirm.example.com", "port2"],
["newconn.example.org", "port2"],
["newconn.example.org", "port2"],
["bar3.example.org", "port2"],
["bar3.example.org", "port2"],
["bar4.example.org", "port2"],
["bar4.example.org", "port2"],
["newconn2.example.org", "port2"],
["newconn2.example.org", "port2"],
["confirm.example.com", "port3"],
["newconn2.example.org", "port3"],
["newconn2.example.org", "port3"],
["bar5.example.org", "port3"],
["bar5.example.org", "port3"],
["bar6.example.org", "port3"],
["bar6.example.org", "port3"],
];
if (expectedLogTemplate.length != dohReqPortLog.length) { // This shouldn't happen, and if it does, we'll fail the assertion // below. But first dump the whole server-side log to help with // debugging should we see a failure. Most likely cause would be // that another consumer of TRR happened to make a request while // the test was running and polluted the log.
info(dohReqPortLog);
}
equal(
expectedLogTemplate.length,
dohReqPortLog.length, "Correct number of req log entries"
);
let seenPorts = new Set(); // This is essentially a symbol table - as we iterate through the log // we will assign the actual seen port numbers to the placeholders.
let seenPortsByExpectedPort = new Map();
for (let i = 0; i < expectedLogTemplate.length; i++) {
let expectedName = expectedLogTemplate[i][0];
let expectedPort = expectedLogTemplate[i][1];
let seenName = dohReqPortLog[i][0];
let seenPort = dohReqPortLog[i][1];
info(`Checking log entry. Name: ${seenName}, Port: ${seenPort}`);
equal(expectedName, seenName, "Name matches for entry " + i); if (!seenPortsByExpectedPort.has(expectedPort)) {
ok(!seenPorts.has(seenPort), "Port should not have been previously used");
seenPorts.add(seenPort);
seenPortsByExpectedPort.set(expectedPort, seenPort);
} else {
equal(
seenPort,
seenPortsByExpectedPort.get(expectedPort), "Connection was reused as expected"
);
}
}
// Clear log for the next test.
await trrServer.execute(
`global.gDoHPortsLog = []; global.gDoHNewConnLog = {};`
);
});
// network.trr.retry_on_recoverable_errors = false // This test unregisters the confirmation NS (server will return HTTP error code 500) before newconn resolutions // The newconn resolutions will fail, triggering a confirmation. The second confirmation will cycle the connection. // We check that the connection is cycled at least once for every newconn resolution.
add_task(async function test_connection_reuse_and_cycling2() {
Services.prefs.setBoolPref("network.trr.retry_on_recoverable_errors", false);
Services.dns.clearCache(true);
Services.prefs.setCharPref( "network.trr.confirmationNS", "confirm.example.com"
);
setLocalModeAndURI( 2,
`https://foo.example.com:${trrServer.port()}/dns-query`
);
Services.prefs.setBoolPref("network.trr.strict_native_fallback", true);
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
);
// Setting conncycle=true in the URI. Server will start logging reqs. // We will do a specific sequence of lookups, then fetch the log from // the server and check that it matches what we'd expect.
setLocalModeAndURI( 2,
`https://foo.example.com:${trrServer.port()}/dns-query?conncycle=true`
);
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
); // Confirmation upon uri-change will have created one req.
for (let i = 1; i <= 6; i++) {
await registerDomain(`bar${i}.example.org`);
}
await registerDomain("newconn.example.org");
await registerDomain("newconn2.example.org");
await new TRRDNSListener("bar1.example.org", "9.8.7.6");
await new TRRDNSListener("bar2.example.org", "9.8.7.6");
let initialPort = await trrServer.execute(
`global.gDoHPortsLog[global.gDoHPortsLog.length-1]`
); // This one will fallback because of the timeout
await unregisterNS();
await new TRRDNSListener("newconn.example.org", "127.0.0.1");
await TestUtils.waitForCondition( // 3 => CONFIRM_FAILED
() => Services.dns.currentTrrConfirmationState == 3,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
);
await registerNS();
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
);
let newConfirmationPort = await trrServer.execute(
`global.gDoHPortsLog[global.gDoHPortsLog.length-1]`
);
// Two reqs for each bar3 and bar4 .
await new TRRDNSListener("bar3.example.org", "9.8.7.6");
await new TRRDNSListener("bar4.example.org", "9.8.7.6");
initialPort = await trrServer.execute(
`global.gDoHPortsLog[global.gDoHPortsLog.length-1]`
);
await unregisterNS(); // This one will fallback because of the timeout
await new TRRDNSListener("newconn2.example.org", "127.0.0.1");
await TestUtils.waitForCondition( // 3 => CONFIRM_FAILED
() => Services.dns.currentTrrConfirmationState == 3,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
);
await registerNS();
await TestUtils.waitForCondition( // 2 => CONFIRM_OK
() => Services.dns.currentTrrConfirmationState == 2,
`Timed out waiting for confirmation success. Currently ${Services.dns.currentTrrConfirmationState}`, 1, 5000
);
newConfirmationPort = await trrServer.execute(
`global.gDoHPortsLog[global.gDoHPortsLog.length-1]`
);
notEqual(
initialPort,
newConfirmationPort, "Failed confirmation must cycle the connection"
);
// Two reqs for each bar5 and bar6 .
await new TRRDNSListener("bar5.example.org", "9.8.7.6");
await new TRRDNSListener("bar6.example.org", "9.8.7.6");
let dohReqPortLog = await trrServer.execute(`global.gDoHPortsLog`);
const uniquePorts = new Set(dohReqPortLog.map(([_, port]) => port)); if (uniquePorts.size < 3) {
info(JSON.stringify(dohReqPortLog));
}
greaterOrEqual(
uniquePorts.size, 3, "Connection must be cycled at least twice"
);
});
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-02)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.