1*61c4878aSAndroid Build Coastguard Worker# Copyright 2020 The Pigweed Authors 2*61c4878aSAndroid Build Coastguard Worker# 3*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of 5*61c4878aSAndroid Build Coastguard Worker# the License at 6*61c4878aSAndroid Build Coastguard Worker# 7*61c4878aSAndroid Build Coastguard Worker# https://www.apache.org/licenses/LICENSE-2.0 8*61c4878aSAndroid Build Coastguard Worker# 9*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under 13*61c4878aSAndroid Build Coastguard Worker# the License. 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard Workerimport("//build_overrides/pigweed.gni") 16*61c4878aSAndroid Build Coastguard Worker 17*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/error.gni") 18*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_build/test_info.gni") 19*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_toolchain/host_clang/toolchains.gni") 20*61c4878aSAndroid Build Coastguard Workerimport("$dir_pw_unit_test/test.gni") 21*61c4878aSAndroid Build Coastguard Worker 22*61c4878aSAndroid Build Coastguard Worker# Creates a libFuzzer-based fuzzer executable target and unit test 23*61c4878aSAndroid Build Coastguard Worker# 24*61c4878aSAndroid Build Coastguard Worker# This will link `sources` and `deps` with the libFuzzer compiler runtime. The 25*61c4878aSAndroid Build Coastguard Worker# `sources` and `deps` should include a definition of the standard LLVM fuzz 26*61c4878aSAndroid Build Coastguard Worker# target function, `LLVMFuzzerTestOneInput`. For more details, see: 27*61c4878aSAndroid Build Coastguard Worker# //pw_fuzzer/docs.rst 28*61c4878aSAndroid Build Coastguard Worker# https://llvm.org/docs/LibFuzzer.html 29*61c4878aSAndroid Build Coastguard Worker# 30*61c4878aSAndroid Build Coastguard Worker# Additionally, this creates a unit test that does not generate fuzzer inputs 31*61c4878aSAndroid Build Coastguard Worker# and simply executes the fuzz target function with fixed inputs. This is useful 32*61c4878aSAndroid Build Coastguard Worker# for verifying the fuzz target function compiles, links, and runs even when not 33*61c4878aSAndroid Build Coastguard Worker# using a fuzzing-capable host or toolchain. 34*61c4878aSAndroid Build Coastguard Worker# 35*61c4878aSAndroid Build Coastguard Worker# Args: 36*61c4878aSAndroid Build Coastguard Worker# - enable_test_if: (optional) Passed as `enable_if` to the unit test. 37*61c4878aSAndroid Build Coastguard Worker# - All of the `pw_executable` args are accepted. 38*61c4878aSAndroid Build Coastguard Workertemplate("pw_fuzzer") { 39*61c4878aSAndroid Build Coastguard Worker if (!pw_toolchain_FUZZING_ENABLED) { 40*61c4878aSAndroid Build Coastguard Worker pw_error(target_name) { 41*61c4878aSAndroid Build Coastguard Worker message_lines = [ "Toolchain does not enable fuzzing." ] 42*61c4878aSAndroid Build Coastguard Worker } 43*61c4878aSAndroid Build Coastguard Worker not_needed(invoker, "*") 44*61c4878aSAndroid Build Coastguard Worker } else if (pw_toolchain_SANITIZERS == []) { 45*61c4878aSAndroid Build Coastguard Worker pw_error(target_name) { 46*61c4878aSAndroid Build Coastguard Worker message_lines = [ "No sanitizer runtime set." ] 47*61c4878aSAndroid Build Coastguard Worker } 48*61c4878aSAndroid Build Coastguard Worker not_needed(invoker, "*") 49*61c4878aSAndroid Build Coastguard Worker } else { 50*61c4878aSAndroid Build Coastguard Worker # Metadata for this test when used as part of a pw_test_group target. 51*61c4878aSAndroid Build Coastguard Worker _fuzzer_target_name = target_name 52*61c4878aSAndroid Build Coastguard Worker _fuzzer_output_dir = "${target_out_dir}/bin" 53*61c4878aSAndroid Build Coastguard Worker if (defined(invoker.output_dir)) { 54*61c4878aSAndroid Build Coastguard Worker _fuzzer_output_dir = invoker.output_dir 55*61c4878aSAndroid Build Coastguard Worker } 56*61c4878aSAndroid Build Coastguard Worker 57*61c4878aSAndroid Build Coastguard Worker _tags = [ "libfuzzer" ] 58*61c4878aSAndroid Build Coastguard Worker if (defined(invoker.tags)) { 59*61c4878aSAndroid Build Coastguard Worker _tags += invoker.tags 60*61c4878aSAndroid Build Coastguard Worker } 61*61c4878aSAndroid Build Coastguard Worker 62*61c4878aSAndroid Build Coastguard Worker _test_metadata = "${target_name}.metadata" 63*61c4878aSAndroid Build Coastguard Worker _extra_metadata = { 64*61c4878aSAndroid Build Coastguard Worker forward_variables_from(invoker, [ "extra_metadata" ]) 65*61c4878aSAndroid Build Coastguard Worker test_directory = rebase_path(_fuzzer_output_dir, root_build_dir) 66*61c4878aSAndroid Build Coastguard Worker } 67*61c4878aSAndroid Build Coastguard Worker pw_test_info(_test_metadata) { 68*61c4878aSAndroid Build Coastguard Worker test_type = "fuzz_test" 69*61c4878aSAndroid Build Coastguard Worker test_name = _fuzzer_target_name 70*61c4878aSAndroid Build Coastguard Worker tags = _tags 71*61c4878aSAndroid Build Coastguard Worker extra_metadata = _extra_metadata 72*61c4878aSAndroid Build Coastguard Worker } 73*61c4878aSAndroid Build Coastguard Worker 74*61c4878aSAndroid Build Coastguard Worker pw_executable(target_name) { 75*61c4878aSAndroid Build Coastguard Worker configs = [] 76*61c4878aSAndroid Build Coastguard Worker deps = [] 77*61c4878aSAndroid Build Coastguard Worker forward_variables_from(invoker, 78*61c4878aSAndroid Build Coastguard Worker "*", 79*61c4878aSAndroid Build Coastguard Worker [ 80*61c4878aSAndroid Build Coastguard Worker "enable_test_if", 81*61c4878aSAndroid Build Coastguard Worker "visibility", 82*61c4878aSAndroid Build Coastguard Worker ]) 83*61c4878aSAndroid Build Coastguard Worker forward_variables_from(invoker, [ "visibility" ]) 84*61c4878aSAndroid Build Coastguard Worker if (pw_toolchain_OSS_FUZZ_ENABLED) { 85*61c4878aSAndroid Build Coastguard Worker configs += [ "$dir_pw_fuzzer:libfuzzer_oss_fuzz_config" ] 86*61c4878aSAndroid Build Coastguard Worker } else { 87*61c4878aSAndroid Build Coastguard Worker configs += [ "$dir_pw_fuzzer:libfuzzer_config" ] 88*61c4878aSAndroid Build Coastguard Worker } 89*61c4878aSAndroid Build Coastguard Worker deps += [ 90*61c4878aSAndroid Build Coastguard Worker ":$_test_metadata", 91*61c4878aSAndroid Build Coastguard Worker "$dir_pw_fuzzer:libfuzzer", 92*61c4878aSAndroid Build Coastguard Worker ] 93*61c4878aSAndroid Build Coastguard Worker output_dir = _fuzzer_output_dir 94*61c4878aSAndroid Build Coastguard Worker metadata = { 95*61c4878aSAndroid Build Coastguard Worker test_barrier = [ ":$_test_metadata" ] 96*61c4878aSAndroid Build Coastguard Worker } 97*61c4878aSAndroid Build Coastguard Worker } 98*61c4878aSAndroid Build Coastguard Worker } 99*61c4878aSAndroid Build Coastguard Worker 100*61c4878aSAndroid Build Coastguard Worker group(target_name + ".run") { 101*61c4878aSAndroid Build Coastguard Worker } 102*61c4878aSAndroid Build Coastguard Worker 103*61c4878aSAndroid Build Coastguard Worker pw_test("${target_name}_test") { 104*61c4878aSAndroid Build Coastguard Worker deps = [] 105*61c4878aSAndroid Build Coastguard Worker forward_variables_from(invoker, "*", [ "visibility" ]) 106*61c4878aSAndroid Build Coastguard Worker forward_variables_from(invoker, [ "visibility" ]) 107*61c4878aSAndroid Build Coastguard Worker deps += [ "$dir_pw_fuzzer:libfuzzer_test" ] 108*61c4878aSAndroid Build Coastguard Worker enable_if = !defined(enable_test_if) || enable_test_if 109*61c4878aSAndroid Build Coastguard Worker } 110*61c4878aSAndroid Build Coastguard Worker} 111*61c4878aSAndroid Build Coastguard Worker 112*61c4878aSAndroid Build Coastguard Worker# Defines a related collection of fuzzers. 113*61c4878aSAndroid Build Coastguard Worker# 114*61c4878aSAndroid Build Coastguard Worker# This template wraps `pw_test_group` to collect a set of libFuzzer-based fuzzer 115*61c4878aSAndroid Build Coastguard Worker# tests. These unit tests do not perform fuzzing. Instead, they execute the fuzz 116*61c4878aSAndroid Build Coastguard Worker# target function with a set of fixed inputs to verify the fuzzer can be built 117*61c4878aSAndroid Build Coastguard Worker# and run. 118*61c4878aSAndroid Build Coastguard Worker# 119*61c4878aSAndroid Build Coastguard Worker# If and only if the current toolchain supports fuzzing, this template will also 120*61c4878aSAndroid Build Coastguard Worker# include the fuzzers themselves. 121*61c4878aSAndroid Build Coastguard Worker# 122*61c4878aSAndroid Build Coastguard Worker# As with `pw_test_group`, targets defined using this template will produce test 123*61c4878aSAndroid Build Coastguard Worker# metadata with a `test_type` of "test_group" and an additional `deps` list 124*61c4878aSAndroid Build Coastguard Worker# describing the tests collected by this target. 125*61c4878aSAndroid Build Coastguard Worker# 126*61c4878aSAndroid Build Coastguard Worker# Args: 127*61c4878aSAndroid Build Coastguard Worker# - fuzzers: List of `pw_fuzzer` targets for each of the fuzzers in the group. 128*61c4878aSAndroid Build Coastguard Worker# 129*61c4878aSAndroid Build Coastguard Worker# - The following args have the same meaning as for `pw_python_action`: 130*61c4878aSAndroid Build Coastguard Worker# group_deps 131*61c4878aSAndroid Build Coastguard Worker# enable_if 132*61c4878aSAndroid Build Coastguard Worker# output_metadata 133*61c4878aSAndroid Build Coastguard Workertemplate("pw_fuzzer_group") { 134*61c4878aSAndroid Build Coastguard Worker _with_fuzzers = pw_toolchain_FUZZING_ENABLED && pw_toolchain_SANITIZERS != [] 135*61c4878aSAndroid Build Coastguard Worker pw_test_group(target_name) { 136*61c4878aSAndroid Build Coastguard Worker forward_variables_from(invoker, 137*61c4878aSAndroid Build Coastguard Worker "*", 138*61c4878aSAndroid Build Coastguard Worker [ 139*61c4878aSAndroid Build Coastguard Worker "fuzzers", 140*61c4878aSAndroid Build Coastguard Worker "tests", 141*61c4878aSAndroid Build Coastguard Worker ]) 142*61c4878aSAndroid Build Coastguard Worker tests = [] 143*61c4878aSAndroid Build Coastguard Worker foreach(fuzzer, invoker.fuzzers) { 144*61c4878aSAndroid Build Coastguard Worker if (_with_fuzzers) { 145*61c4878aSAndroid Build Coastguard Worker tests += [ fuzzer ] 146*61c4878aSAndroid Build Coastguard Worker } 147*61c4878aSAndroid Build Coastguard Worker tests += [ fuzzer + "_test" ] 148*61c4878aSAndroid Build Coastguard Worker } 149*61c4878aSAndroid Build Coastguard Worker } 150*61c4878aSAndroid Build Coastguard Worker} 151