xref: /aosp_15_r20/external/libcxx/run_tests.py (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1*58b9f456SAndroid Build Coastguard Worker#!/usr/bin/env python
2*58b9f456SAndroid Build Coastguard Worker#
3*58b9f456SAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project
4*58b9f456SAndroid Build Coastguard Worker#
5*58b9f456SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*58b9f456SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*58b9f456SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*58b9f456SAndroid Build Coastguard Worker#
9*58b9f456SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*58b9f456SAndroid Build Coastguard Worker#
11*58b9f456SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*58b9f456SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*58b9f456SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*58b9f456SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*58b9f456SAndroid Build Coastguard Worker# limitations under the License.
16*58b9f456SAndroid Build Coastguard Worker#
17*58b9f456SAndroid Build Coastguard Worker"""Runs the libc++ tests against the platform libc++."""
18*58b9f456SAndroid Build Coastguard Workerfrom __future__ import print_function
19*58b9f456SAndroid Build Coastguard Worker
20*58b9f456SAndroid Build Coastguard Workerimport argparse
21*58b9f456SAndroid Build Coastguard Workerimport logging
22*58b9f456SAndroid Build Coastguard Workerimport os
23*58b9f456SAndroid Build Coastguard Workerimport posixpath
24*58b9f456SAndroid Build Coastguard Workerimport sys
25*58b9f456SAndroid Build Coastguard Worker
26*58b9f456SAndroid Build Coastguard WorkerTHIS_DIR = os.path.dirname(os.path.realpath(__file__))
27*58b9f456SAndroid Build Coastguard WorkerANDROID_DIR = os.path.realpath(os.path.join(THIS_DIR, '../..'))
28*58b9f456SAndroid Build Coastguard Worker
29*58b9f456SAndroid Build Coastguard Worker
30*58b9f456SAndroid Build Coastguard Workerdef logger():
31*58b9f456SAndroid Build Coastguard Worker    """Returns the logger for the module."""
32*58b9f456SAndroid Build Coastguard Worker    return logging.getLogger(__name__)
33*58b9f456SAndroid Build Coastguard Worker
34*58b9f456SAndroid Build Coastguard Worker
35*58b9f456SAndroid Build Coastguard Workerdef call(cmd, *args, **kwargs):
36*58b9f456SAndroid Build Coastguard Worker    """subprocess.call with logging."""
37*58b9f456SAndroid Build Coastguard Worker    import subprocess
38*58b9f456SAndroid Build Coastguard Worker    logger().info('call %s', ' '.join(cmd))
39*58b9f456SAndroid Build Coastguard Worker    return subprocess.call(cmd, *args, **kwargs)
40*58b9f456SAndroid Build Coastguard Worker
41*58b9f456SAndroid Build Coastguard Worker
42*58b9f456SAndroid Build Coastguard Workerdef check_call(cmd, *args, **kwargs):
43*58b9f456SAndroid Build Coastguard Worker    """subprocess.check_call with logging."""
44*58b9f456SAndroid Build Coastguard Worker    import subprocess
45*58b9f456SAndroid Build Coastguard Worker    logger().info('check_call %s', ' '.join(cmd))
46*58b9f456SAndroid Build Coastguard Worker    return subprocess.check_call(cmd, *args, **kwargs)
47*58b9f456SAndroid Build Coastguard Worker
48*58b9f456SAndroid Build Coastguard Worker
49*58b9f456SAndroid Build Coastguard Workerdef check_output(cmd, *args, **kwargs):
50*58b9f456SAndroid Build Coastguard Worker    """subprocess.check_output with logging."""
51*58b9f456SAndroid Build Coastguard Worker    import subprocess
52*58b9f456SAndroid Build Coastguard Worker    logger().info('check_output %s', ' '.join(cmd))
53*58b9f456SAndroid Build Coastguard Worker    return subprocess.check_output(cmd, *args, **kwargs)
54*58b9f456SAndroid Build Coastguard Worker
55*58b9f456SAndroid Build Coastguard Worker
56*58b9f456SAndroid Build Coastguard Workerclass ArgParser(argparse.ArgumentParser):
57*58b9f456SAndroid Build Coastguard Worker    """Parses command line arguments."""
58*58b9f456SAndroid Build Coastguard Worker
59*58b9f456SAndroid Build Coastguard Worker    def __init__(self):
60*58b9f456SAndroid Build Coastguard Worker        super(ArgParser, self).__init__()
61*58b9f456SAndroid Build Coastguard Worker        self.add_argument('--bitness', choices=(32, 64), type=int, default=32)
62*58b9f456SAndroid Build Coastguard Worker        self.add_argument('--host', action='store_true')
63*58b9f456SAndroid Build Coastguard Worker
64*58b9f456SAndroid Build Coastguard Worker
65*58b9f456SAndroid Build Coastguard Workerdef extract_build_cmds(commands, exe_name):
66*58b9f456SAndroid Build Coastguard Worker    """Extracts build command information from `ninja -t commands` output.
67*58b9f456SAndroid Build Coastguard Worker
68*58b9f456SAndroid Build Coastguard Worker    Args:
69*58b9f456SAndroid Build Coastguard Worker        commands: String containing the output of `ninja -t commands` for the
70*58b9f456SAndroid Build Coastguard Worker            libcxx_test_template.
71*58b9f456SAndroid Build Coastguard Worker        exe_name: The basename of the built executable.
72*58b9f456SAndroid Build Coastguard Worker
73*58b9f456SAndroid Build Coastguard Worker    Returns:
74*58b9f456SAndroid Build Coastguard Worker        Tuple of (compiler, compiler_flags, linker_flags).
75*58b9f456SAndroid Build Coastguard Worker    """
76*58b9f456SAndroid Build Coastguard Worker    cc = None
77*58b9f456SAndroid Build Coastguard Worker    cflags = None
78*58b9f456SAndroid Build Coastguard Worker    ldflags = None
79*58b9f456SAndroid Build Coastguard Worker    template_name = 'external/libcxx/libcxx_test_template.cpp'
80*58b9f456SAndroid Build Coastguard Worker
81*58b9f456SAndroid Build Coastguard Worker    for cmd in commands.splitlines():
82*58b9f456SAndroid Build Coastguard Worker        cmd_args = cmd.split()
83*58b9f456SAndroid Build Coastguard Worker        if cc is None and template_name in cmd_args:
84*58b9f456SAndroid Build Coastguard Worker            for i, arg in enumerate(cmd_args):
85*58b9f456SAndroid Build Coastguard Worker                if arg == '-o':
86*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i + 1] = '%OUT%'
87*58b9f456SAndroid Build Coastguard Worker                elif arg == template_name:
88*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i] = '%SOURCE%'
89*58b9f456SAndroid Build Coastguard Worker                # Drop dependency tracking args since they can cause file
90*58b9f456SAndroid Build Coastguard Worker                # not found errors at test time.
91*58b9f456SAndroid Build Coastguard Worker                if arg == '-MD':
92*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i] = ''
93*58b9f456SAndroid Build Coastguard Worker                if arg == '-MF':
94*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i] = ''
95*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i + 1] = ''
96*58b9f456SAndroid Build Coastguard Worker            if cmd_args[0] == 'PWD=/proc/self/cwd':
97*58b9f456SAndroid Build Coastguard Worker                cmd_args = cmd_args[1:]
98*58b9f456SAndroid Build Coastguard Worker            if cmd_args[0].endswith('gomacc'):
99*58b9f456SAndroid Build Coastguard Worker                cmd_args = cmd_args[1:]
100*58b9f456SAndroid Build Coastguard Worker            cc = cmd_args[0]
101*58b9f456SAndroid Build Coastguard Worker            cflags = cmd_args[1:]
102*58b9f456SAndroid Build Coastguard Worker        if ldflags is None:
103*58b9f456SAndroid Build Coastguard Worker            is_ld = False
104*58b9f456SAndroid Build Coastguard Worker            for i, arg in enumerate(cmd_args):
105*58b9f456SAndroid Build Coastguard Worker                # Here we assume that the rspfile contains the path to the
106*58b9f456SAndroid Build Coastguard Worker                # object file and nothing else.
107*58b9f456SAndroid Build Coastguard Worker                if arg.startswith('@'):
108*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i] = '%SOURCE%'
109*58b9f456SAndroid Build Coastguard Worker                if arg == '-o' and cmd_args[i + 1].endswith(exe_name):
110*58b9f456SAndroid Build Coastguard Worker                    cmd_args[i + 1] = '%OUT%'
111*58b9f456SAndroid Build Coastguard Worker                    is_ld = True
112*58b9f456SAndroid Build Coastguard Worker            if is_ld:
113*58b9f456SAndroid Build Coastguard Worker                ldflags = cmd_args[1:]
114*58b9f456SAndroid Build Coastguard Worker
115*58b9f456SAndroid Build Coastguard Worker    return cc, cflags, ldflags
116*58b9f456SAndroid Build Coastguard Worker
117*58b9f456SAndroid Build Coastguard Worker
118*58b9f456SAndroid Build Coastguard Workerdef get_build_cmds(bitness, host):
119*58b9f456SAndroid Build Coastguard Worker    """Use ninja -t commands to find the build commands for an executable."""
120*58b9f456SAndroid Build Coastguard Worker    out_dir = os.getenv('OUT_DIR', os.path.join(ANDROID_DIR, 'out'))
121*58b9f456SAndroid Build Coastguard Worker    product_out = os.getenv('ANDROID_PRODUCT_OUT')
122*58b9f456SAndroid Build Coastguard Worker
123*58b9f456SAndroid Build Coastguard Worker    if host:
124*58b9f456SAndroid Build Coastguard Worker        rel_out_dir = os.path.relpath(
125*58b9f456SAndroid Build Coastguard Worker            os.path.join(out_dir, 'soong/host/linux-x86/bin'), ANDROID_DIR)
126*58b9f456SAndroid Build Coastguard Worker        target = os.path.join(rel_out_dir, 'libcxx_test_template64')
127*58b9f456SAndroid Build Coastguard Worker    else:
128*58b9f456SAndroid Build Coastguard Worker        exe_name = 'libcxx_test_template' + str(bitness)
129*58b9f456SAndroid Build Coastguard Worker        rel_out_dir = os.path.relpath(product_out, ANDROID_DIR)
130*58b9f456SAndroid Build Coastguard Worker        target = os.path.join(rel_out_dir, 'system/bin', exe_name)
131*58b9f456SAndroid Build Coastguard Worker
132*58b9f456SAndroid Build Coastguard Worker    # Generate $OUT_DIR/combined-$TARGET_PRODUCT.ninja and build the
133*58b9f456SAndroid Build Coastguard Worker    # template target's dependencies.
134*58b9f456SAndroid Build Coastguard Worker    check_call([
135*58b9f456SAndroid Build Coastguard Worker        'bash',
136*58b9f456SAndroid Build Coastguard Worker        os.path.join(ANDROID_DIR, 'build/soong/soong_ui.bash'), '--make-mode',
137*58b9f456SAndroid Build Coastguard Worker        target
138*58b9f456SAndroid Build Coastguard Worker    ])
139*58b9f456SAndroid Build Coastguard Worker
140*58b9f456SAndroid Build Coastguard Worker    ninja_path = os.path.join(
141*58b9f456SAndroid Build Coastguard Worker        out_dir, 'combined-' + os.getenv('TARGET_PRODUCT') + '.ninja')
142*58b9f456SAndroid Build Coastguard Worker    commands = check_output([
143*58b9f456SAndroid Build Coastguard Worker        os.path.join(ANDROID_DIR, 'prebuilts/build-tools/linux-x86/bin/ninja'),
144*58b9f456SAndroid Build Coastguard Worker        '-C', ANDROID_DIR, '-f', ninja_path, '-t', 'commands', target
145*58b9f456SAndroid Build Coastguard Worker    ])
146*58b9f456SAndroid Build Coastguard Worker
147*58b9f456SAndroid Build Coastguard Worker    return extract_build_cmds(commands, os.path.basename(target))
148*58b9f456SAndroid Build Coastguard Worker
149*58b9f456SAndroid Build Coastguard Worker
150*58b9f456SAndroid Build Coastguard Workerdef setup_test_directory():
151*58b9f456SAndroid Build Coastguard Worker    """Prepares a device test directory for use by the shell user."""
152*58b9f456SAndroid Build Coastguard Worker    stdfs_test_data = os.path.join(
153*58b9f456SAndroid Build Coastguard Worker        THIS_DIR, 'test/std/input.output/filesystems/Inputs/static_test_env')
154*58b9f456SAndroid Build Coastguard Worker    device_dir = '/data/local/tmp/libcxx'
155*58b9f456SAndroid Build Coastguard Worker    dynamic_dir = posixpath.join(device_dir, 'dynamic_test_env')
156*58b9f456SAndroid Build Coastguard Worker    check_call(['adb', 'shell', 'rm', '-rf', device_dir])
157*58b9f456SAndroid Build Coastguard Worker    check_call(['adb', 'shell', 'mkdir', '-p', device_dir])
158*58b9f456SAndroid Build Coastguard Worker    check_call(['adb', 'shell', 'mkdir', '-p', dynamic_dir])
159*58b9f456SAndroid Build Coastguard Worker    check_call(['adb', 'push', '--sync', stdfs_test_data, device_dir])
160*58b9f456SAndroid Build Coastguard Worker    check_call(['adb', 'shell', 'chown', '-R', 'shell:shell', device_dir])
161*58b9f456SAndroid Build Coastguard Worker
162*58b9f456SAndroid Build Coastguard Worker
163*58b9f456SAndroid Build Coastguard Workerdef main():
164*58b9f456SAndroid Build Coastguard Worker    """Program entry point."""
165*58b9f456SAndroid Build Coastguard Worker    logging.basicConfig(level=logging.INFO)
166*58b9f456SAndroid Build Coastguard Worker
167*58b9f456SAndroid Build Coastguard Worker    args, lit_args = ArgParser().parse_known_args()
168*58b9f456SAndroid Build Coastguard Worker    lit_path = os.path.join(ANDROID_DIR, 'external/llvm/utils/lit/lit.py')
169*58b9f456SAndroid Build Coastguard Worker    cc, cflags, ldflags = get_build_cmds(args.bitness, args.host)
170*58b9f456SAndroid Build Coastguard Worker
171*58b9f456SAndroid Build Coastguard Worker    mode_str = 'host' if args.host else 'device'
172*58b9f456SAndroid Build Coastguard Worker    android_mode_arg = '--param=android_mode=' + mode_str
173*58b9f456SAndroid Build Coastguard Worker    cxx_under_test_arg = '--param=cxx_under_test=' + cc
174*58b9f456SAndroid Build Coastguard Worker    cxx_template_arg = '--param=cxx_template=' + ' '.join(cflags)
175*58b9f456SAndroid Build Coastguard Worker    link_template_arg = '--param=link_template=' + ' '.join(ldflags)
176*58b9f456SAndroid Build Coastguard Worker    site_cfg_path = os.path.join(THIS_DIR, 'test/lit.site.cfg')
177*58b9f456SAndroid Build Coastguard Worker    libcxx_site_cfg_arg = '--param=libcxx_site_config=' + site_cfg_path
178*58b9f456SAndroid Build Coastguard Worker    libcxxabi_site_cfg_arg = '--param=libcxxabi_site_config=' + site_cfg_path
179*58b9f456SAndroid Build Coastguard Worker    default_test_paths = [
180*58b9f456SAndroid Build Coastguard Worker        os.path.join(THIS_DIR, 'test'),
181*58b9f456SAndroid Build Coastguard Worker        os.path.join(ANDROID_DIR, 'external/libcxxabi/test')
182*58b9f456SAndroid Build Coastguard Worker    ]
183*58b9f456SAndroid Build Coastguard Worker
184*58b9f456SAndroid Build Coastguard Worker    have_filter_args = False
185*58b9f456SAndroid Build Coastguard Worker    for arg in lit_args:
186*58b9f456SAndroid Build Coastguard Worker        # If the argument is a valid path with default_test_paths, it is a test
187*58b9f456SAndroid Build Coastguard Worker        # filter.
188*58b9f456SAndroid Build Coastguard Worker        real_path = os.path.realpath(arg)
189*58b9f456SAndroid Build Coastguard Worker        if not any(real_path.startswith(path) for path in default_test_paths):
190*58b9f456SAndroid Build Coastguard Worker            continue
191*58b9f456SAndroid Build Coastguard Worker        if not os.path.exists(real_path):
192*58b9f456SAndroid Build Coastguard Worker            continue
193*58b9f456SAndroid Build Coastguard Worker
194*58b9f456SAndroid Build Coastguard Worker        have_filter_args = True
195*58b9f456SAndroid Build Coastguard Worker        break  # No need to keep scanning.
196*58b9f456SAndroid Build Coastguard Worker
197*58b9f456SAndroid Build Coastguard Worker    if not args.host:
198*58b9f456SAndroid Build Coastguard Worker        setup_test_directory()
199*58b9f456SAndroid Build Coastguard Worker
200*58b9f456SAndroid Build Coastguard Worker    lit_args = [
201*58b9f456SAndroid Build Coastguard Worker        '-sv', android_mode_arg, cxx_under_test_arg, cxx_template_arg,
202*58b9f456SAndroid Build Coastguard Worker        link_template_arg, libcxx_site_cfg_arg, libcxxabi_site_cfg_arg
203*58b9f456SAndroid Build Coastguard Worker    ] + lit_args
204*58b9f456SAndroid Build Coastguard Worker    cmd = ['python', lit_path] + lit_args
205*58b9f456SAndroid Build Coastguard Worker    if not have_filter_args:
206*58b9f456SAndroid Build Coastguard Worker        cmd += default_test_paths
207*58b9f456SAndroid Build Coastguard Worker    sys.exit(call(cmd))
208*58b9f456SAndroid Build Coastguard Worker
209*58b9f456SAndroid Build Coastguard Worker
210*58b9f456SAndroid Build Coastguard Workerif __name__ == '__main__':
211*58b9f456SAndroid Build Coastguard Worker    main()
212