summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_http_server_timing.js
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/unit/test_http_server_timing.js')
-rw-r--r--netwerk/test/unit/test_http_server_timing.js138
1 files changed, 138 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_http_server_timing.js b/netwerk/test/unit/test_http_server_timing.js
new file mode 100644
index 0000000000..2e71c65c1e
--- /dev/null
+++ b/netwerk/test/unit/test_http_server_timing.js
@@ -0,0 +1,138 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* eslint-env node */
+
+"use strict";
+
+class ServerCode {
+ static async startServer(port) {
+ global.http = require("http");
+ global.server = global.http.createServer((req, res) => {
+ res.setHeader("Content-Type", "text/plain");
+ res.setHeader("Content-Length", "12");
+ res.setHeader("Transfer-Encoding", "chunked");
+ res.setHeader("Trailer", "Server-Timing");
+ res.setHeader(
+ "Server-Timing",
+ "metric; dur=123.4; desc=description, metric2; dur=456.78; desc=description1"
+ );
+ res.write("data reached");
+ res.addTrailers({
+ "Server-Timing":
+ "metric3; dur=789.11; desc=description2, metric4; dur=1112.13; desc=description3",
+ });
+ res.end();
+ });
+
+ let serverPort = await new Promise(resolve => {
+ global.server.listen(0, "0.0.0.0", 2000, () => {
+ resolve(global.server.address().port);
+ });
+ });
+
+ if (process.env.MOZ_ANDROID_DATA_DIR) {
+ // When creating a server on Android we must make sure that the port
+ // is forwarded from the host machine to the emulator.
+ let adb_path = "adb";
+ if (process.env.MOZ_FETCHES_DIR) {
+ adb_path = `${process.env.MOZ_FETCHES_DIR}/android-sdk-linux/platform-tools/adb`;
+ }
+
+ await new Promise(resolve => {
+ const { exec } = require("child_process");
+ exec(
+ `${adb_path} reverse tcp:${serverPort} tcp:${serverPort}`,
+ (error, stdout, stderr) => {
+ if (error) {
+ console.log(`error: ${error.message}`);
+ return;
+ }
+ if (stderr) {
+ console.log(`stderr: ${stderr}`);
+ }
+ // console.log(`stdout: ${stdout}`);
+ resolve();
+ }
+ );
+ });
+ }
+
+ return serverPort;
+ }
+}
+
+const responseServerTiming = [
+ { metric: "metric", duration: "123.4", description: "description" },
+ { metric: "metric2", duration: "456.78", description: "description1" },
+];
+const trailerServerTiming = [
+ { metric: "metric3", duration: "789.11", description: "description2" },
+ { metric: "metric4", duration: "1112.13", description: "description3" },
+];
+
+let port;
+
+add_task(async function setup() {
+ let processId = await NodeServer.fork();
+ registerCleanupFunction(async () => {
+ await NodeServer.kill(processId);
+ });
+ await NodeServer.execute(processId, ServerCode);
+ port = await NodeServer.execute(processId, `ServerCode.startServer(0)`);
+ ok(port);
+});
+
+// Test that secure origins can use server-timing, even with plain http
+add_task(async function test_localhost_origin() {
+ let chan = NetUtil.newChannel({
+ uri: `http://localhost:${port}/`,
+ loadUsingSystemPrincipal: true,
+ });
+ await new Promise(resolve => {
+ chan.asyncOpen(
+ new ChannelListener((request, buffer) => {
+ let channel = request.QueryInterface(Ci.nsITimedChannel);
+ let headers = channel.serverTiming.QueryInterface(Ci.nsIArray);
+ ok(headers.length);
+
+ let expectedResult = responseServerTiming.concat(trailerServerTiming);
+ Assert.equal(headers.length, expectedResult.length);
+
+ for (let i = 0; i < expectedResult.length; i++) {
+ let header = headers.queryElementAt(i, Ci.nsIServerTiming);
+ Assert.equal(header.name, expectedResult[i].metric);
+ Assert.equal(header.description, expectedResult[i].description);
+ Assert.equal(header.duration, parseFloat(expectedResult[i].duration));
+ }
+ resolve();
+ }, null)
+ );
+ });
+});
+
+// Test that insecure origins can't use server timing.
+add_task(async function test_http_non_localhost() {
+ Services.prefs.setBoolPref("network.dns.native-is-localhost", true);
+ registerCleanupFunction(async () => {
+ Services.prefs.clearUserPref("network.dns.native-is-localhost");
+ });
+
+ let chan = NetUtil.newChannel({
+ uri: `http://example.org:${port}/`,
+ loadUsingSystemPrincipal: true,
+ });
+ await new Promise(resolve => {
+ chan.asyncOpen(
+ new ChannelListener((request, buffer) => {
+ let channel = request.QueryInterface(Ci.nsITimedChannel);
+ let headers = channel.serverTiming.QueryInterface(Ci.nsIArray);
+ Assert.equal(headers.length, 0);
+ resolve();
+ }, null)
+ );
+ });
+});