-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(builtin): enable coverage on nodejs_test
BREAKING CHANGE: jasmine_node_test not longer has the `coverage` attribute
- Loading branch information
Fabian Wiles
committed
Feb 7, 2020
1 parent
ed4454c
commit c426285
Showing
18 changed files
with
775 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"type": "node", | ||
"request": "attach", | ||
"name": "Launch Program", | ||
"internalConsoleOptions": "neverOpen", | ||
"sourceMapPathOverrides": { | ||
"../*": "${workspaceRoot}/*", | ||
"../../*": "${workspaceRoot}/*", | ||
"../../../*": "${workspaceRoot}/*", | ||
"../../../../*": "${workspaceRoot}/*", | ||
"../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../../../../../../*": "${workspaceRoot}/*", | ||
"../../../../../../../../../../../../../*": "${workspaceRoot}/*", | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") | ||
load("@npm_bazel_typescript//:index.from_src.bzl", "checked_in_ts_library") | ||
|
||
nodejs_binary( | ||
name = "lcov_merger_js", | ||
data = [ | ||
":lcov_merger.js", | ||
# TODO: what sort of error does a user get when they don't install c8 | ||
# we may need to do a check elsewhere to ensure it's installed if they want to use `bazel coverage` | ||
"@npm//c8", | ||
], | ||
entry_point = ":lcov_merger.js", | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
sh_binary( | ||
name = "lcov_merger_sh", | ||
srcs = ["lcov_merger.sh"], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
# BEGIN-INTERNAL | ||
# avoid leaking a ts dependency | ||
checked_in_ts_library( | ||
name = "compile_lcov_merger", | ||
srcs = ["lcov_merger.ts"], | ||
checked_in_js = "lcov_merger.js", | ||
visibility = ["//internal/node:__subpackages__"], | ||
deps = [ | ||
"@npm//@types/node", | ||
"@npm//c8", | ||
], | ||
) | ||
# END-INTERNAL |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/* THIS FILE GENERATED FROM .ts; see BUILD.bazel */ /* clang-format off */var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
(function (factory) { | ||
if (typeof module === "object" && typeof module.exports === "object") { | ||
var v = factory(require, exports); | ||
if (v !== undefined) module.exports = v; | ||
} | ||
else if (typeof define === "function" && define.amd) { | ||
define("build_bazel_rules_nodejs/internal/coverage/lcov_merger", ["require", "exports", "fs", "path", "crypto"], factory); | ||
} | ||
})(function (require, exports) { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* @license | ||
* Copyright 2017 The Bazel Authors. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* | ||
* You may obtain a copy of the License at | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const crypto = require("crypto"); | ||
// unfortunnately there's no types for this at the time | ||
// change to an import if some become avilable | ||
// see https://github.com/bcoe/c8/issues/195 | ||
const c8Report = require('c8/lib/report'); | ||
/** | ||
* If there are multiple args with the same name, returns an array of all of them | ||
*/ | ||
function getArgValues(name, args) { | ||
const values = args.filter(a => a.startsWith('--' + name)).map(v => v.split('=')[1]); | ||
return values; | ||
} | ||
/** | ||
* returns the first occurance of the argument by the provided name | ||
*/ | ||
function getArgValue(name, args) { | ||
return getArgValues(name, args)[0]; | ||
} | ||
/** | ||
* This script is called from https://github.com/bazelbuild/bazel/blob/master/tools/test/collect_coverage.sh#L175-L181 | ||
* when collecting coverage. | ||
* It's designed to collect the coverage of one target, since in nodejs and using NODE_V8_COVERAGE it may produce more than one | ||
* coverage file, however bazel expects there to be only one lcov file. | ||
* So this collects up the v8 coverage json's merges them and converts them to lcov for bazel to pick up later | ||
*/ | ||
function main() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const args = process.argv.splice(2); | ||
// TODO: validate these args exist | ||
// otherwise we'll get hard to debug path errors | ||
const coverageDir = getArgValue('coverage_dir', args); | ||
const outputFile = getArgValue('output_file', args); | ||
const sourceFileManifest = getArgValue('source_file_manifest', args); | ||
const filters = getArgValues('filter_sources', args); | ||
const instrumentedSourceFiles = fs.readFileSync(sourceFileManifest).toString('utf8').split('\n'); | ||
// c8 will name the output report file something that bazel wont expect | ||
// so we give it a dir that it can write to | ||
// later on we'll move and rename it into output_file as bazel expects | ||
const tmpdir = process.env['TEST_TMPDIR']; | ||
const c8OutputDir = path.join(tmpdir, crypto.randomBytes(4).toString('hex')); | ||
fs.mkdirSync(c8OutputDir); | ||
// see https://github.com/bcoe/c8/blob/master/lib/report.js | ||
// for more info on this function | ||
yield c8Report({ | ||
// TODO: check if these filters work here, otherwise apply them beforehand | ||
include: instrumentedSourceFiles, | ||
exclude: filters, | ||
reportsDirectory: c8OutputDir, | ||
// tempDirectory as actually the dir that c8 will read from for the v8 json files | ||
tempDirectory: coverageDir, | ||
// we may need to use resolve here to change the base dir, from the docs: "resolve paths to alternate base directory" | ||
// resolve: '' | ||
// TODO: check that lcov is correct here, we may need to do another conversion | ||
reporter: 'lcov' | ||
}).run(); | ||
// this assumes there's only one report from c8 | ||
const lcovReport = fs.readdirSync(c8OutputDir)[0]; | ||
// mopves the report into the fiels bazel expects | ||
fs.copyFileSync(path.join(c8OutputDir, lcovReport), outputFile); | ||
}); | ||
} | ||
main(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/** | ||
* @license | ||
* Copyright 2017 The Bazel Authors. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* | ||
* You may obtain a copy of the License at | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import * as crypto from 'crypto'; | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
// unfortunnately there's no types for this at the time | ||
// change to an import if some become avilable | ||
// see https://github.com/bcoe/c8/issues/195 | ||
const c8Report = require('c8/lib/report'); | ||
|
||
/** | ||
* If there are multiple args with the same name, returns an array of all of them | ||
*/ | ||
function getArgValues(name: string, args: string[]): string[] { | ||
const values = args.filter(a => a.startsWith('--' + name)).map(v => v.split('=')[1]); | ||
return values; | ||
} | ||
|
||
/** | ||
* returns the first occurance of the argument by the provided name | ||
*/ | ||
function getArgValue(name: string, args: string[]): string { | ||
return getArgValues(name, args)[0]; | ||
} | ||
|
||
/** | ||
* This script is called from | ||
* https://github.com/bazelbuild/bazel/blob/master/tools/test/collect_coverage.sh#L175-L181 when | ||
* collecting coverage. It's designed to collect the coverage of one target, since in nodejs and | ||
* using NODEJS_V8_COVERAGE it may produce more than one coverage file, however bazel expects there | ||
* to be only one lcov file. So this collects up the v8 coverage json's merges them and converts | ||
* them to lcov for bazel to pick up later | ||
*/ | ||
async function main(): Promise<number> { | ||
const args = process.argv.splice(2); | ||
|
||
// TODO: validate these args exist | ||
// otherwise we'll get hard to debug path errors | ||
const coverageDir = getArgValue('coverage_dir', args); | ||
const outputFile = getArgValue('output_file', args); | ||
const sourceFileManifest = getArgValue('source_file_manifest', args); | ||
// filter_sources is another arg provided, but at tthis stage it's not needed | ||
// leaving this here incase it's needed later on | ||
// const filters = getArgValues('filter_sources', args); | ||
|
||
const instrumentedSourceFiles = fs.readFileSync(sourceFileManifest).toString('utf8').split('\n'); | ||
|
||
// c8 will name the output report file lcov.info | ||
// so we give it a dir that it can write to | ||
// later on we'll move and rename it into output_file as bazel expects | ||
const tmpdir = process.env['TEST_TMPDIR']; | ||
const c8OutputDir = path.join(tmpdir, crypto.randomBytes(4).toString('hex')); | ||
fs.mkdirSync(c8OutputDir); | ||
|
||
const includes = instrumentedSourceFiles | ||
// we can only cover js files | ||
.filter(f => ['.js', '.jsx', '.ts', '.tsx'].includes(path.extname(f))) | ||
// the actual coverage written by v8 will only inclue urls to .js | ||
// so map inputs to their outputs | ||
.map(f => { | ||
const p = path.parse(f); | ||
return path.format({...p, base: null, ext: '.js'}); | ||
}); | ||
|
||
// see https://github.com/bcoe/c8/blob/master/lib/report.js | ||
// for more info on this function | ||
// TODO: enable the --all functionality | ||
await c8Report({ | ||
include: includes, | ||
exclude: [], | ||
reportsDirectory: c8OutputDir, | ||
// tempDirectory as actually the dir that c8 will read from for the v8 json files | ||
tempDirectory: coverageDir, | ||
resolve: '', | ||
// TODO: maybe add an attribute to allow more reporters | ||
// or maybe an env var? | ||
reporter: ['lcovonly'] | ||
}).run(); | ||
// moves the report into the files bazel expects | ||
// lcovonly names this file lcov.info | ||
fs.copyFileSync(path.join(c8OutputDir, 'lcov.info'), outputFile); | ||
|
||
return 0; | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#!/usr/bin/env bash | ||
|
||
# @license | ||
# Copyright 2017 The Bazel Authors. All rights reserved. | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
|
||
# You may obtain a copy of the License at | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
# This is a workaround for bazelbuild/bazel#6293. Since Bazel 0.18.0, Bazel | ||
# expects tests to have an "$lcov_merger' or "_lcov_merger" attribute that | ||
# points to an executable. If this is missing, the test driver fails. | ||
|
||
# Copied from https://github.com/bazelbuild/rules_go/blob/64c97b54ea2918fc7f1a59d68cd27d1fdb0bd663/go/tools/builders/lcov_merger.sh | ||
|
||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.