diff options
Diffstat (limited to 'devtools/client/webide/test/test_telemetry.html')
-rw-r--r-- | devtools/client/webide/test/test_telemetry.html | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/devtools/client/webide/test/test_telemetry.html b/devtools/client/webide/test/test_telemetry.html new file mode 100644 index 000000000..225ddb89b --- /dev/null +++ b/devtools/client/webide/test/test_telemetry.html @@ -0,0 +1,325 @@ +<!DOCTYPE html> + +<html> + + <head> + <meta charset="utf8"> + <title></title> + + <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script> + <script type="application/javascript;version=1.8" src="head.js"></script> + <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"> + </head> + + <body> + + <script type="application/javascript;version=1.8"> + const Telemetry = require("devtools/client/shared/telemetry"); + const { _DeprecatedUSBRuntime, _WiFiRuntime, _SimulatorRuntime, + _gRemoteRuntime, _gLocalRuntime, RuntimeTypes } + = require("devtools/client/webide/modules/runtimes"); + + // Because we need to gather stats for the period of time that a tool has + // been opened we make use of setTimeout() to create tool active times. + const TOOL_DELAY = 200; + + function patchTelemetry() { + Telemetry.prototype.telemetryInfo = {}; + Telemetry.prototype._oldlog = Telemetry.prototype.log; + Telemetry.prototype.log = function(histogramId, value) { + if (histogramId) { + if (!this.telemetryInfo[histogramId]) { + this.telemetryInfo[histogramId] = []; + } + this.telemetryInfo[histogramId].push(value); + } + } + Telemetry.prototype._oldlogKeyed = Telemetry.prototype.logKeyed; + Telemetry.prototype.logKeyed = function(histogramId, key, value) { + // This simple reduction is enough to test WebIDE's usage + this.log(`${histogramId}|${key}`, value); + } + } + + function resetTelemetry() { + Telemetry.prototype.log = Telemetry.prototype._oldlog; + Telemetry.prototype.logKeyed = Telemetry.prototype._oldlogKeyed; + delete Telemetry.prototype._oldlog; + delete Telemetry.prototype._oldlogKeyed; + delete Telemetry.prototype.telemetryInfo; + } + + function cycleWebIDE() { + return Task.spawn(function*() { + let win = yield openWebIDE(); + // Wait a bit, so we're open for a non-zero time + yield waitForTime(TOOL_DELAY); + yield closeWebIDE(win); + }); + } + + function addFakeRuntimes(win) { + // We use the real runtimes here (and switch out some functionality) + // so we can ensure that logging happens as it would in real use. + + let usb = new _DeprecatedUSBRuntime("fakeUSB"); + // Use local pipe instead + usb.connect = function(connection) { + ok(connection, win.AppManager.connection, "connection is valid"); + connection.host = null; // force connectPipe + connection.connect(); + return promise.resolve(); + }; + win.AppManager.runtimeList.usb.push(usb); + + let wifi = new _WiFiRuntime("fakeWiFi"); + // Use local pipe instead + wifi.connect = function(connection) { + ok(connection, win.AppManager.connection, "connection is valid"); + connection.host = null; // force connectPipe + connection.connect(); + return promise.resolve(); + }; + win.AppManager.runtimeList.wifi.push(wifi); + + let sim = new _SimulatorRuntime({ id: "fakeSimulator" }); + // Use local pipe instead + sim.connect = function(connection) { + ok(connection, win.AppManager.connection, "connection is valid"); + connection.host = null; // force connectPipe + connection.connect(); + return promise.resolve(); + }; + Object.defineProperty(sim, "name", { + get() { + return this.version; + } + }); + win.AppManager.runtimeList.simulator.push(sim); + + let remote = _gRemoteRuntime; + // Use local pipe instead + remote.connect = function(connection) { + ok(connection, win.AppManager.connection, "connection is valid"); + connection.host = null; // force connectPipe + connection.connect(); + return promise.resolve(); + }; + let local = _gLocalRuntime; + + let other = Object.create(_gLocalRuntime); + other.type = RuntimeTypes.OTHER; + + win.AppManager.runtimeList.other = [remote, local, other]; + + win.AppManager.update("runtime-list"); + } + + function addTestApp(win) { + return Task.spawn(function*() { + let packagedAppLocation = getTestFilePath("../app"); + let winProject = getProjectWindow(win); + let onValidated = waitForUpdate(win, "project-validated"); + let onDetails = waitForUpdate(win, "details"); + yield winProject.projectList.importPackagedApp(packagedAppLocation); + yield onValidated; + yield onDetails; + }); + } + + function startConnection(win, docRuntime, type, index) { + let panelNode = docRuntime.querySelector("#runtime-panel"); + let items = panelNode.querySelectorAll(".runtime-panel-item-" + type); + if (index === undefined) { + is(items.length, 1, "Found one runtime button"); + } + + let deferred = promise.defer(); + win.AppManager.connection.once( + win.Connection.Events.CONNECTED, + () => deferred.resolve()); + + items[index || 0].click(); + + return deferred.promise; + } + + function waitUntilConnected(win) { + return Task.spawn(function*() { + ok(win.document.querySelector("window").className, "busy", "UI is busy"); + yield win.UI._busyPromise; + is(Object.keys(DebuggerServer._connections).length, 1, "Connected"); + // Logging runtime info needs to use the device actor + yield waitForUpdate(win, "runtime-global-actors"); + // Ensure detailed telemetry is recorded + yield waitForUpdate(win, "runtime-telemetry"); + }); + } + + function connectToRuntime(win, docRuntime, type, index) { + return Task.spawn(function*() { + startConnection(win, docRuntime, type, index); + yield waitUntilConnected(win); + }); + } + + function checkResults() { + let result = Telemetry.prototype.telemetryInfo; + for (let [histId, value] of Iterator(result)) { + if (histId === "DEVTOOLS_WEBIDE_IMPORT_PROJECT_BOOLEAN") { + ok(value.length === 1 && !!value[0], + histId + " has 1 successful entry"); + } else if (histId === + "DEVTOOLS_WEBIDE_PROJECT_EDITOR_OPENED_COUNT") { + ok(value.length === 1 && !!value[0], + histId + " has 1 successful entry"); + } else if (histId === "DEVTOOLS_WEBIDE_OPENED_COUNT") { + ok(value.length > 1, histId + " has more than one entry"); + + let okay = value.every(function(element) { + return !!element; + }); + + ok(okay, "All " + histId + " entries are true"); + } else if (histId.endsWith("WEBIDE_TIME_ACTIVE_SECONDS")) { + ok(value.length > 1, histId + " has more than one entry"); + + let okay = value.every(function(element) { + return element > 0; + }); + + ok(okay, "All " + histId + " entries have time > 0"); + } else if (histId.endsWith("EDITOR_TIME_ACTIVE_SECONDS")) { + ok(value.length === 1 && value[0] > 0, + histId + " has 1 entry with time > 0"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTION_RESULT") { + ok(value.length === 6, histId + " has 6 connection results"); + + let okay = value.every(function(element) { + return !!element; + }); + + ok(okay, "All " + histId + " connections succeeded"); + } else if (histId.endsWith("CONNECTION_RESULT")) { + ok(value.length === 1 && !!value[0], + histId + " has 1 successful connection"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTION_TIME_SECONDS") { + ok(value.length === 6, histId + " has 6 connection results"); + + let okay = value.every(function(element) { + return element > 0; + }); + + ok(okay, "All " + histId + " connections have time > 0"); + } else if (histId.endsWith("USED")) { + ok(value.length === 6, histId + " has 6 connection actions"); + + let okay = value.every(function(element) { + return !element; + }); + + ok(okay, "All " + histId + " actions were skipped"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|USB") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|WIFI") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|SIMULATOR") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|REMOTE") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|LOCAL") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_TYPE|OTHER") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|fakeUSB") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|fakeWiFi") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|fakeSimulator") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|unknown") { + is(value.length, 1, histId + " has 1 connection results"); + } else if (histId === "DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_ID|local") { + is(value.length, 2, histId + " has 2 connection results"); + } else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_PROCESSOR")) { + let processor = histId.split("|")[1]; + is(processor, Services.appinfo.XPCOMABI.split("-")[0], "Found runtime processor"); + is(value.length, 6, histId + " has 6 connection results"); + } else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_OS")) { + let os = histId.split("|")[1]; + is(os, Services.appinfo.OS, "Found runtime OS"); + is(value.length, 6, histId + " has 6 connection results"); + } else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_PLATFORM_VERSION")) { + let platformversion = histId.split("|")[1]; + is(platformversion, Services.appinfo.platformVersion, "Found runtime platform version"); + is(value.length, 6, histId + " has 6 connection results"); + } else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_APP_TYPE")) { + let apptype = histId.split("|")[1]; + is(apptype, "firefox", "Found runtime app type"); + is(value.length, 6, histId + " has 6 connection results"); + } else if (histId.startsWith("DEVTOOLS_WEBIDE_CONNECTED_RUNTIME_VERSION")) { + let version = histId.split("|")[1]; + is(version, Services.appinfo.version, "Found runtime version"); + is(value.length, 6, histId + " has 6 connection results"); + } else { + ok(false, "Unexpected " + histId + " was logged"); + } + } + } + + window.onload = function() { + SimpleTest.testInChaosMode(); + SimpleTest.waitForExplicitFinish(); + + let win; + + SimpleTest.registerCleanupFunction(() => { + return Task.spawn(function*() { + if (win) { + yield closeWebIDE(win); + } + DebuggerServer.destroy(); + yield removeAllProjects(); + resetTelemetry(); + }); + }); + + Task.spawn(function*() { + if (!DebuggerServer.initialized) { + DebuggerServer.init(); + DebuggerServer.addBrowserActors(); + } + + patchTelemetry(); + + // Cycle once, so we can test for multiple opens + yield cycleWebIDE(); + + win = yield openWebIDE(); + let docRuntime = getRuntimeDocument(win); + + // Wait a bit, so we're open for a non-zero time + yield waitForTime(TOOL_DELAY); + addFakeRuntimes(win); + yield addTestApp(win); + + // Each one should log a connection result and non-zero connection + // time + yield connectToRuntime(win, docRuntime, "usb"); + yield connectToRuntime(win, docRuntime, "wifi"); + yield connectToRuntime(win, docRuntime, "simulator"); + yield connectToRuntime(win, docRuntime, "other", 0 /* remote */); + yield connectToRuntime(win, docRuntime, "other", 1 /* local */); + yield connectToRuntime(win, docRuntime, "other", 2 /* other */); + yield closeWebIDE(win); + win = null; + + checkResults(); + + SimpleTest.finish(); + }); + } + </script> + </body> +</html> |