Skip to content

Commit

Permalink
[kcov] Support python coverage with Bazel 6 (RobotLocomotion#18616)
Browse files Browse the repository at this point in the history
* [kcov] Support python coverage with Bazel 6

To work with the updated python stubs, pre-create our test output
directory, and absorb/ignore more kinds of coverage-py command lines.
  • Loading branch information
rpoyner-tri authored and Marco A. Gutierrez committed Feb 6, 2023
1 parent b2ff0d0 commit bf39355
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 16 deletions.
6 changes: 4 additions & 2 deletions tools/dynamic_analysis/kcov.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ eof
# If we have a Python target...
if [[ $(file -b --mime -L "$1") == *text/x-*python* ]]; then
# Bazel's Python wrappers[1] require extra treatment. PYTHON_COVERAGE and
# COVERAGE_DIR are consumed by the wrapper.
# [1]: https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt
# COVERAGE_DIR are consumed by the wrapper. The wrapper will try to write
# to COVERAGE_DIR, so it needs to be created here first.
# [1]: https://github.com/bazelbuild/bazel/blob/6.0.0/src/main/java/com/google/devtools/build/lib/bazel/rules/python/python_stub_template.txt
export PYTHON_COVERAGE="${WORKSPACE}/tools/dynamic_analysis/kcoverage.py"
export COVERAGE_DIR="${TEST_UNDECLARED_OUTPUTS_DIR}/kcov"
mkdir -p ${COVERAGE_DIR}

# DRAKE_KCOV_COMMAND is consumed by drake's kcov/python integration.
export DRAKE_KCOV_COMMAND
Expand Down
32 changes: 18 additions & 14 deletions tools/dynamic_analysis/kcoverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,17 @@
import sys


def parse_command_line(argv):
"""Absorb the coverage.py command line. We may ignore most of it. Returns
a pair of an argparse.Namespace object, and a list of un-parsed arguments
to the target executable.
def parse_run_command(argv):
"""Absorb the coverage.py 'run' command line. Drake will ignore most of it.
Returns a list of un-parsed arguments to the target executable.
"""
parser = argparse.ArgumentParser()
parser.add_argument('verb', type=str, help='coverage.py verb')
parser.add_argument('exe', type=str, help='target executable')
parser.add_argument('-a', action='store_true', default=False,
help='coverage.py -a')
parser.add_argument('--branch', action='store_true', default=False,
help='coverage.py --branch')
parser = argparse.ArgumentParser(prog='kcoverage.py run')
ignore = "Drake will ignore this coverage.py argument."
parser.add_argument('-a', '--append', action='store_true', help=ignore)
parser.add_argument('--branch', action='store_true', help=ignore)
parser.add_argument('--rcfile', type=str, help=ignore)

return parser.parse_known_args(argv)
return parser.parse_known_args(argv)[1]


def exec_with_kcov(exe, exe_args):
Expand All @@ -48,8 +45,15 @@ def exec_with_kcov(exe, exe_args):


def main():
args, extra = parse_command_line(sys.argv[1:])
exec_with_kcov(args.exe, extra)
verb = sys.argv[1]
if verb == 'lcov':
# Bazel 6 invokes 'lcov', but drake/kcov don't need to do anything.
return
# Drake/kcov support only needs to implement 'run'; anything else that
# reached here is an error.
assert verb == 'run', f"Command '{verb}' not implemented."
extra = parse_run_command(sys.argv[2:])
exec_with_kcov(extra[0], extra[1:])


if __name__ == "__main__":
Expand Down

0 comments on commit bf39355

Please sign in to comment.