aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Green <aarongreen@google.com>2023-03-15 23:01:19 +0000
committerCQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-15 23:01:19 +0000
commit487275b46a496f3f5976348e36d56fb4c4e7d81f (patch)
tree472395ae2e7632c52d19eed4dd03276ab73019a3
parent11436fd01d7622c539ce2a8deecc9039caf8b390 (diff)
downloadpigweed-487275b46a496f3f5976348e36d56fb4c4e7d81f.tar.gz
pw_fuzzer: Separate fuzzers from unit tests
This CL disentangles fuzzers from unit tests. It makes the generated unit tests an explicitly named "${target_name}_test" target, and extracts the actual fuzzers into their own "fuzzers" groups for each relevant module. This allows the top-level "fuzzers" group to much more simply redirect to the `host_clang_fuzz` toolchain. This allows `ninja -C out fuzzers` to behave as expected and only build the fuzzers. Change-Id: I71fe4885ca1ecd0c1ca9af554ceb34dd01dbb97b Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/131451 Commit-Queue: Aaron Green <aarongreen@google.com> Reviewed-by: Wyatt Hepler <hepler@google.com>
-rw-r--r--BUILD.gn8
-rw-r--r--pw_bluetooth_hci/BUILD.gn6
-rw-r--r--pw_fuzzer/BUILD.gn6
-rw-r--r--pw_fuzzer/docs.rst56
-rw-r--r--pw_fuzzer/fuzzer.gni79
-rw-r--r--pw_protobuf/BUILD.gn11
-rw-r--r--pw_random/BUILD.gn6
-rw-r--r--pw_tokenizer/BUILD.gn11
8 files changed, 108 insertions, 75 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 409ec66d6..6a13b3b1e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -289,7 +289,13 @@ group("integration_tests") {
group("fuzzers") {
# Fuzzing is only supported on Linux and MacOS using clang.
if (host_os != "win") {
- deps = [ ":pw_module_tests($dir_pigweed/targets/host:host_clang_fuzz)" ]
+ deps = [
+ "$dir_pw_bluetooth_hci:fuzzers($dir_pigweed/targets/host:host_clang_fuzz)",
+ "$dir_pw_fuzzer:fuzzers($dir_pigweed/targets/host:host_clang_fuzz)",
+ "$dir_pw_protobuf:fuzzers($dir_pigweed/targets/host:host_clang_fuzz)",
+ "$dir_pw_random:fuzzers($dir_pigweed/targets/host:host_clang_fuzz)",
+ "$dir_pw_tokenizer:fuzzers($dir_pigweed/targets/host:host_clang_fuzz)",
+ ]
}
}
diff --git a/pw_bluetooth_hci/BUILD.gn b/pw_bluetooth_hci/BUILD.gn
index e4082fe63..0f5107163 100644
--- a/pw_bluetooth_hci/BUILD.gn
+++ b/pw_bluetooth_hci/BUILD.gn
@@ -63,10 +63,14 @@ pw_test_group("tests") {
tests = [
":packet_test",
":uart_transport_test",
- ":uart_transport_fuzzer",
+ ":uart_transport_fuzzer_test",
]
}
+group("fuzzers") {
+ deps = [ ":uart_transport_fuzzer" ]
+}
+
pw_test("packet_test") {
sources = [ "packet_test.cc" ]
deps = [
diff --git a/pw_fuzzer/BUILD.gn b/pw_fuzzer/BUILD.gn
index 2c8c19512..0c47c0fe9 100644
--- a/pw_fuzzer/BUILD.gn
+++ b/pw_fuzzer/BUILD.gn
@@ -95,5 +95,9 @@ pw_fuzzer("toy_fuzzer") {
}
pw_test_group("tests") {
- tests = [ ":toy_fuzzer" ]
+ tests = [ ":toy_fuzzer_test" ]
+}
+
+group("fuzzers") {
+ deps = [ ":toy_fuzzer" ]
}
diff --git a/pw_fuzzer/docs.rst b/pw_fuzzer/docs.rst
index d40e1b53b..db456c021 100644
--- a/pw_fuzzer/docs.rst
+++ b/pw_fuzzer/docs.rst
@@ -68,8 +68,7 @@ Building fuzzers with GN
To build a fuzzer, do the following:
-1. Add the GN target using ``pw_fuzzer`` GN template, and add it to your the
- test group of the module:
+1. Add the GN target to the module using ``pw_fuzzer`` GN template.
.. code::
@@ -81,37 +80,60 @@ To build a fuzzer, do the following:
deps = [ ":my_lib" ]
}
+2. Add the generated unit test to the module's test group. This helps verify the
+ fuzzer can build and run, even when not being built in a fuzzing toolchain.
+
+.. code::
+
+ # In $dir_my_module/BUILD.gn
pw_test_group("tests") {
tests = [
- ":existing_tests", ...
- ":my_fuzzer", # <- Added!
+ ...
+ ":my_fuzzer_test",
]
}
-2. Select your choice of sanitizers ("address" is also the current default).
- See LLVM for `valid options`_.
-
-.. code:: sh
-
- $ gn gen out --args='pw_toolchain_SANITIZERS=["address"]'
-
-3. Build using a fuzzer toolchain. Fuzzer toolchains are those with
+3. If your module does not already have a group of fuzzers, add it and include
+ it in the top level fuzzers target. Depending on your project, the specific
+ toolchain may differ. Fuzzer toolchains are those with
``pw_toolchain_FUZZING_ENABLED`` set to true. Examples include
``host_clang_fuzz`` and any toolchains that extend it.
-.. code:: sh
+.. code::
- $ ninja -C out '//my_module:tests(host_clang_fuzz)'
+ # In //BUILD.gn
+ group("fuzzers") {
+ deps = [
+ ...
+ "$dir_my_module:fuzzers($dir_pigweed/targets/host:host_clang_fuzz)",
+ ]
+ }
-4. To build all fuzzers, add a top-level fuzzers target. For example, the
- following could be built using `ninja -C out fuzzers`:
+4. Add your fuzzer to the module's group of fuzzers.
.. code::
group("fuzzers") {
- deps = [ ":tests($dir_pigweed/targets/host:host_clang_fuzz)" ]
+ deps = [
+ ...
+ ":my_fuzzer",
+ ]
}
+5. If desired, select a sanitizer runtime. By default,
+ `//targets/host:host_clang_fuzz` uses "address" if no sanitizer is specified.
+ See LLVM for `valid options`_.
+
+.. code:: sh
+
+ $ gn gen out --args='pw_toolchain_SANITIZERS=["address"]'
+
+6. Build the fuzzers!
+
+.. code:: sh
+
+ $ ninja -C out fuzzers
+
.. _bazel:
Building and running fuzzers with Bazel
diff --git a/pw_fuzzer/fuzzer.gni b/pw_fuzzer/fuzzer.gni
index 128a55a99..bf47e8695 100644
--- a/pw_fuzzer/fuzzer.gni
+++ b/pw_fuzzer/fuzzer.gni
@@ -14,10 +14,11 @@
import("//build_overrides/pigweed.gni")
+import("$dir_pw_build/error.gni")
import("$dir_pw_toolchain/host_clang/toolchains.gni")
import("$dir_pw_unit_test/test.gni")
-# Creates a libFuzzer-based fuzzer executable target.
+# Creates a libFuzzer-based fuzzer executable target and unit test
#
# This will link `sources` and `deps` with the libFuzzer compiler runtime. The
# `sources` and `deps` should include a definition of the standard LLVM fuzz
@@ -25,62 +26,40 @@ import("$dir_pw_unit_test/test.gni")
# //pw_fuzzer/docs.rst
# https://llvm.org/docs/LibFuzzer.html
#
+# Additionally, this creates a unit test that does not generate fuzzer inputs
+# and simply executes the fuzz target function with fixed inputs. This is useful
+# for verifying the fuzz target function compiles, links, and runs even when not
+# using a fuzzing-capable host or toolchain.
+#
template("pw_fuzzer") {
- if (pw_toolchain_FUZZING_ENABLED && pw_toolchain_SANITIZERS != []) {
- # Build the actual fuzzer using the fuzzing config.
- pw_executable(target_name) {
- forward_variables_from(invoker, "*", [ "visibility" ])
- forward_variables_from(invoker, [ "visibility" ])
-
- if (!defined(deps)) {
- deps = []
- }
- deps += [ dir_pw_fuzzer ]
-
- if (!defined(configs)) {
- configs = []
- }
- configs += [ "$dir_pw_fuzzer:engine" ]
-
- _fuzzer_output_dir = "${target_out_dir}/bin"
- if (defined(invoker.output_dir)) {
- _fuzzer_output_dir = invoker.output_dir
- }
- output_dir = _fuzzer_output_dir
-
- # Metadata for this fuzzer when used as part of a pw_test_group target.
- metadata = {
- tests = [
- {
- type = "fuzzer"
- test_name = target_name
- test_directory = rebase_path(output_dir, root_build_dir)
- },
- ]
- }
+ if (!pw_toolchain_FUZZING_ENABLED) {
+ pw_error(target_name) {
+ message_lines = [ "Toolchain does not enable fuzzing." ]
}
-
- # No-op target to satisfy `pw_test_group`. It is empty as we don't want to
- # automatically run fuzzers.
- group(target_name + ".run") {
- }
-
- # No-op target to satisfy `pw_test`. It is empty as we don't need a separate
- # lib target.
- group(target_name + ".lib") {
+ not_needed(invoker, "*")
+ } else if (pw_toolchain_SANITIZERS == []) {
+ pw_error(target_name) {
+ message_lines = [ "No sanitizer runtime set." ]
}
+ not_needed(invoker, "*")
} else {
- # Build a unit test that exercise the fuzz target function.
- pw_test(target_name) {
- # TODO(b/234891784): Re-enable when there's better configurability for
- # on-device fuzz testing.
- enable_if = false
- sources = []
+ pw_executable(target_name) {
+ configs = []
deps = []
forward_variables_from(invoker, "*", [ "visibility" ])
forward_variables_from(invoker, [ "visibility" ])
- sources += [ "$dir_pw_fuzzer/pw_fuzzer_disabled.cc" ]
- deps += [ "$dir_pw_fuzzer:run_as_unit_test" ]
+ configs += [ "$dir_pw_fuzzer:engine" ]
+ deps += [ dir_pw_fuzzer ]
}
}
+
+ pw_test("${target_name}_test") {
+ # TODO(b/234891784): Re-enable when there's better configurability for
+ # on-device fuzz testing.
+ enable_if = false
+ deps = []
+ forward_variables_from(invoker, "*", [ "visibility" ])
+ forward_variables_from(invoker, [ "visibility" ])
+ deps += [ "$dir_pw_fuzzer:run_as_unit_test" ]
+ }
}
diff --git a/pw_protobuf/BUILD.gn b/pw_protobuf/BUILD.gn
index 8c21beb6a..267b999eb 100644
--- a/pw_protobuf/BUILD.gn
+++ b/pw_protobuf/BUILD.gn
@@ -120,8 +120,8 @@ pw_test_group("tests") {
":codegen_message_test",
":decoder_test",
":encoder_test",
- ":encoder_fuzzer",
- ":decoder_fuzzer",
+ ":encoder_fuzzer_test",
+ ":decoder_fuzzer_test",
":find_test",
":map_utils_test",
":message_test",
@@ -131,6 +131,13 @@ pw_test_group("tests") {
]
}
+group("fuzzers") {
+ deps = [
+ ":decoder_fuzzer",
+ ":encoder_fuzzer",
+ ]
+}
+
pw_test("decoder_test") {
deps = [ ":pw_protobuf" ]
sources = [ "decoder_test.cc" ]
diff --git a/pw_random/BUILD.gn b/pw_random/BUILD.gn
index 4b2a5c44a..0563fc2e2 100644
--- a/pw_random/BUILD.gn
+++ b/pw_random/BUILD.gn
@@ -48,10 +48,14 @@ pw_source_set("fuzzer_generator") {
pw_test_group("tests") {
tests = [
":xor_shift_star_test",
- ":get_int_bounded_fuzzer",
+ ":get_int_bounded_fuzzer_test",
]
}
+group("fuzzers") {
+ deps = [ ":get_int_bounded_fuzzer" ]
+}
+
pw_test("xor_shift_star_test") {
deps = [
":pw_random",
diff --git a/pw_tokenizer/BUILD.gn b/pw_tokenizer/BUILD.gn
index 636be474f..d114ed293 100644
--- a/pw_tokenizer/BUILD.gn
+++ b/pw_tokenizer/BUILD.gn
@@ -172,18 +172,25 @@ pw_test_group("tests") {
":argument_types_test",
":base64_test",
":decode_test",
- ":detokenize_fuzzer",
+ ":detokenize_fuzzer_test",
":detokenize_test",
":encode_args_test",
":hash_test",
":simple_tokenize_test",
- ":token_database_fuzzer",
+ ":token_database_fuzzer_test",
":token_database_test",
":tokenize_test",
]
group_deps = [ "$dir_pw_preprocessor:tests" ]
}
+group("fuzzers") {
+ deps = [
+ ":detokenize_fuzzer",
+ ":token_database_fuzzer",
+ ]
+}
+
pw_test("argument_types_test") {
sources = [
"argument_types_test.cc",