#!/usr/bin/env python # # Copyright (C) 2017 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an 'AS IS' BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import logging import os import tempfile from vts.runners.host import keys from vts.runners.host import test_runner from vts.utils.python.controllers import adb from vts.utils.python.controllers import android_device from vts.utils.python.common import vts_spec_utils from vts.utils.python.fuzzer import corpus_manager from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_config as config from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_case class FuncFuzzerTest(libfuzzer_test.LibFuzzerTest): """Runs function fuzzer tests on target. Attributes: _dut: AndroidDevice, the device under test as config. _test_cases: LibFuzzerTestCase list, list of test cases to run. _vts_spec_parser: VtsSpecParser, used to parse .vts files. _temp_dir: temporary directory, used as buffer between target and GCS. """ def setUpClass(self): """Creates a remote shell instance, and copies data files.""" required_params = [ keys.ConfigKeys.IKEY_DATA_FILE_PATH, keys.ConfigKeys.IKEY_HAL_HIDL_PACKAGE_NAME, ] self.getUserParams(required_params) logging.info('%s: %s', keys.ConfigKeys.IKEY_DATA_FILE_PATH, self.data_file_path) logging.info('%s: %s', keys.ConfigKeys.IKEY_HAL_HIDL_PACKAGE_NAME, self.hal_hidl_package_name) self._dut = self.android_devices[0] self._dut.adb.shell('mkdir %s -p' % config.FUZZER_TEST_DIR) self._vts_spec_parser = vts_spec_utils.VtsSpecParser( self.data_file_path) self._temp_dir = tempfile.mkdtemp() self._corpus_manager = corpus_manager.CorpusManager(self.user_params, self._dut) def _RegisteredInterfaces(self, hal_package): """Returns a list of registered interfaces for a given hal package. Args: hal_package: string, name of hal package, e.g. android.hardware.nfc@1.0 Returns: list of string, list of interfaces from this package that are registered on device under test. """ # TODO: find a more robust way to query registered interfaces. cmd = '"lshal | grep -v \* | grep -o %s::[[:alpha:]]* | sort -u"' % hal_package out = str(self._dut.adb.shell(cmd)).split() interfaces = map(lambda x: x.split('::')[-1], out) return interfaces def _FuzzerBinHostPath(self, hal_package, vts_spec_name): """Returns path to fuzzer binary on host.""" vts_spec_name = vts_spec_name.replace('.vts', '') bin_name = hal_package + '-vts.func_fuzzer.' + vts_spec_name bin_host_path = os.path.join(self.data_file_path, 'DATA', 'bin', bin_name) return str(bin_host_path) def _CreateTestCasesFromSpec(self, hal_package, vts_spec_name, vts_spec_proto): """Creates LibFuzzerTestCases. Args: hal_package: string, name of hal package, e.g. android.hardware.nfc@1.0 vts_spec_name: string, e.g. 'Nfc.vts'. Returns: LibFuzzerTestCase list, one per function of interface corresponding to vts_spec_name. """ test_cases = [] for api in vts_spec_proto.interface.api: additional_params = {'vts_target_func': api.name} libfuzzer_params = config.FUZZER_DEFAULT_PARAMS bin_host_path = self._FuzzerBinHostPath(hal_package, vts_spec_name) test_case = libfuzzer_test_case.LibFuzzerTestCase( bin_host_path, libfuzzer_params, additional_params) test_case.test_name = api.name test_cases.append(test_case) return test_cases # Override def CreateTestCases(self): """See base class.""" hal_package = self.hal_hidl_package_name hal_name, hal_version = vts_spec_utils.HalPackageToNameAndVersion( hal_package) vts_spec_names = self._vts_spec_parser.VtsSpecNames( hal_name, hal_version) registered_interfaces = self._RegisteredInterfaces( self.hal_hidl_package_name) test_cases = [] for vts_spec_name in vts_spec_names: vts_spec_proto = self._vts_spec_parser.VtsSpecProto( hal_name, hal_version, vts_spec_name) if not vts_spec_proto.component_name in registered_interfaces: continue test_cases += self._CreateTestCasesFromSpec( hal_package, vts_spec_name, vts_spec_proto) return test_cases if __name__ == '__main__': test_runner.main()