From edd7742a84043cefc6ee660c8f0b1fa0673ca941 Mon Sep 17 00:00:00 2001 From: Jordan Santell Date: Thu, 12 Feb 2015 12:55:00 +0100 Subject: [PATCH] Bug 1130202 - Fix compatibility issues in performance tool to work with FxOS 2.2/Gecko 37. r=vp --- .../performance/modules/compatibility.js | 13 ++-- browser/devtools/performance/test/browser.ini | 2 + .../test/browser_perf-compatibility-01.js | 1 + .../test/browser_perf-compatibility-02.js | 1 + .../test/browser_perf-compatibility-03.js | 63 +++++++++++++++++ .../test/browser_perf-compatibility-04.js | 67 +++++++++++++++++++ toolkit/devtools/server/actors/memory.js | 6 +- toolkit/devtools/server/actors/root.js | 5 +- toolkit/devtools/server/actors/timeline.js | 3 +- 9 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 browser/devtools/performance/test/browser_perf-compatibility-03.js create mode 100644 browser/devtools/performance/test/browser_perf-compatibility-04.js diff --git a/browser/devtools/performance/modules/compatibility.js b/browser/devtools/performance/modules/compatibility.js index ed327c94678..3858525b229 100644 --- a/browser/devtools/performance/modules/compatibility.js +++ b/browser/devtools/performance/modules/compatibility.js @@ -74,19 +74,14 @@ function createMockAllocations () { * @param {TabTarget} target * @return {Boolean} */ -function* memoryActorSupported (target) { +function memoryActorSupported (target) { // This `target` property is used only in tests to test // instances where the memory actor is not available. if (target.TEST_MOCK_MEMORY_ACTOR) { return false; } - for (let method of REQUIRED_MEMORY_ACTOR_METHODS) { - if (!(yield target.actorHasMethod("memory", method))) { - return false; - } - } - return true; + return !!target.getTrait("memoryActorAllocations"); } exports.memoryActorSupported = Task.async(memoryActorSupported); @@ -97,13 +92,13 @@ exports.memoryActorSupported = Task.async(memoryActorSupported); * @param {TabTarget} target * @return {Boolean} */ -function* timelineActorSupported(target) { +function timelineActorSupported(target) { // This `target` property is used only in tests to test // instances where the timeline actor is not available. if (target.TEST_MOCK_TIMELINE_ACTOR) { return false; } - return yield target.hasActor("timeline"); + return target.hasActor("timeline"); } exports.timelineActorSupported = Task.async(timelineActorSupported); diff --git a/browser/devtools/performance/test/browser.ini b/browser/devtools/performance/test/browser.ini index 6eb47fbbc79..4472432fde1 100644 --- a/browser/devtools/performance/test/browser.ini +++ b/browser/devtools/performance/test/browser.ini @@ -12,6 +12,8 @@ support-files = [browser_perf-allocations-to-samples.js] [browser_perf-compatibility-01.js] [browser_perf-compatibility-02.js] +[browser_perf-compatibility-03.js] +[browser_perf-compatibility-04.js] [browser_perf-clear-01.js] [browser_perf-clear-02.js] [browser_perf-data-massaging-01.js] diff --git a/browser/devtools/performance/test/browser_perf-compatibility-01.js b/browser/devtools/performance/test/browser_perf-compatibility-01.js index 1c5083f635b..024529e296d 100644 --- a/browser/devtools/performance/test/browser_perf-compatibility-01.js +++ b/browser/devtools/performance/test/browser_perf-compatibility-01.js @@ -12,6 +12,7 @@ function spawnTest () { TEST_MOCK_MEMORY_ACTOR: true, TEST_MOCK_TIMELINE_ACTOR: true }); + Services.prefs.setBoolPref(MEMORY_PREF, true); let { memory, timeline } = front.getMocksInUse(); ok(memory, "memory should be mocked."); diff --git a/browser/devtools/performance/test/browser_perf-compatibility-02.js b/browser/devtools/performance/test/browser_perf-compatibility-02.js index 628777fc105..461799b4b8c 100644 --- a/browser/devtools/performance/test/browser_perf-compatibility-02.js +++ b/browser/devtools/performance/test/browser_perf-compatibility-02.js @@ -13,6 +13,7 @@ let test = Task.async(function*() { TEST_MOCK_MEMORY_ACTOR: true, TEST_MOCK_TIMELINE_ACTOR: true }); + Services.prefs.setBoolPref(MEMORY_PREF, true); let { EVENTS, gFront, PerformanceController, PerformanceView } = panel.panelWin; let { memory: memoryMock, timeline: timelineMock } = gFront.getMocksInUse(); diff --git a/browser/devtools/performance/test/browser_perf-compatibility-03.js b/browser/devtools/performance/test/browser_perf-compatibility-03.js new file mode 100644 index 00000000000..42b0fb25197 --- /dev/null +++ b/browser/devtools/performance/test/browser_perf-compatibility-03.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Test basic functionality of PerformanceFront with only mock memory. + */ + +let WAIT_TIME = 100; + +function spawnTest () { + let { target, front } = yield initBackend(SIMPLE_URL, { + TEST_MOCK_MEMORY_ACTOR: true + }); + Services.prefs.setBoolPref(MEMORY_PREF, true); + + let { memory, timeline } = front.getMocksInUse(); + ok(memory, "memory should be mocked."); + ok(!timeline, "timeline should not be mocked."); + + let { + profilerStartTime, + timelineStartTime, + memoryStartTime + } = yield front.startRecording({ + withTicks: true, + withMemory: true, + withAllocations: true + }); + + ok(typeof profilerStartTime === "number", + "The front.startRecording() emits a profiler start time."); + ok(typeof timelineStartTime === "number", + "The front.startRecording() emits a timeline start time."); + ok(typeof memoryStartTime === "number", + "The front.startRecording() emits a memory start time."); + + yield busyWait(WAIT_TIME); + + let { + profilerEndTime, + timelineEndTime, + memoryEndTime + } = yield front.stopRecording({ + withAllocations: true + }); + + ok(typeof profilerEndTime === "number", + "The front.stopRecording() emits a profiler end time."); + ok(typeof timelineEndTime === "number", + "The front.stopRecording() emits a timeline end time."); + ok(typeof memoryEndTime === "number", + "The front.stopRecording() emits a memory end time."); + + ok(profilerEndTime > profilerStartTime, + "The profilerEndTime is after profilerStartTime."); + ok(timelineEndTime > timelineStartTime, + "The timelineEndTime is after timelineStartTime."); + is(memoryEndTime, memoryStartTime, + "The memoryEndTime is the same as memoryStartTime."); + + yield removeTab(target.tab); + finish(); +} diff --git a/browser/devtools/performance/test/browser_perf-compatibility-04.js b/browser/devtools/performance/test/browser_perf-compatibility-04.js new file mode 100644 index 00000000000..1c75174fd49 --- /dev/null +++ b/browser/devtools/performance/test/browser_perf-compatibility-04.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests that the recording model is populated correctly when using timeline + * and memory actor mocks. + */ + +const WAIT_TIME = 1000; + +let test = Task.async(function*() { + let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL, "performance", { + TEST_MOCK_MEMORY_ACTOR: true + }); + Services.prefs.setBoolPref(MEMORY_PREF, true); + let { EVENTS, gFront, PerformanceController, PerformanceView } = panel.panelWin; + + + let { memory: memoryMock, timeline: timelineMock } = gFront.getMocksInUse(); + ok(memoryMock, "memory should be mocked."); + ok(!timelineMock, "timeline should not be mocked."); + + yield startRecording(panel); + yield busyWait(100); + yield waitUntil(() => PerformanceController.getCurrentRecording().getTicks().length); + yield waitUntil(() => PerformanceController.getCurrentRecording().getMemory().length); + yield waitUntil(() => PerformanceController.getCurrentRecording().getMarkers().length); + yield stopRecording(panel); + + let { + label, duration, allocations, profile + } = PerformanceController.getCurrentRecording().getAllData(); + + is(label, "", "Empty label for mock."); + is(typeof duration, "number", "duration is a number"); + ok(duration > 0, "duration is not 0"); + + isEmptyArray(allocations.sites, "allocations.sites"); + isEmptyArray(allocations.timestamps, "allocations.timestamps"); + isEmptyArray(allocations.frames, "allocations.frames"); + isEmptyArray(allocations.counts, "allocations.counts"); + + let sampleCount = 0; + + for (let thread of profile.threads) { + info("Checking thread: " + thread.name); + + for (let sample of thread.samples) { + sampleCount++; + + if (sample.frames[0].location != "(root)") { + ok(false, "The sample " + sample.toSource() + " doesn't have a root node."); + } + } + } + + ok(sampleCount > 0, + "At least some samples have been iterated over, checking for root nodes."); + + yield teardown(panel); + finish(); +}); + +function isEmptyArray (array, name) { + ok(Array.isArray(array), `${name} is an array`); + is(array.length, 0, `${name} is empty`); +} diff --git a/toolkit/devtools/server/actors/memory.js b/toolkit/devtools/server/actors/memory.js index e1752adf1ff..d4affadea4a 100644 --- a/toolkit/devtools/server/actors/memory.js +++ b/toolkit/devtools/server/actors/memory.js @@ -172,7 +172,8 @@ let MemoryActor = protocol.ActorClass({ options: Arg(0, "nullable:AllocationsRecordingOptions") }, response: { - value: RetVal(0, "number") + // Accept `nullable` in the case of server Gecko <= 37, handled on the front + value: RetVal(0, "nullable:number") } }), @@ -187,7 +188,8 @@ let MemoryActor = protocol.ActorClass({ }), { request: {}, response: { - value: RetVal(0, "number") + // Accept `nullable` in the case of server Gecko <= 37, handled on the front + value: RetVal(0, "nullable:number") } }), diff --git a/toolkit/devtools/server/actors/root.js b/toolkit/devtools/server/actors/root.js index 7db11de164f..57ce5c4207f 100644 --- a/toolkit/devtools/server/actors/root.js +++ b/toolkit/devtools/server/actors/root.js @@ -157,7 +157,10 @@ RootActor.prototype = { noPrettyPrinting: false, // Whether the page style actor implements the getUsedFontFaces method // that returns the font faces used on a node - getUsedFontFaces: true + getUsedFontFaces: true, + // Trait added in Gecko 38, indicating that all features necessary for + // grabbing allocations from the MemoryActor are available for the performance tool + memoryActorAllocations: true }, /** diff --git a/toolkit/devtools/server/actors/timeline.js b/toolkit/devtools/server/actors/timeline.js index 8a986602ff4..b2f07033e52 100644 --- a/toolkit/devtools/server/actors/timeline.js +++ b/toolkit/devtools/server/actors/timeline.js @@ -44,7 +44,8 @@ const DEFAULT_TIMELINE_DATA_PULL_TIMEOUT = 200; // ms */ protocol.types.addType("array-of-numbers-as-strings", { write: (v) => v.join(","), - read: (v) => v.split(",") + // In Gecko <= 37, `v` is an array; do not transform in this case. + read: (v) => typeof v === "string" ? v.split(",") : v }); /**