xref: /aosp_15_r20/external/grpc-grpc/tools/fuzzing/generate_coverage_report.sh (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1#!/bin/bash
2# Copyright 2023 The gRPC Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# This tool builds and runs a fuzzer target and generates coverage report under
17# /tmp.
18#
19# Example:
20# Run fuzzer with existing corpus (no fuzzing):
21# $ ./tools/fuzzing/generate_coverage_report.sh //test/core/end2end/fuzzers:api_fuzzer test/core/end2end/fuzzers/api_fuzzer_corpus/*
22#
23# Run with fuzzing:
24# $ ./tools/fuzzing/generate_coverage_report.sh //test/core/end2end/fuzzers:api_fuzzer -max_total_time=10 test/core/end2end/fuzzers/api_fuzzer_corpus
25#
26# Note that if a crash happened during fuzzing, the coverage data will not be dumped.
27# See https://github.com/google/fuzzing/issues/41#issuecomment-1027653690 for workaround.
28
29err() {
30  echo "$*" >&2
31}
32
33if [[ -z "$1" ]]; then
34  err "target not specified"
35  exit 1
36fi
37
38RANDOM=$(date +%s)
39FILENAME="${RANDOM}"
40
41export LLVM_PROFILE_FILE=/tmp/"${FILENAME}".profraw
42OUTPUT_BASE=$(bazel info output_base)
43MIDDLE="execroot/com_github_grpc_grpc/bazel-out/k8-dbg/bin"
44
45CLANG_MAJOR_VERSION=$(clang --version | grep version | sed -r 's/.*version ([^\.]+).*/\1/')
46LLVM_PROFDATA="llvm-profdata-${CLANG_MAJOR_VERSION}"
47LLVM_COV="llvm-cov-${CLANG_MAJOR_VERSION}"
48
49which "${LLVM_PROFDATA}"
50if (( $? != 0 )); then
51  err "${LLVM_PROFDATA} not found"
52  exit 1
53fi
54
55TARGET=$(bazel query "$1")
56TARGET_BINARY_PATH="${OUTPUT_BASE}/${MIDDLE}/$(echo ${TARGET:2} | sed 's/:/\//')"
57
58# Build:
59bazel build --dynamic_mode=off --config=dbg --config=fuzzer_asan --config=coverage "${TARGET}"
60# Run:
61"${TARGET_BINARY_PATH}" ${@:2}
62
63if [[ ! -e "${LLVM_PROFILE_FILE}" ]]; then
64  err "Profile file ${LLVM_PROFILE_FILE} not created"
65  exit 1
66fi
67
68# Create coverage report:
69"${LLVM_PROFDATA}" merge -sparse "${LLVM_PROFILE_FILE}" -o /tmp/"${FILENAME}".profdata
70"${LLVM_COV}" report "${TARGET_BINARY_PATH}" --format=text --instr-profile=/tmp/"${FILENAME}".profdata > /tmp/"${FILENAME}".cov
71
72if (( $? == 0 )); then
73  echo "Coverage summary report created: /tmp/${FILENAME}.cov"
74  echo "Merged profile data file:        /tmp/${FILENAME}.profdata"
75  echo "Raw profile data file:           /tmp/${FILENAME}.profraw"
76  echo "There are other ways to explore the data, see https://clang.llvm.org/docs/SourceBasedCodeCoverage.html#creating-coverage-reports"
77else
78  err "Something went wrong"
79  exit 1
80fi
81