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
17import os
18
19from vts.utils.python.os import path_utils
20
21from vts.testcases.fuzz.template.libfuzzer_test import libfuzzer_test_config as config
22
23
24class LibFuzzerTestCase(object):
25    """Represents libfuzzer test case.
26
27    Attributes:
28        _bin_host_path: string, path to binary on host.
29        _bin_name: string, name of the binary.
30        _test_name: string, name of the test case.
31        _libfuzzer_params: dict, libfuzzer-specific parameters.
32        _additional_params: dict, additional parameters.
33    """
34
35    def __init__(self, bin_host_path, libfuzzer_params, additional_params):
36        self._bin_host_path = bin_host_path
37        self._libfuzzer_params = libfuzzer_params
38        self._additional_params = additional_params
39        self._binary_name = os.path.basename(bin_host_path)
40        self._test_name = self._binary_name
41
42    def GetCorpusName(self):
43        """Returns corpus directory name on target."""
44        corpus_dir = path_utils.JoinTargetPath(
45            config.FUZZER_TEST_DIR, '%s_corpus' % self._test_name)
46        return corpus_dir
47
48    def CreateFuzzerFlags(self):
49        """Creates flags for the fuzzer executable.
50
51        Returns:
52            string, of form '-<flag0>=<val0> -<flag1>=<val1> ... '
53        """
54        # Used to separate additional and libfuzzer flags.
55        DELIMITER = '--'
56        additional_flags = ' '.join(
57            ['--%s=%s' % (k, v) for k, v in self._additional_params.items()])
58        libfuzzer_flags = ' '.join(
59            ['-%s=%s' % (k, v) for k, v in self._libfuzzer_params.items()])
60        if not additional_flags:
61            flags = libfuzzer_flags
62        else:
63            flags = '%s %s %s' % (additional_flags, DELIMITER, libfuzzer_flags)
64        return flags
65
66    def GetRunCommand(self):
67        """Returns target shell command to run the fuzzer binary."""
68        test_flags = self.CreateFuzzerFlags()
69        corpus_dir = self.GetCorpusName()
70
71        cd_cmd = 'cd %s' % config.FUZZER_TEST_DIR
72        chmod_cmd = 'chmod 777 %s' % self._binary_name
73        ld_path = 'LD_LIBRARY_PATH=/data/local/tmp/64:/data/local/tmp/32:$LD_LIBRARY_PATH'
74        test_cmd = '%s ./%s %s %s > /dev/null' % (ld_path, self._binary_name,
75                                                  corpus_dir, test_flags)
76        return ' && '.join([cd_cmd, chmod_cmd, test_cmd])
77
78    @property
79    def test_name(self):
80        """Name of this test case."""
81        return str(self._test_name)
82
83    @test_name.setter
84    def test_name(self, name):
85        """Set name of this test case."""
86        self._test_name = name
87
88    @property
89    def bin_host_path(self):
90        """Host path to binary for this test case."""
91        return self._bin_host_path
92