| # Copyright 2015 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| # Defines fuzzer_test. |
| # |
| import("//build/config/features.gni") |
| import("//build/config/sanitizers/sanitizers.gni") |
| import("//testing/test.gni") |
| |
| # fuzzer_test is used to define individual libfuzzer tests. |
| # |
| # Supported attributes: |
| # - (required) sources - fuzzer test source files |
| # - deps - test dependencies |
| # - additional_configs - additional configs to be used for compilation |
| # - dict - a dictionary file for the fuzzer. |
| # - libfuzzer_options - options for the fuzzer (e.g. -max_len or -timeout). |
| # - seed_corpus - a directory with seed corpus. |
| # |
| # If use_libfuzzer gn flag is defined, then proper fuzzer would be build. |
| # Without use_libfuzzer or use_afl a unit-test style binary would be built on |
| # linux and the whole target is a no-op otherwise. |
| # |
| # The template wraps test() target with appropriate dependencies. |
| # If any test run-time options are present (dict or libfuzzer_options), then a |
| # config (.options file) file would be generated or modified in root output |
| # dir (next to test). |
| template("fuzzer_test") { |
| if (!disable_libfuzzer && |
| (use_libfuzzer || use_afl || use_drfuzz || is_linux)) { |
| assert(defined(invoker.sources), "Need sources in $target_name.") |
| |
| test_deps = [ "//testing/libfuzzer:libfuzzer_main" ] |
| |
| if (defined(invoker.deps)) { |
| test_deps += invoker.deps |
| } |
| |
| if (defined(invoker.seed_corpus) || defined(invoker.seed_corpuses)) { |
| assert(!(defined(invoker.seed_corpus) && defined(invoker.seed_corpuses)), |
| "Do not use both seed_corpus and seed_corpuses for $target_name.") |
| |
| out = "$root_build_dir/$target_name" + "_seed_corpus.zip" |
| |
| action(target_name + "_seed_corpus") { |
| script = "//testing/libfuzzer/archive_corpus.py" |
| |
| args = [ |
| "--output", |
| rebase_path(out, root_build_dir), |
| ] |
| |
| if (defined(invoker.seed_corpus)) { |
| args += [ rebase_path(invoker.seed_corpus, root_build_dir) ] |
| } |
| |
| if (defined(invoker.seed_corpuses)) { |
| foreach(seed_corpus_path, invoker.seed_corpuses) { |
| args += [ rebase_path(seed_corpus_path, root_build_dir) ] |
| } |
| } |
| |
| outputs = [ |
| out, |
| ] |
| |
| deps = [ |
| "//testing/libfuzzer:seed_corpus", |
| ] |
| } |
| |
| test_deps += [ ":" + target_name + "_seed_corpus" ] |
| } |
| |
| if (defined(invoker.dict) || defined(invoker.libfuzzer_options)) { |
| if (defined(invoker.dict)) { |
| # Copy dictionary to output. |
| copy(target_name + "_dict_copy") { |
| sources = [ |
| invoker.dict, |
| ] |
| outputs = [ |
| "$root_build_dir/" + target_name + ".dict", |
| ] |
| } |
| test_deps += [ ":" + target_name + "_dict_copy" ] |
| } |
| |
| # Generate .options file. |
| config_name = target_name + ".options" |
| action(config_name) { |
| script = "//testing/libfuzzer/gen_fuzzer_config.py" |
| args = [ |
| "--config", |
| rebase_path("$root_build_dir/" + config_name, root_build_dir), |
| ] |
| |
| if (defined(invoker.dict)) { |
| args += [ |
| "--dict", |
| rebase_path("$root_build_dir/" + invoker.target_name + ".dict", |
| root_build_dir), |
| ] |
| } |
| |
| if (defined(invoker.libfuzzer_options)) { |
| args += [ "--libfuzzer_options" ] |
| args += invoker.libfuzzer_options |
| } |
| |
| outputs = [ |
| "$root_build_dir/$config_name", |
| ] |
| } |
| test_deps += [ ":" + config_name ] |
| } |
| |
| test(target_name) { |
| forward_variables_from(invoker, |
| [ |
| "check_includes", |
| "defines", |
| "include_dirs", |
| "sources", |
| ]) |
| deps = test_deps |
| |
| if (defined(invoker.additional_configs)) { |
| configs += invoker.additional_configs |
| } |
| configs += [ "//testing/libfuzzer:fuzzer_test_config" ] |
| |
| # Used by WebRTC to suppress some Clang warnings in their codebase. |
| if (defined(invoker.suppressed_configs)) { |
| configs -= invoker.suppressed_configs |
| } |
| } |
| } else { |
| # noop on unsupported platforms. |
| # mark attributes as used. |
| assert(invoker.sources == [] || invoker.sources != []) |
| if (defined(invoker.additional_configs)) { |
| assert( |
| invoker.additional_configs == [] || invoker.additional_configs != []) |
| } |
| if (defined(invoker.deps)) { |
| assert(invoker.deps == [] || invoker.deps != []) |
| } |
| if (defined(invoker.dict)) { |
| assert(invoker.dict == [] || invoker.dict != []) |
| } |
| if (defined(invoker.libfuzzer_options)) { |
| assert(invoker.libfuzzer_options == [] || invoker.libfuzzer_options != []) |
| } |
| if (defined(invoker.seed_corpus)) { |
| assert(invoker.seed_corpus == [] || invoker.seed_corpus != []) |
| } |
| if (defined(invoker.seed_corpuses)) { |
| assert(invoker.seed_corpuses == [] || invoker.seed_corpuses != []) |
| } |
| assert(!defined(invoker.check_includes) || invoker.check_includes != []) |
| assert(!defined(invoker.include_dirs) || invoker.include_dirs != []) |
| assert(!defined(invoker.defines) || invoker.defines != []) |
| |
| group(target_name) { |
| } |
| } |
| } |