• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2021, 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
17import sys
18import subprocess
19import os
20import argparse
21
22TEST_SUITES = [
23    "blueberry.tests.gd.rust.topshim.facade.adapter_test",
24    "blueberry.tests.gd.rust.topshim.facade.suspend_test"
25]
26
27SOONG_UI_BASH = 'build/soong/soong_ui.bash'
28
29def check_dir_exists(dir, dirname):
30    if not os.path.isdir(dir):
31        print("Couldn't find %s (%s)!" % (dirname, dir))
32        sys.exit(0)
33
34def get_output_from_command(cmd):
35    try:
36        return subprocess.check_output(cmd).strip()
37    except subprocess.CalledProcessError as e:
38        print('Failed to call {cmd}, return code {code}'.format(cmd=cmd, code=e.returncode))
39        print(e)
40        return None
41
42def get_android_root_or_die():
43    value = os.environ.get('ANDROID_BUILD_TOP')
44    if not value:
45        # Try to find build/soong/soong_ui.bash upwards until root directory
46        current_path = os.path.abspath(os.getcwd())
47        while current_path and os.path.isdir(current_path):
48            soong_ui_bash_path = os.path.join(current_path, SOONG_UI_BASH)
49            if os.path.isfile(soong_ui_bash_path):
50                # Use value returned from Soong UI instead in case definition to TOP
51                # changes in the future
52                value = get_output_from_command((soong_ui_bash_path, '--dumpvar-mode', '--abs', 'TOP'))
53                break
54            parent_path = os.path.abspath(os.path.join(current_path, os.pardir))
55            if parent_path == current_path:
56                current_path = None
57            else:
58                current_path = parent_path
59        if not value:
60            print('Cannot determine ANDROID_BUILD_TOP')
61            sys.exit(1)
62    check_dir_exists(value, '$ANDROID_BUILD_TOP')
63    return value
64
65def get_android_host_out_or_die():
66    value = os.environ.get('ANDROID_HOST_OUT')
67    if not value:
68        ANDROID_BUILD_TOP = get_android_root_or_die()
69        value = get_output_from_command((os.path.join(ANDROID_BUILD_TOP, SOONG_UI_BASH), '--dumpvar-mode', '--abs',
70                                         'HOST_OUT'))
71        if not value:
72            print('Cannot determine ANDROID_HOST_OUT')
73            sys.exit(1)
74    check_dir_exists(value, '$ANDROID_HOST_OUT')
75    return value
76
77def get_android_dist_dir_or_die():
78    # Check if $DIST_DIR is predefined as environment variable
79    value = os.environ.get('DIST_DIR')
80    if not value:
81        # If not use the default path
82        ANDROID_BUILD_TOP = get_android_root_or_die()
83        value = os.path.join(os.path.join(ANDROID_BUILD_TOP, 'out'), 'dist')
84    if not os.path.isdir(value):
85        if os.path.exists(value):
86            print('%s is not a directory!' % (value))
87            sys.exit(1)
88        os.makedirs(value)
89    return value
90
91def get_test_cmd_or_die(suite_name, config_path):
92    config_file_path = os.path.join(os.path.join(get_android_root_or_die(), 'out/dist'), config_path)
93
94    if not os.path.isfile(config_file_path):
95        print('Cannot find: ' + config_file_path)
96        sys.exit(1)
97    cmd = ["python3", "-m", suite_name, "-c", config_path]
98    return cmd
99
100# path is relative to Android build top
101def build_dist_target(target):
102    ANDROID_BUILD_TOP = get_android_root_or_die()
103    build_cmd = [SOONG_UI_BASH, '--make-mode', 'dist', target]
104    build_cmd.append(target)
105    p = subprocess.Popen(build_cmd, cwd=ANDROID_BUILD_TOP, env=os.environ.copy())
106    return_code = p.wait()
107    if return_code != 0:
108        print('BUILD FAILED, return code: {0}'.format(str(return_code)))
109        sys.exit(1)
110    return
111
112def main():
113    """ run_topshim - Run registered host based topshim tests
114    """
115    parser = argparse.ArgumentParser(description='Run host based topshim tests.')
116    parser.add_argument(
117        '--config',
118        type=str,
119        dest='config_path',
120        nargs='?',
121        const=True,
122        default='blueberry/tests/gd/host_config.yaml',
123        help='Test config for mobly topshim test')
124    args = parser.parse_args()
125
126    build_dist_target('bluetooth_stack_with_facade')
127    test_results = []
128    dist_path = os.path.join(get_android_root_or_die(), "out/dist")
129    subprocess.call(['unzip', '-o', 'bluetooth_cert_tests.zip'], cwd=dist_path)
130    for test in TEST_SUITES:
131        test_cmd = get_test_cmd_or_die(test, args.config_path)
132        if subprocess.call(test_cmd, cwd=dist_path) != 0:
133            test_results.append(False)
134        else:
135            test_results.append(True)
136    if not all(test_results):
137        failures = [i for i, x in enumerate(test_results) if not x]
138        for index in failures:
139            print('TEST FAILED: ' + TEST_SUITES[index])
140        sys.exit(0)
141    print('TEST PASSED ' + str(len(test_results)) + ' tests were run')
142
143if __name__ == '__main__':
144    main()
145