3 # Copyright 2017, The Android Open Source Project
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
21 # Registered host based unit tests
22 # Must have 'host_supported: true'
24 'bluetooth_test_common',
32 SOONG_UI_BASH = 'build/soong/soong_ui.bash'
35 def str2bool(argument, default=False):
36 """ Convert a string to a booleen value. """
37 argument = str(argument)
38 if argument.lower() in ['0', 'f', 'false', 'off', 'no', 'n']:
40 elif argument.lower() in ['1', 't', 'true', 'on', 'yes', 'y']:
45 def check_dir_exists(dir, dirname):
46 if not os.path.isdir(dir):
47 print "Couldn't find %s (%s)!" % (dirname, dir)
51 def get_output_from_command(cmd):
53 return subprocess.check_output(cmd).strip()
54 except subprocess.CalledProcessError as e:
55 print 'Failed to call {cmd}, return code {code}'.format(
56 cmd=cmd, code=e.returncode)
61 def get_android_root_or_die():
62 value = os.environ.get('ANDROID_BUILD_TOP')
64 # Try to find build/soong/soong_ui.bash upwards until root directory
65 current_path = os.path.abspath(os.getcwd())
66 while current_path and os.path.isdir(current_path):
67 soong_ui_bash_path = os.path.join(current_path, SOONG_UI_BASH)
68 if os.path.isfile(soong_ui_bash_path):
69 # Use value returned from Soong UI instead in case definition to TOP
70 # changes in the future
71 value = get_output_from_command(
72 (soong_ui_bash_path, '--dumpvar-mode', '--abs', 'TOP'))
74 parent_path = os.path.abspath(os.path.join(current_path, os.pardir))
75 if parent_path == current_path:
78 current_path = parent_path
80 print 'Cannot determine ANDROID_BUILD_TOP'
82 check_dir_exists(value, '$ANDROID_BUILD_TOP')
86 def get_android_host_out_or_die():
87 value = os.environ.get('ANDROID_HOST_OUT')
89 ANDROID_BUILD_TOP = get_android_root_or_die()
90 value = get_output_from_command(
91 (os.path.join(ANDROID_BUILD_TOP, SOONG_UI_BASH), '--dumpvar-mode',
94 print 'Cannot determine ANDROID_HOST_OUT'
96 check_dir_exists(value, '$ANDROID_HOST_OUT')
100 def get_android_dist_dir_or_die():
101 # Check if $DIST_DIR is predefined as environment variable
102 value = os.environ.get('DIST_DIR')
104 # If not use the default path
105 ANDROID_BUILD_TOP = get_android_root_or_die()
106 value = os.path.join(os.path.join(ANDROID_BUILD_TOP, 'out'), 'dist')
107 if not os.path.isdir(value):
108 if os.path.exists(value):
109 print '%s is not a directory!' % (value)
115 def get_native_test_root_or_die():
116 android_host_out = get_android_host_out_or_die()
117 test_root = os.path.join(android_host_out, 'nativetest64')
118 if not os.path.isdir(test_root):
119 test_root = os.path.join(android_host_out, 'nativetest')
120 if not os.path.isdir(test_root):
121 print 'Neither nativetest64 nor nativetest directory exist,' \
122 ' please compile first'
127 def get_test_cmd_or_die(test_root, test_name, enable_xml, test_filter):
128 test_path = os.path.join(os.path.join(test_root, test_name), test_name)
129 if not os.path.isfile(test_path):
130 print 'Cannot find: ' + test_path
134 dist_dir = get_android_dist_dir_or_die()
135 log_output_path = os.path.join(
136 dist_dir, 'gtest/{0}_test_details.xml'.format(test_name))
137 cmd.append('--gtest_output=xml:{0}'.format(log_output_path))
139 cmd.append('--gtest_filter=%s' % test_filter)
143 # path is relative to Android build top
144 def build_target(target, num_tasks):
145 ANDROID_BUILD_TOP = get_android_root_or_die()
146 build_cmd = [SOONG_UI_BASH, '--make-mode']
148 build_cmd.append('-j' + str(num_tasks))
149 build_cmd.append(target)
150 p = subprocess.Popen(
151 build_cmd, cwd=ANDROID_BUILD_TOP, env=os.environ.copy())
152 return_code = p.wait()
154 print 'BUILD FAILED, return code: {0}'.format(str(return_code))
160 """ run_host_unit_tests.py - Run registered host based unit tests
162 parser = argparse.ArgumentParser(description='Run host based unit tests.')
171 'Whether to output structured XML log output in out/dist/gtest directory'
180 help='Number of tasks to run at the same time')
183 nargs=argparse.REMAINDER,
184 help='-- args, other gtest arguments for each individual test')
185 args = parser.parse_args()
187 build_target('MODULES-IN-system-bt', args.num_tasks)
188 TEST_ROOT = get_native_test_root_or_die()
190 for test in HOST_TESTS:
191 test_cmd = get_test_cmd_or_die(TEST_ROOT, test, args.enable_xml,
193 if subprocess.call(test_cmd) != 0:
194 test_results.append(False)
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]
202 print 'TEST PASSED ' + str(len(test_results)) + ' tests were run'
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')
209 os.path.join(cmd_path, 'gen_coverage.py'),
220 if __name__ == '__main__':