blob: 3c2bb9cc56c0b139336f2a6d009a528d1df823da [file] [log] [blame]
lberki8a5752d2017-05-23 17:48:14 +02001#!/bin/bash -x
Yue Ganaf1e3c22016-12-05 14:05:15 +00002
3# Copyright 2016 The Bazel Authors. All rights reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Wrapper script for collecting code coverage during test execution.
18#
19# Expected environment:
20# COVERAGE_MANIFEST - mandatory, location of the instrumented file manifest
21# LCOV_MERGER - mandatory, location of the LcovMerger
22# COVERAGE_DIR - optional, location of the coverage temp directory
23# COVERAGE_OUTPUT_FILE - optional, location of the final lcov file
24#
25# Script expects that it will be started in the execution root directory and
26# not in the test's runfiles directory.
27
28if [[ -z "$COVERAGE_MANIFEST" ]]; then
29 echo --
30 echo Coverage runner: \$COVERAGE_MANIFEST is not set
31 echo Current environment:
32 env | sort
33 exit 1
34fi
35
36# When collect_coverage.sh is used, test runner must be instructed not to cd
37# to the test's runfiles directory.
iirina190d4f82018-08-23 06:05:34 -070038export ROOT="$PWD"
Yue Ganaf1e3c22016-12-05 14:05:15 +000039
40if [[ "$COVERAGE_MANIFEST" != /* ]]; then
41 # Canonicalize the path to coverage manifest so that tests can find it.
42 export COVERAGE_MANIFEST="$ROOT/$COVERAGE_MANIFEST"
43fi
44
45# write coverage data outside of the runfiles tree
46export COVERAGE_DIR=${COVERAGE_DIR:-"$ROOT/coverage"}
47# make COVERAGE_DIR an absolute path
48if ! [[ $COVERAGE_DIR == $ROOT* ]]; then
49 COVERAGE_DIR=$ROOT/$COVERAGE_DIR
50fi
51
52mkdir -p "$COVERAGE_DIR"
53COVERAGE_OUTPUT_FILE=${COVERAGE_OUTPUT_FILE:-"$COVERAGE_DIR/_coverage.dat"}
54# make COVERAGE_OUTPUT_FILE an absolute path
55if ! [[ $COVERAGE_OUTPUT_FILE == $ROOT* ]]; then
56 COVERAGE_OUTPUT_FILE=$ROOT/$COVERAGE_OUTPUT_FILE
57fi
58
59
60# Java
61# --------------------------------------
62export JAVA_COVERAGE_FILE=$COVERAGE_DIR/jvcov.dat
63# Let tests know that it is a coverage run
64export COVERAGE=1
65export BULK_COVERAGE_RUN=1
66
67
iirinaeb3e07d2018-09-20 05:58:31 -070068for name in "$LCOV_MERGER"; do
69 if [[ ! -e $name ]]; then
70 echo --
71 echo Coverage runner: cannot locate file $name
72 exit 1
73 fi
74done
Yue Ganaf1e3c22016-12-05 14:05:15 +000075
iirinaeb3e07d2018-09-20 05:58:31 -070076# Setting up the environment for executing the C++ tests.
ulfjackb3763e92020-01-27 05:09:37 -080077if [[ -z "$GCOV_PREFIX_STRIP" ]]; then
78 # TODO: GCOV_PREFIX_STRIP=3 is incorrect on MacOS in the default setup
79 export GCOV_PREFIX_STRIP=3
80fi
iirinaeb3e07d2018-09-20 05:58:31 -070081export GCOV_PREFIX="${COVERAGE_DIR}"
82export LLVM_PROFILE_FILE="${COVERAGE_DIR}/%h-%p-%m.profraw"
Yue Ganaf1e3c22016-12-05 14:05:15 +000083
elenairina2b36cd32019-01-11 10:53:50 -080084# In coverage mode for Java, we need to merge the runtime classpath before
85# running the tests. JacocoCoverageRunner uses this merged jar in order
86# to get coverage data.
87#
88# Merge the classpath using SingleJar and save it in the environment
89# variable JACOCO_METADATA_JAR. The jars on the runtime classpath are listed
90# in the file $JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE.
91#
92# We need to merge the jars here because the merged jar can be an input
93# too large (the combined merged jars for several big tests in a run
94# can go over 10G). Not merging the jars and making
95# JacocoCoverageRunner read every individual jar goes over the shutdown hook
96# time limit in the coverage runner (~few seconds).
97#
98# SINGLE_JAR_TOOL Exec path of SingleJar.
99#
100# JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE Exec path of a file that contains the
101# relative paths of the jars on the runtime
102# classpath delimited by newline.
103if [[ ! -z "${JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE}" ]]; then
104 JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE="${PWD}/${JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE}"
105 SINGLE_JAR_TOOL="${PWD}/${SINGLE_JAR_TOOL}"
106
107 # Create a paramsfile for invoking SingleJar.
108 mkdir -p "${COVERAGE_DIR}"
109 single_jar_params_file="${COVERAGE_DIR}/runtime_classpath.paramsfile"
110 touch "$single_jar_params_file"
111
112 # Export JACOCO_METADATA_JAR in order for JacocoCoverageRunner to be able
113 # to read it.
114 export JACOCO_METADATA_JAR="${COVERAGE_DIR}/coverage-runtime_merged_instr.jar"
115
116 echo -e "--output ${JACOCO_METADATA_JAR}\n--sources" >> "$single_jar_params_file"
117
118 # Append the runfiles prefix to all the relative paths found in
119 # JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE, to invoke SingleJar with the
120 # absolute paths.
121 RUNFILES_PREFIX="$TEST_SRCDIR/$TEST_WORKSPACE/"
122 cat "$JAVA_RUNTIME_CLASSPATH_FOR_COVERAGE" | sed "s@^@$RUNFILES_PREFIX@" >> "$single_jar_params_file"
123
124 # Invoke SingleJar. This will create JACOCO_METADATA_JAR.
125 "${SINGLE_JAR_TOOL}" "@$single_jar_params_file"
126fi
127
iirina9e183ca2018-09-27 04:23:29 -0700128# TODO(bazel-team): cd should be avoided.
Mansheng Yangb0b90482017-09-15 10:19:04 +0200129cd "$TEST_SRCDIR/$TEST_WORKSPACE"
iirina190d4f82018-08-23 06:05:34 -0700130# Execute the test.
Yue Ganaf1e3c22016-12-05 14:05:15 +0000131"$@"
132TEST_STATUS=$?
133
iirina190d4f82018-08-23 06:05:34 -0700134# Always create the coverage report.
Yue Ganaf1e3c22016-12-05 14:05:15 +0000135touch $COVERAGE_OUTPUT_FILE
136
137if [[ $TEST_STATUS -ne 0 ]]; then
138 echo --
139 echo Coverage runner: Not collecting coverage for failed test.
140 echo The following commands failed with status $TEST_STATUS
141 echo "$@"
142 exit $TEST_STATUS
143fi
144
iirina9e183ca2018-09-27 04:23:29 -0700145# TODO(bazel-team): cd should be avoided.
Yue Ganaf1e3c22016-12-05 14:05:15 +0000146cd $ROOT
147
iirina9e183ca2018-09-27 04:23:29 -0700148# Call the C++ code coverage collection script.
iirina190d4f82018-08-23 06:05:34 -0700149if [[ "$CC_CODE_COVERAGE_SCRIPT" ]]; then
150 eval "${CC_CODE_COVERAGE_SCRIPT}"
lberki8a5752d2017-05-23 17:48:14 +0200151fi
152
iirina81efc3f2018-10-29 05:23:09 -0700153
iirinaeb3e07d2018-09-20 05:58:31 -0700154# Export the command line that invokes LcovMerger with the flags:
iirina0d693712018-09-24 09:58:50 -0700155# --coverage_dir The absolute path of the directory where the
156# intermediate coverage reports are located.
157# CoverageOutputGenerator will search for files with
158# the .dat and .gcov extension under this directory and
159# will merge everything it found in the output report.
160#
161# --output_file The absolute path of the merged coverage report.
162#
163# --filter_sources Filters out the sources that match the given regexes
164# from the final coverage report. This is needed
165# because some coverage tools (e.g. gcov) do not have
166# any way of specifying what sources to exclude when
167# generating the code coverage report (in this case the
168# syslib sources).
169#
170# --source_file_manifest The absolute path of the coverage source file
171# manifest. CoverageOutputGenerator uses this file to
172# keep only the C++ sources found in the manifest.
173# For other languages the sources in the manifest are
174# ignored.
iirina81efc3f2018-10-29 05:23:09 -0700175LCOV_MERGER_CMD="${LCOV_MERGER} --coverage_dir=${COVERAGE_DIR} \
iirinaeb3e07d2018-09-20 05:58:31 -0700176 --output_file=${COVERAGE_OUTPUT_FILE} \
177 --filter_sources=/usr/bin/.+ \
178 --filter_sources=/usr/lib/.+ \
iirinaa4a76592018-10-12 10:43:37 -0700179 --filter_sources=/usr/include.+ \
iirina0d693712018-09-24 09:58:50 -0700180 --filter_sources=.*external/.+ \
181 --source_file_manifest=${COVERAGE_MANIFEST}"
Yue Ganaf1e3c22016-12-05 14:05:15 +0000182
iirina81efc3f2018-10-29 05:23:09 -0700183if [[ $COVERAGE_REPORTED_TO_ACTUAL_SOURCES_FILE ]]; then
184 LCOV_MERGER_CMD="$LCOV_MERGER_CMD\
185 --sources_to_replace_file=$ROOT/$COVERAGE_REPORTED_TO_ACTUAL_SOURCES_FILE"
186fi
Yue Ganaf1e3c22016-12-05 14:05:15 +0000187
188if [[ $DISPLAY_LCOV_CMD ]] ; then
189 echo "Running lcov_merger"
190 echo $LCOV_MERGER_CMD
191 echo "-----------------"
192fi
193
lberki913478d2017-06-09 10:31:39 -0400194# JAVA_RUNFILES is set to the runfiles of the test, which does not necessarily
195# contain a JVM (it does only if the test has a Java binary somewhere). So let
196# the LCOV merger discover where its own runfiles tree is.
197JAVA_RUNFILES= exec $LCOV_MERGER_CMD