269 lines
7 KiB
JavaScript
269 lines
7 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
"use strict";
|
|
|
|
const { HttpServer } = ChromeUtils.importESModule(
|
|
"resource://testing-common/httpd.sys.mjs"
|
|
);
|
|
|
|
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);
|
|
|
|
// We don't normally allow localhost channels to be proxied, but this
|
|
// is easier than updating all the certs and/or domains.
|
|
Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
|
|
registerCleanupFunction(() => {
|
|
Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
|
|
});
|
|
|
|
// 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
|
|
);
|
|
|
|
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();
|
|
});
|