diff options
author | Aaron Green <aarongreen@google.com> | 2023-03-15 23:01:19 +0000 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-15 23:01:19 +0000 |
commit | 487275b46a496f3f5976348e36d56fb4c4e7d81f (patch) | |
tree | 472395ae2e7632c52d19eed4dd03276ab73019a3 | |
parent | 11436fd01d7622c539ce2a8deecc9039caf8b390 (diff) | |
download | pigweed-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.gn | 8 | ||||
-rw-r--r-- | pw_bluetooth_hci/BUILD.gn | 6 | ||||
-rw-r--r-- | pw_fuzzer/BUILD.gn | 6 | ||||
-rw-r--r-- | pw_fuzzer/docs.rst | 56 | ||||
-rw-r--r-- | pw_fuzzer/fuzzer.gni | 79 | ||||
-rw-r--r-- | pw_protobuf/BUILD.gn | 11 | ||||
-rw-r--r-- | pw_random/BUILD.gn | 6 | ||||
-rw-r--r-- | pw_tokenizer/BUILD.gn | 11 |
8 files changed, 108 insertions, 75 deletions
@@ -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", |