Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
-
CI results over the last 21 days367Runs100%Pass0Failures0Timeouts0Crashes102Skips
Scheduled runs skipped per day (up to 22.2%) Sep 28Oct 18 - This test gets skipped with pattern: os == 'win' && os_version == '11.26200' && arch == 'x86_64' && msix OR os == 'android' && os_version == '14' && arch == 'x86_64' && debug OR os == 'android' && os_version == '14' && arch == 'x86_64' && opt OR os == 'android' && os_version == '14' && arch == 'x86_64' && ccov
- This test runs only with pattern: !socketprocess_networking
- Manifest: dom/webtransport/test/xpcshell/xpcshell.toml
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
// Tests for new WebTransport features:
// * protocol attribute
// * draining promise
// * createSendGroup()
// * createWritable()
// * exportKeyingMaterial()
// * getStats()
// Very basic tests; most of this is tested via WPT tests
"use strict";
var h3Port;
var host;
registerCleanupFunction(async () => {
Services.prefs.clearUserPref("network.dns.localDomains");
Services.prefs.clearUserPref("network.webtransport.enabled");
});
var { NetUtil } = ChromeUtils.importESModule(
"resource://gre/modules/NetUtil.sys.mjs"
);
function readFile(file) {
let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(
Ci.nsIFileInputStream
);
fstream.init(file, -1, 0, 0);
let data = NetUtil.readInputStreamToString(fstream, fstream.available());
fstream.close();
return data;
}
function addCertFromFile(certdb, filename, trustString) {
let certFile = do_get_file(filename, false);
let pem = readFile(certFile)
.replace(/-----BEGIN CERTIFICATE-----/, "")
.replace(/-----END CERTIFICATE-----/, "")
.replace(/[\r\n]/g, "");
certdb.addCertFromBase64(pem, trustString);
}
add_setup(async function setup() {
Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
Services.prefs.setBoolPref("network.webtransport.enabled", true);
h3Port = Services.env.get("MOZHTTP3_PORT");
Assert.notEqual(h3Port, null);
Assert.notEqual(h3Port, "");
host = "foo.example.com:" + h3Port;
do_get_profile();
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
addCertFromFile(
certdb,
"../../../../netwerk/test/unit/http2-ca.pem",
"CTu,u,u"
);
});
add_task(async function test_protocol_attribute() {
await wt.ready;
// Protocol attribute should be empty string when no protocols specified
Assert.equal(wt.protocol, "");
wt.close();
await wt.closed;
});
add_task(async function test_draining_promise() {
await wt.ready;
// Draining promise should exist
Assert.notEqual(wt.draining, null);
Assert.equal(typeof wt.draining.then, "function");
wt.close();
await wt.closed;
});
add_task(async function test_createSendGroup() {
await wt.ready;
// Create a send group
const sendGroup = wt.createSendGroup();
Assert.notEqual(sendGroup, null);
wt.close();
await wt.closed;
});
add_task(async function test_createWritable() {
await wt.ready;
// Create a writable datagram stream
const writable = wt.datagrams.createWritable();
Assert.notEqual(writable, null);
// Writable should have sendGroup and sendOrder attributes
Assert.equal(writable.sendGroup, null);
Assert.equal(writable.sendOrder, 0);
// Set sendOrder
writable.sendOrder = 42;
Assert.equal(writable.sendOrder, 42);
wt.close();
await wt.closed;
});
add_task(async function test_createWritable_with_options() {
await wt.ready;
// Create a send group
const sendGroup = wt.createSendGroup();
// Create a writable with options
const writable = wt.datagrams.createWritable({
sendOrder: 100,
sendGroup,
});
Assert.notEqual(writable, null);
Assert.equal(writable.sendOrder, 100);
Assert.equal(writable.sendGroup, sendGroup);
wt.close();
await wt.closed;
});
add_task(async function test_exportKeyingMaterial() {
await wt.ready;
// Export keying material with an empty context
const label = new TextEncoder().encode("test-label");
const keyMaterial = await wt.exportKeyingMaterial(
label,
new Uint8Array(0),
32
);
Assert.notEqual(keyMaterial, null);
Assert.equal(ArrayBuffer.isView(keyMaterial), true);
// Export with a non-empty context
const context = new TextEncoder().encode("test-context");
const keyMaterial2 = await wt.exportKeyingMaterial(label, context, 32);
Assert.notEqual(keyMaterial2, null);
Assert.equal(ArrayBuffer.isView(keyMaterial2), true);
wt.close();
await wt.closed;
});
add_task(async function test_getStats() {
await wt.ready;
const stats = await wt.getStats();
Assert.notEqual(stats, null);
// Numeric connection stats
Assert.equal(typeof stats.bytesSent, "number");
// bytesSentOverhead is omitted: Firefox cannot decompose bytesSent into
// spec requires unavailable stats to be absent from the dictionary.
Assert.equal(typeof stats.bytesSentOverhead, "undefined");
Assert.equal(typeof stats.bytesAcknowledged, "number");
Assert.equal(typeof stats.packetsSent, "number");
Assert.equal(typeof stats.bytesLost, "number");
Assert.equal(typeof stats.packetsLost, "number");
Assert.equal(typeof stats.bytesReceived, "number");
Assert.equal(typeof stats.packetsReceived, "number");
// RTT fields
Assert.equal(typeof stats.smoothedRtt, "number");
Assert.equal(typeof stats.rttVariation, "number");
Assert.equal(typeof stats.minRtt, "number");
// estimatedSendRate is nullable
Assert.ok(
stats.estimatedSendRate === null ||
typeof stats.estimatedSendRate === "number"
);
// Boolean capacity indicator
Assert.equal(typeof stats.atSendCapacity, "boolean");
// Datagram sub-stats (required field)
Assert.notEqual(stats.datagrams, null);
Assert.equal(typeof stats.datagrams.droppedIncoming, "number");
Assert.equal(typeof stats.datagrams.expiredIncoming, "number");
Assert.equal(typeof stats.datagrams.expiredOutgoing, "number");
Assert.equal(typeof stats.datagrams.lostOutgoing, "number");
wt.close();
await wt.closed;
});
add_task(async function test_sendGroup_validation() {
await wt1.ready;
await wt2.ready;
// Create send group on wt1
const sendGroup = wt1.createSendGroup();
// Try to use send group from wt1 on wt2's stream - should fail
try {
await wt2.createUnidirectionalStream({ sendGroup });
Assert.ok(false, "Should have thrown InvalidStateError");
} catch (e) {
Assert.equal(e.name, "InvalidStateError");
}
wt1.close();
wt2.close();
await wt1.closed;
await wt2.closed;
});
add_task(async function test_getStats_after_close() {
await wt.ready;
wt.close();
await wt.closed;
// Per spec, getStats() on a closed transport returns the last cached stats.
const stats = await wt.getStats();
Assert.notEqual(stats, null);
Assert.equal(typeof stats.bytesSent, "number");
Assert.equal(typeof stats.bytesReceived, "number");
Assert.notEqual(stats.datagrams, null);
});
add_task(async function test_closed_state_errors() {
await wt.ready;
wt.close();
await wt.closed;
try {
await wt.exportKeyingMaterial(
new Uint8Array([1, 2, 3]),
new Uint8Array(0),
32
);
Assert.ok(false, "exportKeyingMaterial should have thrown");
} catch (e) {
Assert.equal(e.name, "InvalidStateError");
}
});