fune/toolkit/components/telemetry/tests/unit/test_TelemetryCaptureStack.js
Victor Porof 4a06c925ac Bug 1561435 - Format toolkit/components/, a=automatic-formatting
# ignore-this-changeset

Differential Revision: https://phabricator.services.mozilla.com/D36052

--HG--
extra : source : b5be5b4f4b47c256e28a29f665dc754f6407ee7f
2019-07-05 11:14:05 +02:00

212 lines
6 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
ChromeUtils.import("resource://gre/modules/TelemetryController.jsm", this);
ChromeUtils.import("resource://gre/modules/AppConstants.jsm", this);
// We need both in order to capture stacks.
const ENABLE_TESTS = AppConstants.MOZ_GECKO_PROFILER;
/**
* Ensures that the sctucture of the javascript object used for capturing stacks
* is as intended. The structure is expected to be as in this example:
*
* {
* "memoryMap": [
* [String, String],
* ...
* ],
* "stacks": [
* [
* [Integer, Integer], // Frame
* ...
* ],
* ...
* ],
* "captures": [
* [String, Integer, Integer],
* ...
* ]
* }
*
* @param {Object} obj abject to be inpected vor validity.
*
* @return {Boolean} True if the structure is valid. False - otherwise.
*/
function checkObjectStructure(obj) {
// Ensuring an object is given.
if (!obj || typeof obj !== "object") {
return false;
}
// Ensuring all properties exist inside the object and are arrays.
for (let property of ["memoryMap", "stacks", "captures"]) {
if (!(property in obj) || !Array.isArray(obj[property])) {
return false;
}
}
return true;
}
/**
* A helper for triggering a stack capture and returning the new state of stacks.
*
* @param {String} key The key for capturing stack.
* @param {Boolean} clear True to reset captured stacks, False - otherwise.
*
* @return {Object} captured stacks.
*/
function captureStacks(key, clear = true) {
Telemetry.captureStack(key);
let stacks = Telemetry.snapshotCapturedStacks(clear);
Assert.ok(checkObjectStructure(stacks));
return stacks;
}
const TEST_STACK_KEYS = ["TEST-KEY1", "TEST-KEY2"];
/**
* Ensures that captured stacks appear in pings, if any were captured.
*/
add_task(
{
skip_if: () => !ENABLE_TESTS,
},
async function test_capturedStacksAppearInPings() {
await TelemetryController.testSetup();
captureStacks("DOES-NOT-MATTER", false);
let ping = TelemetryController.getCurrentPingData();
Assert.ok("capturedStacks" in ping.payload.processes.parent);
let capturedStacks = ping.payload.processes.parent.capturedStacks;
Assert.ok(checkObjectStructure(capturedStacks));
}
);
/**
* Ensures that capturing a stack for a new key increases the number
* of captured stacks and adds a new entry to captures.
*/
add_task(
{
skip_if: () => !ENABLE_TESTS,
},
function test_CaptureStacksIncreasesNumberOfCapturedStacks() {
// Construct a unique key for this test.
let key = TEST_STACK_KEYS[0] + "-UNIQUE-KEY-1";
// Ensure that no captures for the key exist.
let original = Telemetry.snapshotCapturedStacks();
Assert.equal(
undefined,
original.captures.find(capture => capture[0] === key)
);
// Capture stack and find updated capture stats for TEST_STACK_KEYS[0].
let updated = captureStacks(key);
// Ensure that a new element has been appended to both stacks and captures.
Assert.equal(original.stacks.length + 1, updated.stacks.length);
Assert.equal(original.captures.length + 1, updated.captures.length);
// Ensure that the capture info for the key exists and structured well.
Assert.deepEqual(
[key, original.stacks.length, 1],
updated.captures.find(capture => capture[0] === key)
);
}
);
/**
* Ensures that stacks are grouped by the key. If a stack is captured
* more than once for the key, the length of stacks does not increase.
*/
add_task(
{
skip_if: () => !ENABLE_TESTS,
},
function test_CaptureStacksGroupsDuplicateStacks() {
// Make sure that there are initial captures for TEST_STACK_KEYS[0].
let stacks = captureStacks(TEST_STACK_KEYS[0], false);
let original = {
captures: stacks.captures.find(
capture => capture[0] === TEST_STACK_KEYS[0]
),
stacks: stacks.stacks,
};
// Capture stack and find updated capture stats for TEST_STACK_KEYS[0].
stacks = captureStacks(TEST_STACK_KEYS[0]);
let updated = {
captures: stacks.captures.find(
capture => capture[0] === TEST_STACK_KEYS[0]
),
stacks: stacks.stacks,
};
// The length of captured stacks should remain same.
Assert.equal(original.stacks.length, updated.stacks.length);
// We expect the info on captures to look as original. Only
// stack counter should be increased by one.
let expectedCaptures = original.captures;
expectedCaptures[2]++;
Assert.deepEqual(expectedCaptures, updated.captures);
}
);
/**
* Ensure that capturing the stack for a key does not affect info
* for other keys.
*/
add_task(
{
skip_if: () => !ENABLE_TESTS,
},
function test_CaptureStacksSeparatesInformationByKeys() {
// Make sure that there are initial captures for TEST_STACK_KEYS[0].
let stacks = captureStacks(TEST_STACK_KEYS[0], false);
let original = {
captures: stacks.captures.find(
capture => capture[0] === TEST_STACK_KEYS[0]
),
stacks: stacks.stacks,
};
// Capture stack for a new key.
let uniqueKey = TEST_STACK_KEYS[1] + "-UNIQUE-KEY-2";
let updated = captureStacks(uniqueKey);
// The length of captured stacks should increase to reflect the new capture.
Assert.equal(original.stacks.length + 1, updated.stacks.length);
// The information for TEST_STACK_KEYS[0] should remain same.
Assert.deepEqual(
original.captures,
updated.captures.find(capture => capture[0] === TEST_STACK_KEYS[0])
);
}
);
/**
* Ensure that Telemetry does not allow weird keys.
*/
add_task(
{
skip_if: () => !ENABLE_TESTS,
},
function test_CaptureStacksDoesNotAllowBadKey() {
for (let badKey of [null, 'KEY-!@"#$%^&*()_']) {
let stacks = captureStacks(badKey);
let captureData = stacks.captures.find(capture => capture[0] === badKey);
Assert.ok(!captureData, `"${badKey}" should not be allowed as a key`);
}
}
);
function run_test() {
do_get_profile(true);
run_next_test();
}