summaryrefslogtreecommitdiffstats
path: root/devtools/server/tests/unit/test_profiler_data.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/tests/unit/test_profiler_data.js')
-rw-r--r--devtools/server/tests/unit/test_profiler_data.js110
1 files changed, 110 insertions, 0 deletions
diff --git a/devtools/server/tests/unit/test_profiler_data.js b/devtools/server/tests/unit/test_profiler_data.js
new file mode 100644
index 000000000..2a79eed1f
--- /dev/null
+++ b/devtools/server/tests/unit/test_profiler_data.js
@@ -0,0 +1,110 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests if the profiler actor can correctly retrieve a profile after
+ * it is activated.
+ */
+
+const Profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
+const INITIAL_WAIT_TIME = 100; // ms
+const MAX_WAIT_TIME = 20000; // ms
+
+function run_test()
+{
+ get_chrome_actors((client, form) => {
+ let actor = form.profilerActor;
+ activate_profiler(client, actor, startTime => {
+ test_data(client, actor, startTime, () => {
+ deactivate_profiler(client, actor, () => {
+ client.close().then(do_test_finished);
+ });
+ });
+ });
+ });
+
+ do_test_pending();
+}
+
+function activate_profiler(client, actor, callback)
+{
+ client.request({ to: actor, type: "startProfiler" }, response => {
+ do_check_true(response.started);
+ client.request({ to: actor, type: "isActive" }, response => {
+ do_check_true(response.isActive);
+ callback(response.currentTime);
+ });
+ });
+}
+
+function deactivate_profiler(client, actor, callback)
+{
+ client.request({ to: actor, type: "stopProfiler" }, response => {
+ do_check_false(response.started);
+ client.request({ to: actor, type: "isActive" }, response => {
+ do_check_false(response.isActive);
+ callback();
+ });
+ });
+}
+
+function test_data(client, actor, startTime, callback)
+{
+ function attempt(delay)
+ {
+ // No idea why, but Components.stack.sourceLine returns null.
+ let funcLine = Components.stack.lineNumber - 3;
+
+ // Spin for the requested time, then take a sample.
+ let start = Date.now();
+ let stack;
+ do_print("Attempt: delay = " + delay);
+ while (Date.now() - start < delay) { stack = Components.stack; }
+ do_print("Attempt: finished waiting.");
+
+ client.request({ to: actor, type: "getProfile", startTime }, response => {
+ // Any valid getProfile response should have the following top
+ // level structure.
+ do_check_eq(typeof response.profile, "object");
+ do_check_eq(typeof response.profile.meta, "object");
+ do_check_eq(typeof response.profile.meta.platform, "string");
+ do_check_eq(typeof response.profile.threads, "object");
+ do_check_eq(typeof response.profile.threads[0], "object");
+ do_check_eq(typeof response.profile.threads[0].samples, "object");
+
+ // At this point, we may or may not have samples, depending on
+ // whether the spin loop above has given the profiler enough time
+ // to get started.
+ if (response.profile.threads[0].samples.length == 0) {
+ if (delay < MAX_WAIT_TIME) {
+ // Double the spin-wait time and try again.
+ do_print("Attempt: no samples, going around again.");
+ return attempt(delay * 2);
+ } else {
+ // We've waited long enough, so just fail.
+ do_print("Attempt: waited a long time, but no samples were collected.");
+ do_print("Giving up.");
+ do_check_true(false);
+ return;
+ }
+ }
+
+ // Now check the samples. At least one sample is expected to
+ // have been in the busy wait above.
+ let loc = stack.name + " (" + stack.filename + ":" + funcLine + ")";
+ let thread0 = response.profile.threads[0];
+ do_check_true(thread0.samples.data.some(sample => {
+ let frames = getInflatedStackLocations(thread0, sample);
+ return frames.length != 0 &&
+ frames.some(location => (location == loc));
+ }));
+
+ callback();
+ });
+ }
+
+ // Start off with a 100 millisecond delay.
+ attempt(INITIAL_WAIT_TIME);
+}