blob: 266016ce4f9ac539d4beafddfa65bf820899a9e7 [file] [log] [blame]
aizatskycb1a43932015-12-14 20:59:141# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
aizatsky7dfb57342015-12-21 04:02:525# Defines fuzzer_test.
6#
aizatsky43d459a52016-02-13 01:22:187import("//build/config/features.gni")
8import("//build/config/sanitizers/sanitizers.gni")
aizatskycb1a43932015-12-14 20:59:149import("//testing/test.gni")
10
11# fuzzer_test is used to define individual libfuzzer tests.
12#
13# Supported attributes:
14# - (required) sources - fuzzer test source files
aizatskycb1a43932015-12-14 20:59:1415# - deps - test dependencies
16# - additional_configs - additional configs to be used for compilation
17# - dict - a dictionary file for the fuzzer.
mmoroz344a75ae2016-03-02 16:57:1718# - libfuzzer_options - options for the fuzzer (e.g. -max_len or -timeout).
aizatsky198e3022016-03-08 21:33:4619# - seed_corpus - a directory with seed corpus.
aizatskycb1a43932015-12-14 20:59:1420#
aizatsky43d459a52016-02-13 01:22:1821# If use_libfuzzer gn flag is defined, then proper fuzzer would be build.
22# Without use_libfuzzer a unit-test style binary would be built on linux
23# and the whole target is a no-op otherwise.
24#
aizatskycb1a43932015-12-14 20:59:1425# The template wraps test() target with appropriate dependencies.
mmoroz344a75ae2016-03-02 16:57:1726# If any test run-time options are present (dict or libfuzzer_options), then a
27# config (.options file) file would be generated or modified in root output
aizatskycb1a43932015-12-14 20:59:1428# dir (next to test).
29template("fuzzer_test") {
aizatsky43d459a52016-02-13 01:22:1830 if (!disable_libfuzzer && (use_libfuzzer || use_drfuzz || is_linux)) {
31 assert(defined(invoker.sources), "Need sources in $target_name.")
aizatskycb1a43932015-12-14 20:59:1432
aizatsky43d459a52016-02-13 01:22:1833 test_deps = [ "//testing/libfuzzer:libfuzzer_main" ]
aizatskycb1a43932015-12-14 20:59:1434
aizatsky43d459a52016-02-13 01:22:1835 if (defined(invoker.deps)) {
36 test_deps += invoker.deps
37 }
aizatskycb1a43932015-12-14 20:59:1438
mmoroz344a75ae2016-03-02 16:57:1739 if (defined(invoker.libfuzzer_options) && !defined(invoker.dict)) {
40 # Copy libfuzzer_options to output if dict is not provided.
41 copy(target_name + "_libfuzzer_options_copy") {
42 sources = [
43 invoker.libfuzzer_options,
44 ]
45 outputs = [
46 "$root_build_dir/" + target_name + ".options",
47 ]
48 }
49
50 test_deps += [ ":" + target_name + "_libfuzzer_options_copy" ]
aizatsky43d459a52016-02-13 01:22:1851 }
aizatskycb1a43932015-12-14 20:59:1452
aizatsky198e3022016-03-08 21:33:4653 if (defined(invoker.seed_corpus)) {
54 depfile = "$root_build_dir/$target_name" + ".seed_corpus.d"
55 out = "$root_build_dir/$target_name" + "_seed_corpus.zip"
56
57 action(target_name + "_seed_corpus") {
58 script = "//testing/libfuzzer/archive_corpus.py"
59 args = [
60 "--depfile",
61 rebase_path(depfile),
62 "--corpus",
63 rebase_path(invoker.seed_corpus),
64 "--output",
65 rebase_path(out),
66 "--fuzzer",
67 rebase_path("$root_build_dir/$target_name"),
68 ]
69
70 depfile = depfile
71 outputs = [
72 out,
73 ]
aizatsky7951d34f2016-03-11 00:09:4574 deps = [
75 "//testing/libfuzzer:seed_corpus",
76 ]
aizatsky198e3022016-03-08 21:33:4677 }
78
79 test_deps += [ ":" + target_name + "_seed_corpus" ]
80 }
81
aizatsky43d459a52016-02-13 01:22:1882 if (defined(invoker.dict)) {
mmoroz344a75ae2016-03-02 16:57:1783 # Copy dictionary to output.
aizatsky43d459a52016-02-13 01:22:1884 copy(target_name + "_dict_copy") {
85 sources = [
86 invoker.dict,
87 ]
88 outputs = [
mmoroz344a75ae2016-03-02 16:57:1789 "$root_build_dir/" + target_name + ".dict",
aizatsky43d459a52016-02-13 01:22:1890 ]
91 }
92
mmoroz344a75ae2016-03-02 16:57:1793 test_deps += [ ":" + target_name + "_dict_copy" ]
aizatsky43d459a52016-02-13 01:22:1894
mmoroz344a75ae2016-03-02 16:57:1795 # Generate new .options file or update an existing one.
96 config_name = target_name + ".options"
97 action(config_name) {
98 script = "//testing/libfuzzer/gen_fuzzer_config.py"
99 args = [
100 "--config",
101 rebase_path("$root_build_dir/" + config_name),
102 "--dict",
103 rebase_path("$root_build_dir/" + invoker.target_name + ".dict"),
104 ]
105
106 if (defined(invoker.libfuzzer_options)) {
107 args += [
108 "--libfuzzer_options",
109 rebase_path(invoker.libfuzzer_options),
110 ]
111 }
112 outputs = [
113 "$root_build_dir/$config_name",
114 ]
115 }
116 test_deps += [ ":" + config_name ]
aizatskycb1a43932015-12-14 20:59:14117 }
118
aizatsky43d459a52016-02-13 01:22:18119 test(target_name) {
120 forward_variables_from(invoker,
121 [
122 "sources",
123 "include_dirs",
124 ])
125 deps = test_deps
aizatsky43d459a52016-02-13 01:22:18126
127 if (defined(invoker.additional_configs)) {
128 configs += invoker.additional_configs
129 }
aizatskycb1a43932015-12-14 20:59:14130 }
aizatsky43d459a52016-02-13 01:22:18131 } else {
132 # noop on unsupported platforms.
133 # mark attributes as used.
134 assert(invoker.sources == [] || invoker.sources != [])
aizatskycb1a43932015-12-14 20:59:14135 if (defined(invoker.additional_configs)) {
aizatsky43d459a52016-02-13 01:22:18136 assert(
137 invoker.additional_configs == [] || invoker.additional_configs != [])
138 }
139 if (defined(invoker.deps)) {
140 assert(invoker.deps == [] || invoker.deps != [])
141 }
142 if (defined(invoker.dict)) {
143 assert(invoker.dict == [] || invoker.dict != [])
144 }
mmoroz344a75ae2016-03-02 16:57:17145 if (defined(invoker.libfuzzer_options)) {
146 assert(invoker.libfuzzer_options == [] || invoker.libfuzzer_options != [])
147 }
aizatsky198e3022016-03-08 21:33:46148 if (defined(invoker.seed_corpus)) {
149 assert(invoker.seed_corpus == [] || invoker.seed_corpus != [])
150 }
aizatsky43d459a52016-02-13 01:22:18151
152 group(target_name) {
aizatskycb1a43932015-12-14 20:59:14153 }
154 }
155}