summaryrefslogtreecommitdiffstats
path: root/dom/tests/browser/perfmetrics/browser_test_performance_metrics.js
blob: 65a7aaaee2751fbf796fc081b6ddf8f97210e630 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const ROOT_URL = "http://example.com/browser/dom/tests/browser/perfmetrics";
const DUMMY_URL = ROOT_URL + "/dummy.html";
const WORKER_URL = ROOT_URL + "/ping_worker.html";
const WORKER_URL2 = ROOT_URL + "/ping_worker2.html";
const INTERVAL_URL = ROOT_URL + "/setinterval.html";
const TIMEOUT_URL = ROOT_URL + "/settimeout.html";
const SOUND_URL = ROOT_URL + "/sound.html";
const CATEGORY_TIMER = 2;

add_task(async function test() {
  waitForExplicitFinish();

  // Load 3 pages and wait. The 3rd one has a worker
  let page1 = await BrowserTestUtils.openNewForegroundTab({
    gBrowser,
    opening: "about:about",
    forceNewProcess: false,
  });

  let page2 = await BrowserTestUtils.openNewForegroundTab({
    gBrowser,
    opening: "about:memory",
    forceNewProcess: false,
  });

  let page3 = await BrowserTestUtils.openNewForegroundTab({
    gBrowser,
    opening: WORKER_URL,
  });
  // load a 4th tab with a worker
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: WORKER_URL2 },
    async function (browser) {
      // grab events..
      let workerDuration = 0;
      let workerTotal = 0;
      let duration = 0;
      let total = 0;
      let isTopLevel = false;
      let aboutMemoryFound = false;
      let parentProcessEvent = false;
      let subFrameIds = [];
      let topLevelIds = [];
      let sharedWorker = false;
      let counterIds = [];
      let timerCalls = 0;
      let heapUsage = 0;
      let mediaMemory = 0;

      function exploreResults(data, filterByWindowId) {
        for (let entry of data) {
          if (filterByWindowId && entry.windowId != filterByWindowId) {
            continue;
          }
          if (!counterIds.includes(entry.pid + ":" + entry.counterId)) {
            counterIds.push(entry.pid + ":" + entry.counterId);
          }
          sharedWorker =
            entry.host.endsWith("shared_worker.js") || sharedWorker;
          heapUsage += entry.memoryInfo.jsMemUsage;
          mediaMemory +=
            entry.memoryInfo.media.audioSize +
            entry.memoryInfo.media.resourcesSize;
          Assert.ok(
            entry.host != "" || entry.windowId != 0,
            "An entry should have a host or a windowId"
          );
          if (
            entry.windowId != 0 &&
            !entry.isToplevel &&
            !entry.isWorker &&
            !subFrameIds.includes(entry.windowId)
          ) {
            subFrameIds.push(entry.windowId);
          }
          if (entry.isTopLevel && !topLevelIds.includes(entry.windowId)) {
            topLevelIds.push(entry.windowId);
          }
          if (entry.host == "example.com" && entry.isTopLevel) {
            isTopLevel = true;
          }
          if (entry.host == "about:memory") {
            aboutMemoryFound = true;
          }
          if (entry.pid == Services.appinfo.processID) {
            parentProcessEvent = true;
          }
          if (entry.isWorker) {
            workerDuration += entry.duration;
          } else {
            duration += entry.duration;
          }
          // let's look at the data we got back
          for (let item of entry.items) {
            Assert.ok(
              item.count > 0,
              "Categories with an empty count are dropped"
            );
            if (entry.isWorker) {
              workerTotal += item.count;
            } else {
              total += item.count;
            }
            if (item.category == CATEGORY_TIMER) {
              timerCalls += item.count;
            }
          }
        }
      }

      // get all metrics via the promise
      let results = await ChromeUtils.requestPerformanceMetrics();
      exploreResults(results);

      Assert.greater(workerDuration, 0, "Worker duration should be positive");
      Assert.greater(workerTotal, 0, "Worker count should be positive");
      Assert.greater(duration, 0, "Duration should be positive");
      Assert.greater(total, 0, "Should get a positive count");
      Assert.ok(parentProcessEvent, "parent process sent back some events");
      Assert.ok(isTopLevel, "example.com as a top level window");
      Assert.ok(aboutMemoryFound, "about:memory");
      Assert.greater(heapUsage, 0, "got some memory value reported");
      Assert.ok(sharedWorker, "We got some info from a shared worker");
      let numCounters = counterIds.length;
      Assert.ok(
        numCounters > 5,
        "This test generated at least " + numCounters + " unique counters"
      );

      // checking that subframes are not orphans
      for (let frameId of subFrameIds) {
        Assert.ok(topLevelIds.includes(frameId), "subframe is not orphan ");
      }

      // Doing a second call, we shoud get bigger values
      let previousWorkerDuration = workerDuration;
      let previousWorkerTotal = workerTotal;
      let previousDuration = duration;
      let previousTotal = total;

      results = await ChromeUtils.requestPerformanceMetrics();
      exploreResults(results);

      Assert.ok(
        workerDuration > previousWorkerDuration,
        "Worker duration should be positive"
      );
      Assert.ok(
        workerTotal > previousWorkerTotal,
        "Worker count should be positive"
      );
      Assert.greater(duration, previousDuration, "Duration should be positive");
      Assert.greater(total, previousTotal, "Should get a positive count");

      // load a tab with a setInterval, we should get counters on TaskCategory::Timer
      await BrowserTestUtils.withNewTab(
        { gBrowser, url: INTERVAL_URL },
        async function (browser) {
          let tabId = gBrowser.selectedBrowser.outerWindowID;
          let previousTimerCalls = timerCalls;
          results = await ChromeUtils.requestPerformanceMetrics();
          exploreResults(results, tabId);
          Assert.greater(timerCalls, previousTimerCalls, "Got timer calls");
        }
      );

      // load a tab with a setTimeout, we should get counters on TaskCategory::Timer
      await BrowserTestUtils.withNewTab(
        { gBrowser, url: TIMEOUT_URL },
        async function (browser) {
          let tabId = gBrowser.selectedBrowser.outerWindowID;
          let previousTimerCalls = timerCalls;
          results = await ChromeUtils.requestPerformanceMetrics();
          exploreResults(results, tabId);
          Assert.greater(timerCalls, previousTimerCalls, "Got timer calls");
        }
      );

      // load a tab with a sound
      await BrowserTestUtils.withNewTab(
        { gBrowser, url: SOUND_URL },
        async function (browser) {
          let tabId = gBrowser.selectedBrowser.outerWindowID;
          results = await ChromeUtils.requestPerformanceMetrics();
          exploreResults(results, tabId);
          Assert.greater(mediaMemory, 0, "Got some memory used for media");
        }
      );
    }
  );

  BrowserTestUtils.removeTab(page1);
  BrowserTestUtils.removeTab(page2);
  BrowserTestUtils.removeTab(page3);
});