Home | History | Annotate | Download | only in build
      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