Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const { HttpServer } = ChromeUtils.importESModule(
);
const { TelemetryUtils } = ChromeUtils.importESModule(
"resource://gre/modules/TelemetryUtils.sys.mjs"
);
// Enable the collection (during test) for all products so even products
// that don't collect the data will be able to run the test without failure.
Services.prefs.setBoolPref(
"toolkit.telemetry.testing.overrideProductsCheck",
true
);
Services.prefs.setBoolPref("network.dns.native-is-localhost", true);
// Trigger a proper telemetry init.
do_get_profile(true);
AddonTestUtils.init(this);
AddonTestUtils.overrideCertDB();
AddonTestUtils.createAppInfo(
"xpcshell@tests.mozilla.org",
"XPCShell",
"42",
"42"
);
// setup and configure a proxy server that will just deny connections.
const proxy = AddonTestUtils.createHttpServer();
proxy.registerPrefixHandler("/", (request, response) => {
response.setStatusLine(request.httpVersion, 504, "hello proxy user");
response.write("ok!");
});
// Register a proxy to be used by TCPSocket connections later.
let proxy_info;
function getBadProxyPort() {
let server = new HttpServer();
server.start(-1);
const badPort = server.identity.primaryPort;
server.stop();
return badPort;
}
function registerProxy() {
let pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(
Ci.nsIProtocolProxyService
);
const proxyFilter = {
applyFilter(uri, defaultProxyInfo, callback) {
if (
proxy_info &&
uri.host == PingServer.host &&
uri.port == PingServer.port
) {
let proxyInfo = pps.newProxyInfo(
proxy_info.type,
proxy_info.host,
proxy_info.port,
"",
"",
0,
4096,
null
);
proxyInfo.sourceId = proxy_info.sourceId;
callback.onProxyFilterResult(proxyInfo);
} else {
callback.onProxyFilterResult(defaultProxyInfo);
}
},
};
pps.registerFilter(proxyFilter, 0);
registerCleanupFunction(() => {
pps.unregisterFilter(proxyFilter);
});
}
add_task(async function setup() {
fakeIntlReady();
// Make sure we don't generate unexpected pings due to pref changes.
await setEmptyPrefWatchlist();
Services.prefs.setBoolPref(
TelemetryUtils.Preferences.HealthPingEnabled,
false
);
TelemetryStopwatch.setTestModeEnabled(true);
registerProxy();
PingServer.start();
// accept proxy connections for PingServer
proxy.identity.add("http", PingServer.host, PingServer.port);
await TelemetrySend.setup(true);
TelemetrySend.setTestModeEnabled(true);
TelemetrySend.setServer(`http://localhost:${PingServer.port}`);
});
function checkEvent() {
// ServiceRequest should have recorded an event for this.
let expected = [
"service_request",
"bypass",
"proxy_info",
"telemetry.send",
{
source: proxy_info.sourceId,
type: "api",
},
];
let snapshot = Telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_ALL_CHANNELS,
false
);
let received = snapshot.parent[0];
received.shift();
Assert.deepEqual(
expected,
received,
`retry telemetry data matched ${JSON.stringify(received)}`
);
Telemetry.clearEvents();
}
async function submitPingWithDate(date, expected) {
fakeNow(new Date(date));
let pingId = await TelemetryController.submitExternalPing(
"test-send-date-header",
{}
);
let req = await PingServer.promiseNextRequest();
let ping = decodeRequestPayload(req);
Assert.equal(
req.getHeader("Date"),
expected,
"Telemetry should send the correct Date header with requests."
);
Assert.equal(ping.id, pingId, "Should have received the correct ping id.");
}
// While there is no specific indiction, this test causes the
// telemetrySend doPing onload handler to be invoked.
add_task(async function test_failed_server() {
proxy_info = {
type: "http",
host: proxy.identity.primaryHost,
port: proxy.identity.primaryPort,
sourceId: "failed_server_test",
};
await TelemetrySend.reset();
await submitPingWithDate(
Date.UTC(2011, 1, 1, 11, 0, 0),
"Tue, 01 Feb 2011 11:00:00 GMT"
);
checkEvent();
});
// While there is no specific indiction, this test causes the
// telemetrySend doPing error handler to be invoked.
add_task(async function test_no_server() {
// Make sure the underlying proxy failover is disabled to easily force
// telemetry to retry the request.
Services.prefs.setBoolPref("network.proxy.failover_direct", false);
proxy_info = {
type: "http",
host: "localhost",
port: getBadProxyPort(),
sourceId: "no_server_test",
};
await TelemetrySend.reset();
await submitPingWithDate(
Date.UTC(2012, 1, 1, 11, 0, 0),
"Wed, 01 Feb 2012 11:00:00 GMT"
);
checkEvent();
});
// Mock out the send timer activity.
function waitForTimer() {
return new Promise(resolve => {
fakePingSendTimer(
(callback, timeout) => {
resolve([callback, timeout]);
},
() => {}
);
});
}
add_task(async function test_no_bypass() {
// Make sure the underlying proxy failover is disabled to easily force
// telemetry to retry the request.
Services.prefs.setBoolPref("network.proxy.failover_direct", false);
// Disable the retry and submit again.
Services.prefs.setBoolPref("network.proxy.allow_bypass", false);
proxy_info = {
type: "http",
host: "localhost",
port: getBadProxyPort(),
sourceId: "no_server_test",
};
await TelemetrySend.reset();
fakeNow(new Date(Date.UTC(2013, 1, 1, 11, 0, 0)));
let timerPromise = waitForTimer();
let pingId = await TelemetryController.submitExternalPing(
"test-send-date-header",
{}
);
let [pingSendTimerCallback] = await timerPromise;
Assert.ok(!!pingSendTimerCallback, "Should have a timer callback");
Assert.equal(
TelemetrySend.pendingPingCount,
1,
"Should have correct pending ping count"
);
// Reset the proxy, trigger the next tick - we should receive the ping.
proxy_info = null;
pingSendTimerCallback();
let req = await PingServer.promiseNextRequest();
let ping = decodeRequestPayload(req);
// PingServer finished before telemetry, so make sure it's done.
await TelemetrySend.testWaitOnOutgoingPings();
Assert.equal(
req.getHeader("Date"),
"Fri, 01 Feb 2013 11:00:00 GMT",
"Telemetry should send the correct Date header with requests."
);
Assert.equal(ping.id, pingId, "Should have received the correct ping id.");
// reset to save any pending pings
Assert.equal(
TelemetrySend.pendingPingCount,
0,
"Should not have any pending pings"
);
await TelemetrySend.reset();
PingServer.stop();
});