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 18import logging 19import os 20import tempfile 21 22from vts.runners.host import keys 23from vts.runners.host import test_runner 24from vts.utils.python.controllers import adb 25from vts.utils.python.controllers import android_device 26from vts.utils.python.common import vts_spec_utils 27from vts.utils.python.fuzzer import corpus_manager 28 29from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_config as config 30from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test 31from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_case 32 33 34class FuncFuzzerTest(libfuzzer_test.LibFuzzerTest): 35 """Runs function fuzzer tests on target. 36 37 Attributes: 38 _dut: AndroidDevice, the device under test as config. 39 _test_cases: LibFuzzerTestCase list, list of test cases to run. 40 _vts_spec_parser: VtsSpecParser, used to parse .vts files. 41 _temp_dir: temporary directory, used as buffer between target and GCS. 42 """ 43 44 def setUpClass(self): 45 """Creates a remote shell instance, and copies data files.""" 46 required_params = [ 47 keys.ConfigKeys.IKEY_DATA_FILE_PATH, 48 keys.ConfigKeys.IKEY_HAL_HIDL_PACKAGE_NAME, 49 ] 50 self.getUserParams(required_params) 51 logging.info('%s: %s', keys.ConfigKeys.IKEY_DATA_FILE_PATH, 52 self.data_file_path) 53 logging.info('%s: %s', keys.ConfigKeys.IKEY_HAL_HIDL_PACKAGE_NAME, 54 self.hal_hidl_package_name) 55 56 self._dut = self.android_devices[0] 57 self._dut.adb.shell('mkdir %s -p' % config.FUZZER_TEST_DIR) 58 self._vts_spec_parser = vts_spec_utils.VtsSpecParser( 59 self.data_file_path) 60 self._temp_dir = tempfile.mkdtemp() 61 self._corpus_manager = corpus_manager.CorpusManager(self.user_params, self._dut) 62 63 def _RegisteredInterfaces(self, hal_package): 64 """Returns a list of registered interfaces for a given hal package. 65 66 Args: 67 hal_package: string, name of hal package, 68 e.g. android.hardware.nfc@1.0 69 70 Returns: 71 list of string, list of interfaces from this package that are 72 registered on device under test. 73 """ 74 # TODO: find a more robust way to query registered interfaces. 75 cmd = '"lshal | grep -v \* | grep -o %s::[[:alpha:]]* | sort -u"' % hal_package 76 out = str(self._dut.adb.shell(cmd)).split() 77 interfaces = map(lambda x: x.split('::')[-1], out) 78 return interfaces 79 80 def _FuzzerBinHostPath(self, hal_package, vts_spec_name): 81 """Returns path to fuzzer binary on host.""" 82 vts_spec_name = vts_spec_name.replace('.vts', '') 83 bin_name = hal_package + '-vts.func_fuzzer.' + vts_spec_name 84 bin_host_path = os.path.join(self.data_file_path, 'DATA', 'bin', 85 bin_name) 86 return str(bin_host_path) 87 88 def _CreateTestCasesFromSpec(self, hal_package, vts_spec_name, 89 vts_spec_proto): 90 """Creates LibFuzzerTestCases. 91 92 Args: 93 hal_package: string, name of hal package, 94 e.g. android.hardware.nfc@1.0 95 vts_spec_name: string, e.g. 'Nfc.vts'. 96 97 Returns: 98 LibFuzzerTestCase list, one per function of interface corresponding 99 to vts_spec_name. 100 """ 101 test_cases = [] 102 for api in vts_spec_proto.interface.api: 103 additional_params = {'vts_target_func': api.name} 104 libfuzzer_params = config.FUZZER_DEFAULT_PARAMS 105 bin_host_path = self._FuzzerBinHostPath(hal_package, vts_spec_name) 106 test_case = libfuzzer_test_case.LibFuzzerTestCase( 107 bin_host_path, libfuzzer_params, additional_params) 108 test_case.test_name = api.name 109 test_cases.append(test_case) 110 return test_cases 111 112 # Override 113 def CreateTestCases(self): 114 """See base class.""" 115 hal_package = self.hal_hidl_package_name 116 hal_name, hal_version = vts_spec_utils.HalPackageToNameAndVersion( 117 hal_package) 118 vts_spec_names = self._vts_spec_parser.VtsSpecNames( 119 hal_name, hal_version) 120 121 registered_interfaces = self._RegisteredInterfaces( 122 self.hal_hidl_package_name) 123 test_cases = [] 124 for vts_spec_name in vts_spec_names: 125 vts_spec_proto = self._vts_spec_parser.VtsSpecProto( 126 hal_name, hal_version, vts_spec_name) 127 if not vts_spec_proto.component_name in registered_interfaces: 128 continue 129 test_cases += self._CreateTestCasesFromSpec( 130 hal_package, vts_spec_name, vts_spec_proto) 131 return test_cases 132 133 134if __name__ == '__main__': 135 test_runner.main() 136