Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move cov to nodejs test #1135

Merged
merged 1 commit into from
May 5, 2020

Conversation

Toxicable
Copy link

@Toxicable Toxicable commented Sep 13, 2019

This moves coverage support from jasmine_node_test to nodejs_binary, meaning any test can collect coverage.
It also
This does not report any coverage to the user, it only collects coverage and stores it in V8's format somewhere in a tmpdir that's not reasonable accessible.
This also allows support for worker threads and process coverage collection.

The next step from here would be to do more integration work with bazel coverage but this lays down the ground work for collecting coverage correctly .

PR Checklist

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

  • Feature (please, look at the "Scope of the project" section in the README.md file)

What is the current behavior?

Code coverage can only be collected via the jasmine_node_test rule

Issue Number: N/A

What is the new behavior?

Code coverage can be collected on run rule using nodejs_test

Does this PR introduce a breaking change?

  • Yes

removes the coverage attribute, instead relying on the command being invoked with bazel coverage.

Other information

fixes #1218

@Toxicable

This comment has been minimized.

@buildsize
Copy link

buildsize bot commented Sep 18, 2019

File name Previous Size New Size Change
release.tar.gz 967.47 KB 970.1 KB 2.63 KB (0%)

Copy link
Collaborator

@alexeagle alexeagle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iirina any progress on letting third-party starlark rules participate in bazel coverage?

@@ -155,6 +155,10 @@ def _nodejs_binary_impl(ctx):
if k in ctx.var.keys():
env_vars += "export %s=\"%s\"\n" % (k, ctx.var[k])

if ctx.attr.coverage:
# TODO: use proper path for tmpdir
env_vars += "export NODE_V8_COVERAGE=/tmp/$RANDOM\n"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coverage only applies to test right? bazel gives you $TEST_TMPDIR but you should wait until you're inside the test action to try to read the environment

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While only doing coverage under bazel test makes sense, we often run out test targets with bazel run when we're developing them, simply becuase it's the same command we use to run our nodejs targets.
However, if there's no way to get access to a tmpdir under bazel run then we'll have to do that, we'll have to ensure this is documented

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note even with the bazel coverage integration, we'd still need this set since the v8 coverage format is only an intermediate format

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we're only doing coverage with bazel coverage as per the below comment, I changed this to be env_vars += "export NODE_V8_COVERAGE=$TEST_TMPDIR/$RANDOM\n" - not sure if $RANDOM is correct but it's close if not

internal/node/node.bzl Outdated Show resolved Hide resolved
packages/jasmine/src/jasmine_runner.js Outdated Show resolved Hide resolved
@Toxicable
Copy link
Author

@soldair Should be good for a review now.
I've reduced the scope on this to only be the brekaing changes, ill make another PR that adds in the coverage processing script.

Copy link
Collaborator

@soldair soldair left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Toxicable
Copy link
Author

@alexeagle On this one do you want at least feature parity with jasmine_node_test#coverage=True
Before we merge this?

One path we could take:

This only solve the issue about the breaking change of removing (or maybe deprecating) the coverage attribute.
Further work needs to be done to remove v8-coverage explained in detail more here: #931 (comment)
Also relates here: #867

TLDR:

  • need Skylark support for aggrigating coverage reports accross targets
  • need source map support to swap v8-coverage for c8 or even v8-to-istanbul

@Toxicable
Copy link
Author

Took another look at this today
I was looking further at using bazel coverage for coverage aggregation.

Main issue is that COVERAGE_DIR isn't defiend when running bazel coverage
I think if that's defined then we can set NODE_V8_COVERAGE=$COVERAGE_DIR
Doing this would cause v8 to write it's coverage to this dir, then if we defined out LCOV_MERGE, it could collect all this v8 format coverage, convert it and aggregate it.

Here's a bunch of links to related topics/code that I found which I'll probably look at again next time.

