| # 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/coverage/coverage.gni") | 
 | 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. | 
 | # - seed_corpus_deps - dependencies for generating the seed corpus. | 
 | # - skip_owners - if true, skips writing the owners file. | 
 | # | 
 | # 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") { | 
 |   assert(!(is_mac && use_clang_coverage && use_fuzzing_engine), | 
 |          "Code Coverage for fuzz targets does not work on Mac until " + | 
 |              "crbug.com/790747 is resolved.") | 
 |  | 
 |   if (!disable_libfuzzer && (use_fuzzing_engine || 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" | 
 |  | 
 |       seed_corpus_deps = [] | 
 |  | 
 |       if (defined(invoker.seed_corpus_deps)) { | 
 |         seed_corpus_deps += invoker.seed_corpus_deps | 
 |       } | 
 |  | 
 |       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" ] + seed_corpus_deps | 
 |       } | 
 |  | 
 |       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_file_name = target_name + ".options" | 
 |       action(config_file_name) { | 
 |         script = "//testing/libfuzzer/gen_fuzzer_config.py" | 
 |         args = [ | 
 |           "--config", | 
 |           rebase_path("$root_build_dir/" + config_file_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_file_name", | 
 |         ] | 
 |       } | 
 |       test_deps += [ ":" + config_file_name ] | 
 |     } | 
 |  | 
 |     # Generate .owners file (if skip_owners is not true). | 
 |     owners_file_name = target_name + ".owners" | 
 |     action(owners_file_name) { | 
 |       script = "//testing/libfuzzer/gen_fuzzer_owners.py" | 
 |       args = [ | 
 |         "--owners", | 
 |         rebase_path("$root_build_dir/" + owners_file_name, root_build_dir), | 
 |       ] | 
 |  | 
 |       if (defined(invoker.sources) && invoker.sources != []) { | 
 |         args += [ "--sources" ] + rebase_path(invoker.sources, root_build_dir) | 
 |       } else if (defined(invoker.deps) && invoker.deps != []) { | 
 |         args += [ | 
 |                   "--build-dir", | 
 |                   rebase_path("$root_build_dir/", root_build_dir), | 
 |                   "--deps", | 
 |                 ] + invoker.deps | 
 |       } | 
 |  | 
 |       outputs = [ | 
 |         "$root_build_dir/$owners_file_name", | 
 |       ] | 
 |     } | 
 |     test_deps += [ ":" + owners_file_name ] | 
 |  | 
 |     test(target_name) { | 
 |       forward_variables_from(invoker, | 
 |                              [ | 
 |                                "cflags", | 
 |                                "cflags_cc", | 
 |                                "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 | 
 |       } | 
 |  | 
 |       if (is_mac) { | 
 |         sources += [ "//testing/libfuzzer/libfuzzer_exports.h" ] | 
 |       } | 
 |     } | 
 |   } else { | 
 |     # noop on unsupported platforms. | 
 |     # mark attributes as used. | 
 |     not_needed(invoker, "*") | 
 |  | 
 |     group(target_name) { | 
 |     } | 
 |   } | 
 | } |