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
|
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env mozilla/frame-script */
// Functions that are automatically loaded as frame scripts for
// timeline tests.
const { setTimeout } = ChromeUtils.importESModule(
"resource://gre/modules/Timer.sys.mjs"
);
// Functions that look like mochitest functions but forward to the
// browser process.
this.ok = function(value, message) {
sendAsyncMessage("browser:test:ok", {
value: !!value,
message,
});
};
this.is = function(v1, v2, message) {
ok(v1 == v2, message);
};
this.info = function(message) {
sendAsyncMessage("browser:test:info", { message });
};
this.finish = function() {
sendAsyncMessage("browser:test:finish");
};
/* Start a task that runs some timeline tests in the ordinary way.
*
* @param array tests
* The tests to run. This is an array where each element
* is of the form { desc, searchFor, setup, check }.
*
* desc is the test description, a string.
* searchFor is a string or a function
* If a string, then when a marker with this name is
* found, marker-reading is stopped.
* If a function, then the accumulated marker array is
* passed to it, and marker reading stops when it returns
* true.
* setup is a function that takes the docshell as an argument.
* It should start the test.
* check is a function that takes an array of markers
* as an argument and checks the results of the test.
*/
this.timelineContentTest = function(tests) {
(async function() {
let docShell = content.docShell;
info("Start recording");
docShell.recordProfileTimelineMarkers = true;
for (let { desc, searchFor, setup, check } of tests) {
info("Running test: " + desc);
info("Flushing the previous markers if any");
docShell.popProfileTimelineMarkers();
info("Running the test setup function");
let onMarkers = timelineWaitForMarkers(docShell, searchFor);
setup(docShell);
info("Waiting for new markers on the docShell");
let markers = await onMarkers;
// Cycle collection markers are non-deterministic, and none of these tests
// expect them to show up.
markers = markers.filter(m => !m.name.includes("nsCycleCollector"));
info("Running the test check function");
check(markers);
}
info("Stop recording");
docShell.recordProfileTimelineMarkers = false;
finish();
})();
};
function timelineWaitForMarkers(docshell, searchFor) {
if (typeof searchFor == "string") {
let searchForString = searchFor;
let f = function(markers) {
return markers.some(m => m.name == searchForString);
};
searchFor = f;
}
return new Promise(function(resolve, reject) {
let waitIterationCount = 0;
let maxWaitIterationCount = 10; // Wait for 2sec maximum
let markers = [];
setTimeout(function timeoutHandler() {
let newMarkers = docshell.popProfileTimelineMarkers();
markers = [...markers, ...newMarkers];
if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) {
resolve(markers);
} else {
setTimeout(timeoutHandler, 200);
waitIterationCount++;
}
}, 200);
});
}
|