OLD | NEW |
1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 # Defines fuzzer_test. | 5 # Defines fuzzer_test. |
6 # | 6 # |
7 import("//build/config/features.gni") | 7 import("//build/config/features.gni") |
8 import("//build/config/sanitizers/sanitizers.gni") | 8 import("//build/config/sanitizers/sanitizers.gni") |
9 import("//testing/test.gni") | 9 import("//testing/test.gni") |
10 | 10 |
11 # visible for testing only. | |
12 template("fuzzer_test_launcher") { | |
13 assert(defined(invoker.fuzzer_name), "need fuzzer_name in $target_name.") | |
14 assert(defined(invoker.dict), "need dict in $target_name.") | |
15 | |
16 generated_script = "$root_build_dir/$target_name" | |
17 | |
18 action(target_name) { | |
19 script = "//testing/libfuzzer/gen_fuzzer_runner.py" | |
20 args = [ | |
21 "--fuzzer", | |
22 invoker.fuzzer_name, | |
23 "--launcher", | |
24 rebase_path(generated_script, root_build_dir), | |
25 "--dict", | |
26 rebase_path("$root_build_dir/" + invoker.dict, root_build_dir), | |
27 ] | |
28 outputs = [ | |
29 generated_script, | |
30 ] | |
31 } | |
32 } | |
33 | |
34 # fuzzer_test is used to define individual libfuzzer tests. | 11 # fuzzer_test is used to define individual libfuzzer tests. |
35 # | 12 # |
36 # Supported attributes: | 13 # Supported attributes: |
37 # - (required) sources - fuzzer test source files | 14 # - (required) sources - fuzzer test source files |
38 # - data - test data files. | |
39 # - deps - test dependencies | 15 # - deps - test dependencies |
40 # - additional_configs - additional configs to be used for compilation | 16 # - additional_configs - additional configs to be used for compilation |
41 # - dict - a dictionary file for the fuzzer. | 17 # - dict - a dictionary file for the fuzzer. |
| 18 # - libfuzzer_options - options for the fuzzer (e.g. -max_len or -timeout). |
42 # | 19 # |
43 # If use_libfuzzer gn flag is defined, then proper fuzzer would be build. | 20 # If use_libfuzzer gn flag is defined, then proper fuzzer would be build. |
44 # Without use_libfuzzer a unit-test style binary would be built on linux | 21 # Without use_libfuzzer a unit-test style binary would be built on linux |
45 # and the whole target is a no-op otherwise. | 22 # and the whole target is a no-op otherwise. |
46 # | 23 # |
47 # The template wraps test() target with appropriate dependencies. | 24 # The template wraps test() target with appropriate dependencies. |
48 # If any test run-time options are present (dict), then a launcher | 25 # If any test run-time options are present (dict or libfuzzer_options), then a |
49 # file would be generated with <fuzzer_name>.sh name in root output | 26 # config (.options file) file would be generated or modified in root output |
50 # dir (next to test). | 27 # dir (next to test). |
51 template("fuzzer_test") { | 28 template("fuzzer_test") { |
52 if (!disable_libfuzzer && (use_libfuzzer || use_drfuzz || is_linux)) { | 29 if (!disable_libfuzzer && (use_libfuzzer || use_drfuzz || is_linux)) { |
53 assert(defined(invoker.sources), "Need sources in $target_name.") | 30 assert(defined(invoker.sources), "Need sources in $target_name.") |
54 | 31 |
55 test_deps = [ "//testing/libfuzzer:libfuzzer_main" ] | 32 test_deps = [ "//testing/libfuzzer:libfuzzer_main" ] |
56 | 33 |
57 if (defined(invoker.deps)) { | 34 if (defined(invoker.deps)) { |
58 test_deps += invoker.deps | 35 test_deps += invoker.deps |
59 } | 36 } |
60 | 37 |
61 test_data = [] | 38 if (defined(invoker.libfuzzer_options) && !defined(invoker.dict)) { |
62 if (defined(invoker.data)) { | 39 # Copy libfuzzer_options to output if dict is not provided. |
63 test_data += invoker.data | 40 copy(target_name + "_libfuzzer_options_copy") { |
| 41 sources = [ |
| 42 invoker.libfuzzer_options, |
| 43 ] |
| 44 outputs = [ |
| 45 "$root_build_dir/" + target_name + ".options", |
| 46 ] |
| 47 } |
| 48 |
| 49 test_deps += [ ":" + target_name + "_libfuzzer_options_copy" ] |
64 } | 50 } |
65 | 51 |
66 if (defined(invoker.dict)) { | 52 if (defined(invoker.dict)) { |
67 fuzzer_name = target_name | 53 # Copy dictionary to output. |
68 launcher_name = target_name + ".sh" | |
69 | |
70 # Copy dictionary to output | |
71 copy(target_name + "_dict_copy") { | 54 copy(target_name + "_dict_copy") { |
72 sources = [ | 55 sources = [ |
73 invoker.dict, | 56 invoker.dict, |
74 ] | 57 ] |
75 outputs = [ | 58 outputs = [ |
76 "$root_build_dir/" + invoker.dict, | 59 "$root_build_dir/" + target_name + ".dict", |
77 ] | 60 ] |
78 } | 61 } |
79 | 62 |
80 fuzzer_test_launcher(launcher_name) { | 63 test_deps += [ ":" + target_name + "_dict_copy" ] |
81 dict = invoker.dict | 64 |
| 65 # Generate new .options file or update an existing one. |
| 66 config_name = target_name + ".options" |
| 67 action(config_name) { |
| 68 script = "//testing/libfuzzer/gen_fuzzer_config.py" |
| 69 args = [ |
| 70 "--config", |
| 71 rebase_path("$root_build_dir/" + config_name), |
| 72 "--dict", |
| 73 rebase_path("$root_build_dir/" + invoker.target_name + ".dict"), |
| 74 ] |
| 75 |
| 76 if (defined(invoker.libfuzzer_options)) { |
| 77 args += [ |
| 78 "--libfuzzer_options", |
| 79 rebase_path(invoker.libfuzzer_options), |
| 80 ] |
| 81 } |
| 82 outputs = [ |
| 83 "$root_build_dir/$config_name", |
| 84 ] |
82 } | 85 } |
83 | 86 test_deps += [ ":" + config_name ] |
84 test_deps += [ | |
85 ":$launcher_name", | |
86 ":" + fuzzer_name + "_dict_copy", | |
87 ] | |
88 test_data += [ | |
89 invoker.dict, | |
90 ":$launcher_name", | |
91 ] | |
92 } | 87 } |
93 | 88 |
94 test(target_name) { | 89 test(target_name) { |
95 forward_variables_from(invoker, | 90 forward_variables_from(invoker, |
96 [ | 91 [ |
97 "sources", | 92 "sources", |
98 "include_dirs", | 93 "include_dirs", |
99 ]) | 94 ]) |
100 deps = test_deps | 95 deps = test_deps |
101 data = test_data | |
102 | 96 |
103 if (defined(invoker.additional_configs)) { | 97 if (defined(invoker.additional_configs)) { |
104 configs += invoker.additional_configs | 98 configs += invoker.additional_configs |
105 } | 99 } |
106 } | 100 } |
107 } else { | 101 } else { |
108 # noop on unsupported platforms. | 102 # noop on unsupported platforms. |
109 # mark attributes as used. | 103 # mark attributes as used. |
110 assert(invoker.sources == [] || invoker.sources != []) | 104 assert(invoker.sources == [] || invoker.sources != []) |
111 if (defined(invoker.additional_configs)) { | 105 if (defined(invoker.additional_configs)) { |
112 assert( | 106 assert( |
113 invoker.additional_configs == [] || invoker.additional_configs != []) | 107 invoker.additional_configs == [] || invoker.additional_configs != []) |
114 } | 108 } |
115 if (defined(invoker.deps)) { | 109 if (defined(invoker.deps)) { |
116 assert(invoker.deps == [] || invoker.deps != []) | 110 assert(invoker.deps == [] || invoker.deps != []) |
117 } | 111 } |
118 if (defined(invoker.dict)) { | 112 if (defined(invoker.dict)) { |
119 assert(invoker.dict == [] || invoker.dict != []) | 113 assert(invoker.dict == [] || invoker.dict != []) |
120 } | 114 } |
| 115 if (defined(invoker.libfuzzer_options)) { |
| 116 assert(invoker.libfuzzer_options == [] || invoker.libfuzzer_options != []) |
| 117 } |
121 | 118 |
122 group(target_name) { | 119 group(target_name) { |
123 } | 120 } |
124 } | 121 } |
125 } | 122 } |
OLD | NEW |