https://github.com/bazelbuild/bazel/blob/f708b0f847ba6c1d2ccfd33c283a2dd81e0803e6/site/docs/skylark/rules.md#code-coverage-instrumentation
https://github.com/dropbox/dbx_build_tools/blob/3f68abae62135488e135af145a0b48e9030488ff/build_tools/py/py.bzl#L841
bazelbuild/bazel#10660
https://docs.google.com/document/d/1WRQTXQBV-m1_HDkAPvRSfGIrDW4pkI7ATPWtNdC8k9E/edit#heading=h.pt2fqnujvoh2
https://groups.google.com/forum/#!topic/bazel-discuss/LC97zBrMG84
https://github.com/bazelbuild/bazel/blob/master/tools/test/collect_cc_coverage.sh
https://github.com/bazelbuild/bazel/blob/master/tools/test/collect_coverage.sh
bazelbuild/bazel#6293
bazelbuild/bazel#8670
bazelbuild/bazel#5885

@Toxicable
Copy link
Author

Progress update; TLDR: closer but still not quite there

Along with a huge help from @armooo
We were able to somewhat get bazel coverage working.

In it's current state:
Bazel runs the program with https://github.com/bazelbuild/bazel/blob/master/tools/test/collect_coverage.sh
Which gives us the env vars we need to collect coverage from targets.
The test target runs as expected and v8 writes it's coverage information.
Then collect_coverage tries to run out lcov_merger but runfiles fails and it exits without anything helpful.

I've added a new binary: lcov_merger which will be responsible for colelcting v8 coverage from a target, merging and converting to lcov for bazel to use later on.

Assuming we can solve the issues above we should be able to use --combined_report=lcov to produce a single coverage report at bazel-out/_coverage/_coverage_report.dat

We need to use the coverage_common.instrumented_files_info provider which i've added to nodejs_binary and ts_library, it will need to be added to any rule that provides source files which need to be instrumented

Once we have lcov_merger running we may run into some source map issues.

If you want to test it out yourself run npx bazel coverage packages/jasmine/test:coverage_test on this branch

@Toxicable
Copy link
Author

This looks like the issue causing the runfiles to fail bazelbuild/bazel#4033

@Toxicable
Copy link
Author

Toxicable commented Feb 4, 2020

I've changed tac on tthis one a bit, i've moved the logic into the jasmine runner for combining and converting to lcov.
It's less portable doing it this way, since we'd need to implement it for each runner, but at least this provides a example.

However; it requires some hacks to c8 and v8-to-istanbul, around source maps, to get it working i've modified them manually.
So ill need to work on fixing those issues and maybe upstreaming something there.

Aside from that this now work with bazel coverage, however all the outpout from collect_coverage.sh is pretty annoying, might look seeing if we can turn off the set -x that it does.

Next piece is to figure out how with bazel we can get it to extract the coverage data out, it looked like we can use --combined-report=lcov but that resulted in an error

Internal error thrown during build. Printing stack trace: java.lang.NullPointerException
        at com.google.devtools.build.lib.bazel.coverage.BazelCoverageReportModule$1.getArgs(BazelCoverageReportModule.java:115)
        at com.google.devtools.build.lib.bazel.coverage.CoverageReportActionBuilder.generateCoverageReportAction(CoverageReportActionBuilder.java:246)
        at com.google.devtools.build.lib.bazel.coverage.CoverageReportActionBuilder.createCoverageActionsWrapper(CoverageReportActionBuilder.java:193)
        at com.google.devtools.build.lib.bazel.coverage.BazelCoverageReportModule$1.createCoverageReportActionsWrapper(BazelCoverageReportModule.java:97)

looks like there's an issue for it bazelbuild/bazel#6450

