summaryrefslogtreecommitdiffstats
path: root/tools/code-coverage/tests/xpcshell
diff options
context:
space:
mode:
Diffstat (limited to 'tools/code-coverage/tests/xpcshell')
-rw-r--r--tools/code-coverage/tests/xpcshell/head.js100
-rw-r--r--tools/code-coverage/tests/xpcshell/support.js5
-rw-r--r--tools/code-coverage/tests/xpcshell/test_basic.js115
-rw-r--r--tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js120
-rw-r--r--tools/code-coverage/tests/xpcshell/xpcshell.ini7
5 files changed, 347 insertions, 0 deletions
diff --git a/tools/code-coverage/tests/xpcshell/head.js b/tools/code-coverage/tests/xpcshell/head.js
new file mode 100644
index 0000000000..3642c5794c
--- /dev/null
+++ b/tools/code-coverage/tests/xpcshell/head.js
@@ -0,0 +1,100 @@
+/* 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/. */
+
+var { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+
+function getFiles() {
+ // This is the directory where gcov is emitting the gcda files.
+ const jsCoveragePath = Services.env.get("JS_CODE_COVERAGE_OUTPUT_DIR");
+
+ const jsCoverageDir = Cc["@mozilla.org/file/local;1"].createInstance(
+ Ci.nsIFile
+ );
+ jsCoverageDir.initWithPath(jsCoveragePath);
+
+ let files = [];
+
+ let entries = jsCoverageDir.directoryEntries;
+ while (entries.hasMoreElements()) {
+ files.push(entries.nextFile);
+ }
+
+ return files;
+}
+
+function diffFiles(files_after, files_before) {
+ let files_before_set = new Set(files_before.map(file => file.leafName));
+ return files_after.filter(file => !files_before_set.has(file.leafName));
+}
+
+const BASENAME_RE = new RegExp("([^/\\\\]+)$");
+
+function parseRecords(files) {
+ let records = new Map();
+
+ for (let file of files) {
+ const lines = Cu.readUTF8File(file).split("\n");
+ let currentSF = null;
+
+ for (let line of lines) {
+ let [recordType, ...recordContent] = line.split(":");
+ recordContent = recordContent.join(":");
+
+ switch (recordType) {
+ case "FNDA": {
+ if (currentSF == null) {
+ throw new Error("SF missing");
+ }
+
+ let [hits, name] = recordContent.split(",");
+ currentSF.push({
+ type: "FNDA",
+ hits,
+ name,
+ });
+ break;
+ }
+
+ case "FN": {
+ if (currentSF == null) {
+ throw new Error("SF missing");
+ }
+
+ let name = recordContent.split(",")[1];
+ currentSF.push({
+ type: "FN",
+ name,
+ });
+ break;
+ }
+
+ case "SF": {
+ if (
+ recordContent.startsWith("resource:") ||
+ recordContent.startsWith("chrome:")
+ ) {
+ recordContent = recordContent.split("/").at(-1);
+ } else {
+ if (AppConstants.platform == "win") {
+ recordContent = recordContent.replace(/\//g, "\\");
+ }
+ const match = BASENAME_RE.exec(recordContent);
+ if (match.length) {
+ recordContent = match[0];
+ }
+ }
+
+ currentSF = [];
+
+ records.set(recordContent, currentSF);
+ break;
+ }
+ }
+ }
+ }
+
+ return records;
+}
diff --git a/tools/code-coverage/tests/xpcshell/support.js b/tools/code-coverage/tests/xpcshell/support.js
new file mode 100644
index 0000000000..9189427111
--- /dev/null
+++ b/tools/code-coverage/tests/xpcshell/support.js
@@ -0,0 +1,5 @@
+function test_code_coverage_func2() {
+ return 22;
+}
+
+test_code_coverage_func2();
diff --git a/tools/code-coverage/tests/xpcshell/test_basic.js b/tools/code-coverage/tests/xpcshell/test_basic.js
new file mode 100644
index 0000000000..9523a37ca2
--- /dev/null
+++ b/tools/code-coverage/tests/xpcshell/test_basic.js
@@ -0,0 +1,115 @@
+/* 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/. */
+
+function test_code_coverage_func1() {
+ return 22;
+}
+
+function test_code_coverage_func2() {
+ return 22;
+}
+
+async function run_test() {
+ do_test_pending();
+
+ Assert.ok("@mozilla.org/tools/code-coverage;1" in Cc);
+
+ const codeCoverageCc = Cc["@mozilla.org/tools/code-coverage;1"];
+ Assert.ok(!!codeCoverageCc);
+
+ const codeCoverage = codeCoverageCc.getService(Ci.nsICodeCoverage);
+ Assert.ok(!!codeCoverage);
+
+ const files_orig = getFiles();
+
+ test_code_coverage_func1();
+
+ // Flush counters for the first time, we should see this function executed, but test_code_coverage_func not executed.
+ await codeCoverage.flushCounters();
+
+ const first_flush_files = getFiles();
+ const first_flush_records = parseRecords(
+ diffFiles(first_flush_files, files_orig)
+ );
+
+ Assert.ok(first_flush_records.has("test_basic.js"));
+ let fnRecords = first_flush_records
+ .get("test_basic.js")
+ .filter(record => record.type == "FN");
+ let fndaRecords = first_flush_records
+ .get("test_basic.js")
+ .filter(record => record.type == "FNDA");
+ Assert.ok(fnRecords.some(record => record.name == "top-level"));
+ Assert.ok(fnRecords.some(record => record.name == "run_test"));
+ Assert.ok(
+ fnRecords.some(record => record.name == "test_code_coverage_func1")
+ );
+ Assert.ok(
+ fndaRecords.some(record => record.name == "run_test" && record.hits == 1)
+ );
+ Assert.ok(
+ !fndaRecords.some(record => record.name == "run_test" && record.hits != 1)
+ );
+ Assert.ok(
+ fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits == 1
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits != 1
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(record => record.name == "test_code_coverage_func2")
+ );
+
+ test_code_coverage_func2();
+
+ // Flush counters for the second time, we should see this function not executed, but test_code_coverage_func executed.
+ await codeCoverage.flushCounters();
+
+ const second_flush_files = getFiles();
+ const second_flush_records = parseRecords(
+ diffFiles(second_flush_files, first_flush_files)
+ );
+
+ Assert.ok(second_flush_records.has("test_basic.js"));
+ fnRecords = second_flush_records
+ .get("test_basic.js")
+ .filter(record => record.type == "FN");
+ fndaRecords = second_flush_records
+ .get("test_basic.js")
+ .filter(record => record.type == "FNDA");
+ Assert.ok(fnRecords.some(record => record.name == "top-level"));
+ Assert.ok(fnRecords.some(record => record.name == "run_test"));
+ Assert.ok(
+ fnRecords.some(record => record.name == "test_code_coverage_func1")
+ );
+ Assert.ok(
+ fnRecords.some(record => record.name == "test_code_coverage_func2")
+ );
+ Assert.ok(
+ fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits == 0
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits != 0
+ )
+ );
+ Assert.ok(
+ fndaRecords.some(
+ record => record.name == "test_code_coverage_func2" && record.hits == 1
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "test_code_coverage_func2" && record.hits != 1
+ )
+ );
+
+ do_test_finished();
+}
diff --git a/tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js b/tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js
new file mode 100644
index 0000000000..b2e8f32915
--- /dev/null
+++ b/tools/code-coverage/tests/xpcshell/test_basic_child_and_parent.js
@@ -0,0 +1,120 @@
+/* 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/. */
+
+function test_code_coverage_func1() {
+ return 22;
+}
+
+async function run_test() {
+ do_load_child_test_harness();
+ do_test_pending();
+
+ const codeCoverage = Cc["@mozilla.org/tools/code-coverage;1"].getService(
+ Ci.nsICodeCoverage
+ );
+
+ const files_orig = getFiles();
+
+ test_code_coverage_func1();
+
+ await codeCoverage.flushCounters();
+
+ const first_flush_files = getFiles();
+ const first_flush_records = parseRecords(
+ diffFiles(first_flush_files, files_orig)
+ );
+
+ Assert.ok(first_flush_records.has("test_basic_child_and_parent.js"));
+ Assert.ok(!first_flush_records.has("support.js"));
+ let fnRecords = first_flush_records
+ .get("test_basic_child_and_parent.js")
+ .filter(record => record.type == "FN");
+ let fndaRecords = first_flush_records
+ .get("test_basic_child_and_parent.js")
+ .filter(record => record.type == "FNDA");
+ Assert.ok(fnRecords.some(record => record.name == "top-level"));
+ Assert.ok(fnRecords.some(record => record.name == "run_test"));
+ Assert.ok(
+ fnRecords.some(record => record.name == "test_code_coverage_func1")
+ );
+ Assert.ok(
+ fndaRecords.some(record => record.name == "run_test" && record.hits == 1)
+ );
+ Assert.ok(
+ !fndaRecords.some(record => record.name == "run_test" && record.hits != 1)
+ );
+ Assert.ok(
+ fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits == 1
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits != 1
+ )
+ );
+
+ sendCommand("load('support.js');", async function() {
+ await codeCoverage.flushCounters();
+
+ const second_flush_files = getFiles();
+ const second_flush_records = parseRecords(
+ diffFiles(second_flush_files, first_flush_files)
+ );
+
+ Assert.ok(second_flush_records.has("test_basic_child_and_parent.js"));
+ fnRecords = second_flush_records
+ .get("test_basic_child_and_parent.js")
+ .filter(record => record.type == "FN");
+ fndaRecords = second_flush_records
+ .get("test_basic_child_and_parent.js")
+ .filter(record => record.type == "FNDA");
+ Assert.ok(fnRecords.some(record => record.name == "top-level"));
+ Assert.ok(fnRecords.some(record => record.name == "run_test"));
+ Assert.ok(
+ fnRecords.some(record => record.name == "test_code_coverage_func1")
+ );
+ Assert.ok(
+ fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits == 0
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "test_code_coverage_func1" && record.hits != 0
+ )
+ );
+ Assert.ok(second_flush_records.has("support.js"));
+ fnRecords = second_flush_records
+ .get("support.js")
+ .filter(record => record.type == "FN");
+ fndaRecords = second_flush_records
+ .get("support.js")
+ .filter(record => record.type == "FNDA");
+ Assert.ok(fnRecords.some(record => record.name == "top-level"));
+ Assert.ok(
+ fnRecords.some(record => record.name == "test_code_coverage_func2")
+ );
+ Assert.ok(
+ fndaRecords.some(record => record.name == "top-level" && record.hits == 1)
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "top-level" && record.hits != 1
+ )
+ );
+ Assert.ok(
+ fndaRecords.some(
+ record => record.name == "test_code_coverage_func2" && record.hits == 1
+ )
+ );
+ Assert.ok(
+ !fndaRecords.some(
+ record => record.name == "test_code_coverage_func2" && record.hits != 1
+ )
+ );
+
+ do_test_finished();
+ });
+}
diff --git a/tools/code-coverage/tests/xpcshell/xpcshell.ini b/tools/code-coverage/tests/xpcshell/xpcshell.ini
new file mode 100644
index 0000000000..93f756be8b
--- /dev/null
+++ b/tools/code-coverage/tests/xpcshell/xpcshell.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+head = head.js
+support-files =
+ support.js
+
+[test_basic.js]
+[test_basic_child_and_parent.js]