1 #!/usr/bin/env python 2 # 3 # Copyright (C) 2017 The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the 'License'); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an 'AS IS' BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 # 17 18 import logging 19 import os 20 21 from vts.runners.host import keys 22 from vts.runners.host import test_runner 23 from vts.utils.python.controllers import adb 24 from vts.utils.python.controllers import android_device 25 from vts.utils.python.common import vts_spec_utils 26 27 from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_config as config 28 from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test 29 from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_case 30 31 32 class FuncFuzzerTest(libfuzzer_test.LibFuzzerTest): 33 """Runs function fuzzer tests on target. 34 35 Attributes: 36 _dut: AndroidDevice, the device under test as config. 37 _test_cases: LibFuzzerTestCase list, list of test cases to run. 38 _vts_spec_parser: VtsSpecParser, used to parse .vts files. 39 """ 40 41 def setUpClass(self): 42 """Creates a remote shell instance, and copies data files.""" 43 required_params = [ 44 keys.ConfigKeys.IKEY_DATA_FILE_PATH, 45 keys.ConfigKeys.IKEY_HAL_HIDL_PACKAGE_NAME, 46 ] 47 self.getUserParams(required_params) 48 logging.info('%s: %s', keys.ConfigKeys.IKEY_DATA_FILE_PATH, 49 self.data_file_path) 50 logging.info('%s: %s', keys.ConfigKeys.IKEY_HAL_HIDL_PACKAGE_NAME, 51 self.hal_hidl_package_name) 52 53 self._dut = self.registerController(android_device, False)[0] 54 self._dut.adb.shell('mkdir %s -p' % config.FUZZER_TEST_DIR) 55 self._vts_spec_parser = vts_spec_utils.VtsSpecParser( 56 self.data_file_path) 57 58 def _RegisteredInterfaces(self, hal_package): 59 """Returns a list of registered interfaces for a given hal package. 60 61 Args: 62 hal_package: string, name of hal package, 63 e.g. android.hardware.nfc (at] 1.0 64 65 Returns: 66 list of string, list of interfaces from this package that are 67 registered on device under test. 68 """ 69 # TODO: find a more robust way to query registered interfaces. 70 cmd = '"lshal | grep -v \* | grep -o %s::[[:alpha:]]* | sort -u"' % hal_package 71 out = str(self._dut.adb.shell(cmd)).split() 72 interfaces = map(lambda x: x.split('::')[-1], out) 73 return interfaces 74 75 def _FuzzerBinHostPath(self, hal_package, vts_spec_name): 76 """Returns path to fuzzer binary on host.""" 77 vts_spec_name = vts_spec_name.replace('.vts', '') 78 bin_name = hal_package + '-vts.func_fuzzer.' + vts_spec_name 79 bin_host_path = os.path.join(self.data_file_path, 'DATA', 'bin', 80 bin_name) 81 return str(bin_host_path) 82 83 def _CreateTestCasesFromSpec(self, hal_package, vts_spec_name, 84 vts_spec_proto): 85 """Creates LibFuzzerTestCases. 86 87 Args: 88 hal_package: string, name of hal package, 89 e.g. android.hardware.nfc (at] 1.0 90 vts_spec_name: string, e.g. 'Nfc.vts'. 91 92 Returns: 93 LibFuzzerTestCase list, one per function of interface corresponding 94 to vts_spec_name. 95 """ 96 test_cases = [] 97 for api in vts_spec_proto.interface.api: 98 additional_params = {'vts_target_func': api.name} 99 libfuzzer_params = config.FUZZER_DEFAULT_PARAMS 100 bin_host_path = self._FuzzerBinHostPath(hal_package, vts_spec_name) 101 test_case = libfuzzer_test_case.LibFuzzerTestCase( 102 bin_host_path, libfuzzer_params, additional_params) 103 test_case.test_name = api.name 104 test_cases.append(test_case) 105 return test_cases 106 107 # Override 108 def CreateTestCases(self): 109 """See base class.""" 110 hal_package = self.hal_hidl_package_name 111 hal_name, hal_version = vts_spec_utils.HalPackageToNameAndVersion( 112 hal_package) 113 vts_spec_names = self._vts_spec_parser.VtsSpecNames(hal_name, 114 hal_version) 115 116 registered_interfaces = self._RegisteredInterfaces( 117 self.hal_hidl_package_name) 118 test_cases = [] 119 for vts_spec_name in vts_spec_names: 120 vts_spec_proto = self._vts_spec_parser.VtsSpecProto( 121 hal_name, hal_version, vts_spec_name) 122 if not vts_spec_proto.component_name in registered_interfaces: 123 continue 124 test_cases += self._CreateTestCasesFromSpec( 125 hal_package, vts_spec_name, vts_spec_proto) 126 return test_cases 127 128 129 if __name__ == '__main__': 130 test_runner.main() 131