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
20
21from vts.runners.host import keys
22from vts.runners.host import test_runner
23from vts.utils.python.controllers import adb
24from vts.utils.python.controllers import android_device
25from vts.utils.python.common import vts_spec_utils
26
27from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_config as config
28from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_case
29from vts.testcases.fuzz.template.func_fuzzer_test import func_fuzzer_test
30
31
32class IfaceFuzzerTest(func_fuzzer_test.FuncFuzzerTest):
33    """Runs iface_fuzzer tests on target.
34
35    Attributes:
36        See func_fuzzer_test.
37    """
38    _VTS_SPEC_DIR_TARGET = os.path.join(config.FUZZER_TEST_DIR, 'spec')
39
40    def _PushVtsResources(self, hal_name, hal_version):
41        """Pushes resources needed for test to target device.
42
43        Args:
44            hal_name: string, name of the hal, e.g. 'vibrator'.
45            hal_version: string, version of the hal, e.g '7.4'
46        """
47        # Push .vts spec files.
48        hal_name_dir = vts_spec_utils.HalNameDir(hal_name)
49        src_dir = os.path.join(self.data_file_path, 'spec', 'hardware',
50                               'interfaces', hal_name_dir, hal_version, 'vts')
51        dst_dir = os.path.join(self._VTS_SPEC_DIR_TARGET, hal_name_dir,
52                               hal_version)
53
54        # Push corresponding VTS drivers.
55        driver_name = 'android.hardware.%s@%s-vts.driver.so' % (hal_name,
56                                                                hal_version)
57        asan_path = os.path.join(self.data_file_path, 'DATA', 'asan', 'system')
58        driver32 = os.path.join(asan_path, 'lib', driver_name)
59        driver64 = os.path.join(asan_path, 'lib64', driver_name)
60        try:
61            self._dut.adb.push(src_dir, dst_dir)
62            self._dut.adb.push(driver32, 'data/local/tmp/32')
63            self._dut.adb.push(driver64, 'data/local/tmp/64')
64        except adb.AdbError as e:
65            logging.exception(e)
66
67    def _VtsSpecDirsTarget(self, hal_name, hal_version):
68        """Returns a list of directories on target with .vts specs.
69
70        Args:
71            hal_name: string, name of the hal, e.g. 'vibrator'.
72            hal_version: string, version of the hal, e.g '7.4'
73
74        Returns:
75            string list, directories on target
76        """
77        hal_name_dir = vts_spec_utils.HalNameDir(hal_name)
78        spec_dirs = [os.path.join(self._VTS_SPEC_DIR_TARGET, hal_name_dir,
79                                  hal_version)]
80
81        imported_hals = self._vts_spec_parser.ImportedHals(hal_name,
82                                                           hal_version)
83        for name, version in imported_hals:
84            spec_dirs.append(
85                os.path.join(self._VTS_SPEC_DIR_TARGET,
86                             vts_spec_utils.HalNameDir(name), version))
87        return spec_dirs
88
89    # Override
90    def CreateTestCases(self):
91        """See base class."""
92        hal_package = self.hal_hidl_package_name
93        hal_name, hal_version = vts_spec_utils.HalPackageToNameAndVersion(
94            hal_package)
95
96        imported_hals = self._vts_spec_parser.IndirectImportedHals(hal_name,
97                                                                   hal_version)
98        self._PushVtsResources(hal_name, hal_version)
99        for name, version in imported_hals:
100            self._PushVtsResources(name, version)
101
102        registered_interfaces = self._RegisteredInterfaces(hal_package)
103        spec_dirs = ':'.join(self._VtsSpecDirsTarget(hal_name, hal_version))
104
105        test_cases = []
106        for iface in registered_interfaces:
107            additional_params = {
108                'vts_spec_dir': spec_dirs,
109                'vts_exec_size': 16,
110                'vts_target_iface': iface,
111            }
112            libfuzzer_params = config.FUZZER_DEFAULT_PARAMS.copy()
113            libfuzzer_params.update({
114                'max_len': 67108864,
115                'max_total_time': 600,
116            })
117            bin_host_path = os.path.join(self.data_file_path, 'DATA', 'bin',
118                                         'vts_proto_fuzzer')
119            test_case = libfuzzer_test_case.LibFuzzerTestCase(
120                bin_host_path, libfuzzer_params, additional_params)
121            test_case.test_name = iface
122            test_cases.append(test_case)
123
124        return test_cases
125
126    # Override
127    def LogCrashReport(self, test_case):
128        """See base class."""
129        # Re-run the failing test case in debug mode.
130        logging.info('Attempting to reproduce the failure.')
131        repro_cmd = '"%s %s"' % (test_case.GetRunCommand(debug_mode=True),
132                                 config.FUZZER_TEST_CRASH_REPORT)
133        self._dut.adb.shell(repro_cmd, no_except=True)
134
135
136if __name__ == '__main__':
137    test_runner.main()
138