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