1import os
2
3import lit.util  # pylint: disable=import-error
4
5from libcxx.android.executors import AdbExecutor
6from libcxx.test.executor import LocalExecutor, TimeoutExecutor
7import libcxx.test.format
8import libcxx.android.adb as adb
9
10
11class HostTestFormat(libcxx.test.format.LibcxxTestFormat):
12    # pylint: disable=super-init-not-called
13    def __init__(self, cxx, libcxx_src_root, libcxx_obj_root, timeout,
14                 exec_env=None):
15        self.cxx = cxx
16        self.libcxx_src_root = libcxx_src_root
17        self.libcxx_obj_root = libcxx_obj_root
18        self.use_verify_for_fail = False
19        self.executor = TimeoutExecutor(timeout, LocalExecutor())
20
21        if exec_env is None:
22            # We need to use LD_LIBRARY_PATH because the build system's rpath
23            # is relative, which won't work since we're running from /tmp. We
24            # can either scan `cxx_under_test`/`link_template` to determine
25            # whether we're 32-bit or 64-bit, scan testconfig.mk, or just add
26            # both directories and let the linker sort it out. I'm choosing the
27            # lazy option.
28            outdir = os.getenv('ANDROID_HOST_OUT')
29            libpath = os.pathsep.join([
30                os.path.join(outdir, 'lib'),
31                os.path.join(outdir, 'lib64'),
32            ])
33            self.exec_env = {'LD_LIBRARY_PATH': libpath}
34        else:
35            self.exec_env = exec_env
36
37
38class TestFormat(HostTestFormat):
39    def __init__(self, cxx, libcxx_src_root, libcxx_obj_root, device_dir,
40                 timeout, exec_env=None):
41        HostTestFormat.__init__(
42            self,
43            cxx,
44            libcxx_src_root,
45            libcxx_obj_root,
46            timeout,
47            exec_env)
48        self.device_dir = device_dir
49        self.executor = TimeoutExecutor(timeout, AdbExecutor())
50
51    def _working_directory(self, file_name):
52        return os.path.join(self.device_dir, file_name)
53
54    def _wd_path(self, test_name, file_name):
55        return os.path.join(self._working_directory(test_name), file_name)
56
57    def _build(self, exec_path, source_path, compile_only=False,
58               use_verify=False):
59        # pylint: disable=protected-access
60        cmd, report, rc = libcxx.test.format.LibcxxTestFormat._build(
61            self, exec_path, source_path, compile_only, use_verify)
62        if rc != 0:
63            return cmd, report, rc
64
65        try:
66            exec_file = os.path.basename(exec_path)
67
68            adb.mkdir(self._working_directory(exec_file))
69            adb.push(exec_path, self._wd_path(exec_file, exec_file))
70
71            # Push any .dat files in the same directory as the source to the
72            # working directory.
73            src_dir = os.path.dirname(source_path)
74            data_files = [f for f in os.listdir(src_dir) if f.endswith('.dat')]
75            for data_file in data_files:
76                df_path = os.path.join(src_dir, data_file)
77                df_dev_path = self._wd_path(exec_file, data_file)
78                adb.push(df_path, df_dev_path)
79            return cmd, report, rc
80        except adb.AdbError as ex:
81            return self._make_report(ex.cmd, ex.out, ex.err, ex.exit_code)
82
83    def _clean(self, exec_path):
84        exec_file = os.path.basename(exec_path)
85        cmd = ['adb', 'shell', 'rm', '-rf', self._working_directory(exec_file)]
86        lit.util.executeCommand(cmd)
87        try:
88            os.remove(exec_path)
89        except OSError:
90            pass
91
92    def _run(self, exec_path, _, in_dir=None):
93        raise NotImplementedError()
94