1 # 2 # Copyright (C) 2017 The Android Open Source Project 3 # 4 # Licensed under the Apache License, Version 2.0 (the 'License'); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an 'AS IS' BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 # 16 17 import os 18 import sys 19 20 from importlib import import_module 21 22 23 class FuncFuzzerBuildRuleGen(object): 24 """Build rule generator for test/vts-testcase/fuzz/func_fuzzer. 25 26 Attributes: 27 _android_build_top: string, equal to environment variable ANDROID_BUILD_TOP. 28 _project_path: string, path to test/vts-testcase/fuzz. 29 _func_fuzzer_dir: string, path to test/vts-testcase/fuzz/func_fuzzer. 30 _func_fuzzer_build_template: string, path to fuzzer build template file. 31 _utils: test/vts-testcase/hal/script/build/build_rule_gen_utils module. 32 _vts_spec_parser: tools that generates and parses vts spec with hidl-gen. 33 _warning_header: string, warning header for every generated file. 34 """ 35 36 def __init__(self, warning_header): 37 """BuildRuleGen constructor. 38 39 Args: 40 warning_header: string, warning header for every generated file. 41 """ 42 self._android_build_top = os.environ.get('ANDROID_BUILD_TOP') 43 if not self._android_build_top: 44 print 'Run "lunch" command first.' 45 sys.exit(1) 46 self._project_path = os.path.join(self._android_build_top, 'test', 47 'vts-testcase', 'fuzz') 48 self._func_fuzzer_dir = os.path.join(self._project_path, 'func_fuzzer') 49 self._func_fuzzer_build_template = os.path.join( 50 self._project_path, 'script', 'build', 'template', 51 'func_fuzzer_build_template.bp') 52 self._func_fuzzer_build_defaults = os.path.join( 53 self._project_path, 'script', 'build', 'template', 54 'func_fuzzer_build_defaults.bp') 55 56 sys.path.append( 57 os.path.join(self._android_build_top, 'test', 'vts-testcase', 'hal', 58 'script', 'build')) 59 vts_spec_parser = import_module('vts_spec_parser') 60 self._utils = import_module('build_rule_gen_utils') 61 self._vts_spec_parser = vts_spec_parser.VtsSpecParser() 62 self._warning_header = warning_header 63 64 def UpdateBuildRule(self): 65 """Updates build rules under test/vts-testcase/fuzz/func_fuzzer.""" 66 self._utils.RemoveFilesInDirIf( 67 self._func_fuzzer_dir, 68 lambda x: self._IsAutoGenerated(x)) 69 hal_list = self._vts_spec_parser.HalNamesAndVersions() 70 self.UpdateTopLevelBuildRule() 71 self.UpdateSecondLevelBuildRule(hal_list) 72 self.UpdateHalDirBuildRule(hal_list) 73 74 def UpdateTopLevelBuildRule(self): 75 """Updates test/vts-testcase/fuzz/func_fuzzer/Android.bp""" 76 build_rule = self._warning_header 77 with open(self._func_fuzzer_build_defaults) as build_file: 78 build_rule += str(build_file.read()) 79 80 self._utils.WriteBuildRule( 81 os.path.join(self._func_fuzzer_dir, 'Android.bp'), build_rule) 82 83 def UpdateSecondLevelBuildRule(self, hal_list): 84 """Updates test/vts-testcase/fuzz/func_fuzzer/<hal_name>/Android.bp""" 85 top_level_dirs = dict() 86 for target in hal_list: 87 hal_dir = os.path.join( 88 self._utils.HalNameDir(target[0]), 89 self._utils.HalVerDir(target[1])) 90 top_dir = hal_dir.split('/', 1)[0] 91 top_level_dirs.setdefault( 92 top_dir, []).append(os.path.relpath(hal_dir, top_dir)) 93 94 for k, v in top_level_dirs.items(): 95 file_path = os.path.join(self._func_fuzzer_dir, k, 'Android.bp') 96 self._utils.WriteBuildRule( 97 file_path, 98 self._utils.OnlySubdirsBpRule(self._warning_header, sorted(v))) 99 100 def UpdateHalDirBuildRule(self, hal_list): 101 """Updates build rules for function fuzzers. 102 103 Updates func_fuzzer build rules for each pair of 104 (hal_name, hal_version) in hal_list. 105 106 Args: 107 hal_list: list of tuple of strings. For example, 108 [('vibrator', '1.3'), ('sensors', '1.7')] 109 """ 110 for target in hal_list: 111 hal_name = target[0] 112 hal_version = target[1] 113 114 file_path = os.path.join( 115 self._func_fuzzer_dir, self._utils.HalNameDir(hal_name), 116 self._utils.HalVerDir(hal_version), 'Android.bp') 117 118 self._utils.WriteBuildRule( 119 file_path, self._FuncFuzzerBuildRuleFromTemplate( 120 hal_name, hal_version, self._func_fuzzer_build_template)) 121 122 def _FuncFuzzerBuildRuleFromTemplate(self, hal_name, hal_version, 123 template_path): 124 """Returns build rules in string form by filling out a template. 125 126 Reads template from given path and fills it out. 127 128 Args: 129 template_path: string, path to build rule template file. 130 hal_name: string, name of the hal, e.g. 'vibrator'. 131 hal_version: string, version of the hal, e.g '7.4' 132 133 Returns: 134 string, complete build rules in string form 135 """ 136 with open(template_path) as template_file: 137 build_template = str(template_file.read()) 138 139 vts_spec_names = self._vts_spec_parser.VtsSpecNames(hal_name, 140 hal_version) 141 142 result = self._warning_header 143 for vts_spec in vts_spec_names: 144 hal_iface_name = vts_spec.replace('.vts', '') 145 if not self._IsFuzzable(hal_iface_name): 146 continue 147 result += self._FillOutBuildRuleTemplate( 148 hal_name, hal_version, hal_iface_name, build_template) 149 150 return result 151 152 def _FillOutBuildRuleTemplate(self, hal_name, hal_version, hal_iface_name, 153 template): 154 """Returns build rules in string form by filling out given template. 155 156 Args: 157 hal_name: string, name of the hal, e.g. 'vibrator'. 158 hal_version: string, version of the hal, e.g '7.4' 159 hal_iface_name: string, name of a hal interface, e.g 'Vibrator' 160 template: string, build rule template to fill out. 161 162 Returns: 163 string, complete build rule in string form. 164 """ 165 build_rule = template 166 build_rule = build_rule.replace('{HAL_NAME}', hal_name) 167 build_rule = build_rule.replace('{HAL_NAME_DIR}', 168 self._utils.HalNameDir(hal_name)) 169 build_rule = build_rule.replace('{HAL_VERSION}', hal_version) 170 build_rule = build_rule.replace('{HAL_IFACE_NAME}', hal_iface_name) 171 return build_rule 172 173 def _IsAutoGenerated(self, abs_file_path): 174 """Checks if file was auto-generated. 175 176 Args: 177 abs_file_path: string, absolute file path. 178 179 Returns: 180 True iff file was auto-generated by FuncFuzzerBuildRuleGen. 181 """ 182 with open(abs_file_path) as myfile: 183 header = ''.join([next(myfile) for x in xrange(2)]) 184 return header == self._warning_header 185 186 @staticmethod 187 def _IsFuzzable(component_name): 188 """Checks if component is fuzzable. 189 190 Args: 191 component_name: string, name of component, e.g. 'types, 'Vibrator' 192 193 Returns: 194 True iff can generate a func_fuzzer for component_name. 195 """ 196 if component_name == 'types': 197 return False 198 elif component_name.endswith('Callback'): 199 return False 200 else: 201 return True 202