blob: 3d3f1c712fada890f40c97a69193c6d75039473d [file] [log] [blame]
Jack Heaba81f42017-09-28 18:41:28 -07001#!/usr/bin/env python
2#
3# Copyright 2017, 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.
16import sys
17import subprocess
18import os
19import argparse
Jack Heaba81f42017-09-28 18:41:28 -070020
21# Registered host based unit tests
22# Must have 'host_supported: true'
23HOST_TESTS = [
Jack Hec27d2572018-07-25 12:02:22 -070024 'bluetooth_test_common',
Jack He39555a32017-10-23 13:28:59 -070025 'bluetoothtbd_test',
Ajay Panicker2c822c92018-02-21 21:04:24 -080026 'net_test_avrcp',
Jack He39555a32017-10-23 13:28:59 -070027 'net_test_btcore',
28 'net_test_types',
Ajay Panicker341ab2b2018-01-03 14:23:44 -080029 'net_test_btpackets',
Jack Heaba81f42017-09-28 18:41:28 -070030]
31
Jack He39555a32017-10-23 13:28:59 -070032SOONG_UI_BASH = 'build/soong/soong_ui.bash'
33
Jack Heaba81f42017-09-28 18:41:28 -070034def str2bool(argument, default=False):
35 """ Convert a string to a booleen value. """
36 argument = str(argument)
37 if argument.lower() in ['0', 'f', 'false', 'off', 'no', 'n']:
38 return False
39 elif argument.lower() in ['1', 't', 'true', 'on', 'yes', 'y']:
40 return True
41 return default
42
43
44def check_dir_exists(dir, dirname):
45 if not os.path.isdir(dir):
46 print "Couldn't find %s (%s)!" % (dirname, dir)
47 sys.exit(0)
48
49
Jack He39555a32017-10-23 13:28:59 -070050def get_output_from_command(cmd):
51 try:
52 return subprocess.check_output(cmd).strip()
53 except subprocess.CalledProcessError as e:
54 print 'Failed to call {cmd}, return code {code}'.format(cmd=cmd,
55 code=e.returncode)
56 print e
57 return None
Jack Heaba81f42017-09-28 18:41:28 -070058
59
60def get_android_root_or_die():
61 value = os.environ.get('ANDROID_BUILD_TOP')
62 if not value:
Jack He39555a32017-10-23 13:28:59 -070063 # Try to find build/soong/soong_ui.bash upwards until root directory
64 current_path = os.path.abspath(os.getcwd())
65 while current_path and os.path.isdir(current_path):
66 soong_ui_bash_path = os.path.join(current_path, SOONG_UI_BASH)
67 if os.path.isfile(soong_ui_bash_path):
68 # Use value returned from Soong UI instead in case definition to TOP
69 # changes in the future
70 value = get_output_from_command((soong_ui_bash_path,
71 '--dumpvar-mode',
72 '--abs',
73 'TOP'))
74 break
75 parent_path = os.path.abspath(os.path.join(current_path, os.pardir))
76 if parent_path == current_path:
77 current_path = None
78 else:
79 current_path = parent_path
80 if not value:
81 print 'Cannot determine ANDROID_BUILD_TOP'
Jack Heb7385762017-10-25 10:14:53 -070082 sys.exit(1)
Jack Heaba81f42017-09-28 18:41:28 -070083 check_dir_exists(value, '$ANDROID_BUILD_TOP')
84 return value
85
86
87def get_android_host_out_or_die():
88 value = os.environ.get('ANDROID_HOST_OUT')
89 if not value:
Jack He39555a32017-10-23 13:28:59 -070090 ANDROID_BUILD_TOP = get_android_root_or_die()
91 value = get_output_from_command((os.path.join(ANDROID_BUILD_TOP,
92 SOONG_UI_BASH),
93 '--dumpvar-mode',
94 '--abs',
95 'HOST_OUT'))
96 if not value:
97 print 'Cannot determine ANDROID_HOST_OUT'
Jack Heb7385762017-10-25 10:14:53 -070098 sys.exit(1)
Jack Heaba81f42017-09-28 18:41:28 -070099 check_dir_exists(value, '$ANDROID_HOST_OUT')
100 return value
101
102
103def get_android_dist_dir_or_die():
Jack He11f1e932017-10-17 12:01:39 -0700104 # Check if $DIST_DIR is predefined as environment variable
105 value = os.environ.get('DIST_DIR')
106 if not value:
107 # If not use the default path
108 ANDROID_BUILD_TOP = get_android_root_or_die()
109 value = os.path.join(os.path.join(ANDROID_BUILD_TOP, 'out'), 'dist')
Jack Heaba81f42017-09-28 18:41:28 -0700110 if not os.path.isdir(value):
111 if os.path.exists(value):
112 print '%s is not a directory!' % (value)
Jack Heb7385762017-10-25 10:14:53 -0700113 sys.exit(1)
Jack Heaba81f42017-09-28 18:41:28 -0700114 os.makedirs(value)
115 return value
116
117
118def get_native_test_root_or_die():
119 android_host_out = get_android_host_out_or_die()
120 test_root = os.path.join(android_host_out, 'nativetest64')
121 if not os.path.isdir(test_root):
122 test_root = os.path.join(android_host_out, 'nativetest')
123 if not os.path.isdir(test_root):
124 print 'Neither nativetest64 nor nativetest directory exist,' \
Jack He39555a32017-10-23 13:28:59 -0700125 ' please compile first'
Jack Heb7385762017-10-25 10:14:53 -0700126 sys.exit(1)
Jack Heaba81f42017-09-28 18:41:28 -0700127 return test_root
128
129
130def get_test_cmd_or_die(test_root, test_name, enable_xml, test_filter):
131 test_path = os.path.join(os.path.join(test_root, test_name), test_name)
132 if not os.path.isfile(test_path):
133 print 'Cannot find: ' + test_path
Jack Heb7385762017-10-25 10:14:53 -0700134 sys.exit(1)
Jack Heaba81f42017-09-28 18:41:28 -0700135 cmd = [test_path]
136 if enable_xml:
137 dist_dir = get_android_dist_dir_or_die()
Jack He39555a32017-10-23 13:28:59 -0700138 log_output_path = os.path.join(dist_dir, 'gtest/{0}_test_details.xml'
139 .format(test_name))
140 cmd.append('--gtest_output=xml:{0}'.format(log_output_path))
Jack Heaba81f42017-09-28 18:41:28 -0700141 if test_filter:
142 cmd.append('--gtest_filter=%s' % test_filter)
143 return cmd
144
145
146# path is relative to Android build top
Jack He39555a32017-10-23 13:28:59 -0700147def build_target(target, num_tasks):
Jack Heaba81f42017-09-28 18:41:28 -0700148 ANDROID_BUILD_TOP = get_android_root_or_die()
Jack He39555a32017-10-23 13:28:59 -0700149 build_cmd = [SOONG_UI_BASH, '--make-mode']
Jack Heaba81f42017-09-28 18:41:28 -0700150 if num_tasks > 1:
151 build_cmd.append('-j' + str(num_tasks))
Jack He39555a32017-10-23 13:28:59 -0700152 build_cmd.append(target)
153 p = subprocess.Popen(build_cmd, cwd=ANDROID_BUILD_TOP, env=os.environ.copy())
Jack Heb7385762017-10-25 10:14:53 -0700154 return_code = p.wait()
155 if return_code != 0:
156 print 'BUILD FAILED, return code: {0}'.format(str(return_code))
157 sys.exit(1)
Jack Heaba81f42017-09-28 18:41:28 -0700158 return
159
160
161def main():
162 """ run_host_unit_tests.py - Run registered host based unit tests
163 """
164 parser = argparse.ArgumentParser(description='Run host based unit tests.')
165 parser.add_argument(
166 '--enable_xml',
167 type=str2bool,
168 dest='enable_xml',
169 nargs='?',
170 const=True,
171 default=False,
172 help=
173 'Whether to output structured XML log output in out/dist/gtest directory')
174 parser.add_argument(
175 '-j',
176 type=int,
177 nargs='?',
178 dest='num_tasks',
179 const=-1,
180 default=-1,
181 help='Number of tasks to run at the same time')
182 parser.add_argument(
183 'rest',
184 nargs=argparse.REMAINDER,
185 help='-- args, other gtest arguments for each individual test')
186 args = parser.parse_args()
187
Jack He39555a32017-10-23 13:28:59 -0700188 build_target('MODULES-IN-system-bt', args.num_tasks)
Jack Heaba81f42017-09-28 18:41:28 -0700189 TEST_ROOT = get_native_test_root_or_die()
190 test_results = []
191 for test in HOST_TESTS:
192 test_cmd = get_test_cmd_or_die(TEST_ROOT, test, args.enable_xml, args.rest)
Jack Heaba81f42017-09-28 18:41:28 -0700193 if subprocess.call(test_cmd) != 0:
194 test_results.append(False)
195 else:
196 test_results.append(True)
197 if not all(test_results):
198 failures = [i for i, x in enumerate(test_results) if not x]
199 for index in failures:
200 print 'TEST FAILLED: ' + HOST_TESTS[index]
201 sys.exit(0)
202 print 'TEST PASSED ' + str(len(test_results)) + ' tests were run'
Ajay Panickerff48ce82018-09-20 14:39:00 -0700203
204 dist_dir = get_android_dist_dir_or_die()
205 log_output_path = os.path.join(dist_dir, 'gtest/coverage')
206 cmd_path = os.path.join(get_android_root_or_die(), 'system/bt/test')
207 print cmd_path
208 cmd = [
209 os.path.join(cmd_path, 'gen_coverage.py'),
210 '--skip-html',
211 '--json-file',
212 '-o',
213 log_output_path,
214 ]
215 subprocess.call(cmd)
216
Jack Heaba81f42017-09-28 18:41:28 -0700217 sys.exit(0)
218
219
220if __name__ == '__main__':
221 main()