@Toxicable Toxicable force-pushed the nodejs_test_coverage branch 5 times, most recently from c426285 to c921f4b Compare February 7, 2020 06:12
# handled by the node process.
# If we had merely forked a child process here, we'd be responsible
# for forwarding those OS interactions.
exec "${node}" "${LAUNCHER_NODE_OPTIONS[@]:-}" "${USER_NODE_OPTIONS[@]:-}" "${MAIN}" ${ARGS[@]+"${ARGS[@]}"}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by not using exec do we still handle "stdin, stdout, signals, etc" still?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also if we're ditching exec could we compbine this with the one belonw, Line 260

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I think combining the two is reasonable. I don't think there is much value in running coverage when expected exit code != 0 but maybe someone will find that useful and it would simplify the code

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point re: the exec. We should look back at why the exec was there (trace back to the commit where it was added and see what it was fixing as I don't recall) and if there is anything special needed to pipe the io streams & signals. The non-exec non-zero exit code path had no special handling but that path is likely not used at all outside of this repo.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like where it was introduced c124496

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like w'ell need to go back to the trap approah to handle SIGTERM, SIGINT, SIGQUIT. will throw that together and see what it looks like with that other refactor in

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Toxicable . Was just looking at that commit and came to the same conclusion.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified it based off your changes and the ones in that MR, please check it well, my bash skills are not amazing

@Toxicable
Copy link
Author

Just pushed up a few changes, please take another review @gregmagolan

  1. I tried looking at the implementation of coverage_common but it's defiend in Java here https://github.com/bazelbuild/bazel/blob/7891d3b4be8549f762f32308a4085f802e7608e5/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/test/CoverageCommonApi.java
    But my wild guess is that we don't need to specify it on the ts_library since all the files are accessible through the data attribute?
    I think we should leave it off since it appears to work, but if we find a case where we need to add it, we can add it back then

  2. My feeling here is that until we have a better solution we just map everything to .js, once we figure out what use cases this dosen't satisfy we could look at options here.

  3. I think leaving this as is for now is going to be fine, we could revisit the API for that on a follow up.

@Toxicable
Copy link
Author

@googlebot I consent.

@gregmagolan
Copy link
Collaborator

@Toxicable Can you plz rebase this to head? We can land this now as master is on the 2.0.0-next.0 track now.

@Toxicable
Copy link
Author

@gregmagolan done!

@Toxicable Toxicable force-pushed the nodejs_test_coverage branch 5 times, most recently from 9055b31 to 3c4efec Compare April 25, 2020 22:28
@Toxicable
Copy link
Author

Toxicable commented Apr 25, 2020

CI failure looks like we broke something, not sure

packages/typescript/test/lit_plugin/bad.ts:9:4 - error TS2322: [lit] Unknown tag <unknown-element>. Did you mean <lit-element>?
  Check that you've imported the element, and that it's declared on the HTMLElementTagNameMap. If it can't be imported, consider adding it to the 'globalTags' plugin configuration or disabling the 'no-unknown-tag' rule.

9   <unknown-element></unknown-element>
     ~~~~~~~~~~~~~~~
//packages/typescript/test/lit_plugin:lit_plugin:1:1 - error TS2322: Expected a compilation error matching "TS2322: \\[lit\\] Unknown tag \"unknown-element\". Did you mean 'lit-element'?"

am able to reproduce it locally

@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@gregmagolan gregmagolan force-pushed the nodejs_test_coverage branch 3 times, most recently from 59586ab to 6d11fae Compare May 5, 2020 09:44
BREAKING CHANGE: jasmine_node_test not longer has the `coverage`
attribute
@gregmagolan
Copy link
Collaborator

Turns out that the failures you saw were from upgrading npm packages such as terser and ts-lit-plugin and rollup* to newer versions. Behavior of these npm packages changed slightly which causes some tests to fail. You must have turned your yarn.lock and regenerated it from scratch and the packages were marked ^x.x.x.

@alexeagle We should turn on renovate for npm packages as that would catch npm package upgrade failures. I tried configuring renovate to make npm update PRs a little while ago but still not working.

@gregmagolan
Copy link
Collaborator

In any case, this should go green now.

@gregmagolan gregmagolan self-requested a review May 5, 2020 10:31
Copy link
Collaborator

@alexeagle alexeagle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Toxicable for giving coverage so much love!

@alexeagle alexeagle merged commit 2059ea9 into bazel-contrib:master May 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

@bazel/jasmine 0.38 depends on mem@1.1 which has a security issue
6 participants