1/* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5/* exported PerTestCoverageUtils */ 6 7"use strict"; 8 9var EXPORTED_SYMBOLS = ["PerTestCoverageUtils"]; 10 11const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); 12 13const env = Cc["@mozilla.org/process/environment;1"].getService( 14 Ci.nsIEnvironment 15); 16// This is the directory where gcov is emitting the gcda files. 17const gcovPrefixPath = env.get("GCOV_PREFIX"); 18// This is the directory where codecoverage.py is expecting to see the gcda files. 19const gcovResultsPath = env.get("GCOV_RESULTS_DIR"); 20// This is the directory where the JS engine is emitting the lcov files. 21const jsvmPrefixPath = env.get("JS_CODE_COVERAGE_OUTPUT_DIR"); 22// This is the directory where codecoverage.py is expecting to see the lcov files. 23const jsvmResultsPath = env.get("JSVM_RESULTS_DIR"); 24 25const gcovPrefixDir = Cc["@mozilla.org/file/local;1"].createInstance( 26 Ci.nsIFile 27); 28if (gcovPrefixPath) { 29 gcovPrefixDir.initWithPath(gcovPrefixPath); 30} 31 32let gcovResultsDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); 33if (gcovResultsPath) { 34 gcovResultsDir.initWithPath(gcovResultsPath); 35} 36 37const jsvmPrefixDir = Cc["@mozilla.org/file/local;1"].createInstance( 38 Ci.nsIFile 39); 40if (jsvmPrefixPath) { 41 jsvmPrefixDir.initWithPath(jsvmPrefixPath); 42} 43 44let jsvmResultsDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); 45if (jsvmResultsPath) { 46 jsvmResultsDir.initWithPath(jsvmResultsPath); 47} 48 49function awaitPromise(promise) { 50 let ret; 51 let complete = false; 52 let error = null; 53 promise 54 .catch(e => (error = e)) 55 .then(v => { 56 ret = v; 57 complete = true; 58 }); 59 Services.tm.spinEventLoopUntil( 60 "PerTestCoverageUtils.jsm:awaitPromise", 61 () => complete 62 ); 63 if (error) { 64 throw new Error(error); 65 } 66 return ret; 67} 68 69function removeDirectoryContents(dir) { 70 let entries = dir.directoryEntries; 71 while (entries.hasMoreElements()) { 72 entries.nextFile.remove(true); 73 } 74} 75 76function moveDirectoryContents(src, dst) { 77 let entries = src.directoryEntries; 78 while (entries.hasMoreElements()) { 79 entries.nextFile.moveTo(dst, null); 80 } 81} 82 83var PerTestCoverageUtils = class PerTestCoverageUtilsClass { 84 // Resets the counters to 0. 85 static async beforeTest() { 86 if (!PerTestCoverageUtils.enabled) { 87 return; 88 } 89 90 // Flush the counters. 91 let codeCoverageService = Cc[ 92 "@mozilla.org/tools/code-coverage;1" 93 ].getService(Ci.nsICodeCoverage); 94 await codeCoverageService.flushCounters(); 95 96 // Remove coverage files created by the flush, and those that might have been created between the end of a previous test and the beginning of the next one (e.g. some tests can create a new content process for every sub-test). 97 removeDirectoryContents(gcovPrefixDir); 98 removeDirectoryContents(jsvmPrefixDir); 99 100 // Move coverage files from the GCOV_RESULTS_DIR and JSVM_RESULTS_DIR directories, so we can accumulate the counters. 101 moveDirectoryContents(gcovResultsDir, gcovPrefixDir); 102 moveDirectoryContents(jsvmResultsDir, jsvmPrefixDir); 103 } 104 105 static beforeTestSync() { 106 awaitPromise(this.beforeTest()); 107 } 108 109 // Dumps counters and moves the gcda files in the directory expected by codecoverage.py. 110 static async afterTest() { 111 if (!PerTestCoverageUtils.enabled) { 112 return; 113 } 114 115 // Flush the counters. 116 let codeCoverageService = Cc[ 117 "@mozilla.org/tools/code-coverage;1" 118 ].getService(Ci.nsICodeCoverage); 119 await codeCoverageService.flushCounters(); 120 121 // Move the coverage files in GCOV_RESULTS_DIR and JSVM_RESULTS_DIR, so that the execution from now to shutdown (or next test) is not counted. 122 moveDirectoryContents(gcovPrefixDir, gcovResultsDir); 123 moveDirectoryContents(jsvmPrefixDir, jsvmResultsDir); 124 } 125 126 static afterTestSync() { 127 awaitPromise(this.afterTest()); 128 } 129}; 130 131PerTestCoverageUtils.enabled = !!gcovResultsPath; 132