1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*a65addddSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. All Rights Reserved. 3*a65addddSAndroid Build Coastguard Worker# 4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*a65addddSAndroid Build Coastguard Worker# 8*a65addddSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*a65addddSAndroid Build Coastguard Worker# 10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS, 12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*a65addddSAndroid Build Coastguard Worker# limitations under the License. 15*a65addddSAndroid Build Coastguard Worker 16*a65addddSAndroid Build Coastguard Workerimport os 17*a65addddSAndroid Build Coastguard Workerimport tempfile 18*a65addddSAndroid Build Coastguard Workerimport unittest 19*a65addddSAndroid Build Coastguard Workerimport textwrap 20*a65addddSAndroid Build Coastguard Workerimport re 21*a65addddSAndroid Build Coastguard Workerimport sys 22*a65addddSAndroid Build Coastguard Workerimport shlex 23*a65addddSAndroid Build Coastguard Worker 24*a65addddSAndroid Build Coastguard Workerimport itertools 25*a65addddSAndroid Build Coastguard Worker 26*a65addddSAndroid Build Coastguard Workerimport subprocess 27*a65addddSAndroid Build Coastguard Worker 28*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized 29*a65addddSAndroid Build Coastguard Worker 30*a65addddSAndroid Build Coastguard Workerfrom fruit_test_config import * 31*a65addddSAndroid Build Coastguard Worker 32*a65addddSAndroid Build Coastguard Workerfrom absl.testing import absltest 33*a65addddSAndroid Build Coastguard Worker 34*a65addddSAndroid Build Coastguard Workerrun_under_valgrind = RUN_TESTS_UNDER_VALGRIND.lower() not in ('false', 'off', 'no', '0', '') 35*a65addddSAndroid Build Coastguard Worker 36*a65addddSAndroid Build Coastguard Workerdef pretty_print_command(command, env): 37*a65addddSAndroid Build Coastguard Worker return 'cd %s; env -i %s %s' % ( 38*a65addddSAndroid Build Coastguard Worker shlex.quote(os.getcwd()), 39*a65addddSAndroid Build Coastguard Worker ' '.join('%s=%s' % (var_name, shlex.quote(value)) for var_name, value in env.items() if var_name != 'PWD'), 40*a65addddSAndroid Build Coastguard Worker ' '.join(shlex.quote(x) for x in command)) 41*a65addddSAndroid Build Coastguard Worker 42*a65addddSAndroid Build Coastguard Workerdef multiple_parameters(*param_lists): 43*a65addddSAndroid Build Coastguard Worker param_lists = [[params if isinstance(params, tuple) else (params,) 44*a65addddSAndroid Build Coastguard Worker for params in param_list] 45*a65addddSAndroid Build Coastguard Worker for param_list in param_lists] 46*a65addddSAndroid Build Coastguard Worker result = param_lists[0] 47*a65addddSAndroid Build Coastguard Worker for param_list in param_lists[1:]: 48*a65addddSAndroid Build Coastguard Worker result = [(*args1, *args2) 49*a65addddSAndroid Build Coastguard Worker for args1 in result 50*a65addddSAndroid Build Coastguard Worker for args2 in param_list] 51*a65addddSAndroid Build Coastguard Worker return parameterized.parameters(*result) 52*a65addddSAndroid Build Coastguard Worker 53*a65addddSAndroid Build Coastguard Workerdef multiple_named_parameters(*param_lists): 54*a65addddSAndroid Build Coastguard Worker result = param_lists[0] 55*a65addddSAndroid Build Coastguard Worker for param_list in param_lists[1:]: 56*a65addddSAndroid Build Coastguard Worker result = [(name1 + ', ' + name2, *args1, *args2) 57*a65addddSAndroid Build Coastguard Worker for name1, *args1 in result 58*a65addddSAndroid Build Coastguard Worker for name2, *args2 in param_list] 59*a65addddSAndroid Build Coastguard Worker return parameterized.named_parameters(*result) 60*a65addddSAndroid Build Coastguard Worker 61*a65addddSAndroid Build Coastguard Workerclass CommandFailedException(Exception): 62*a65addddSAndroid Build Coastguard Worker def __init__(self, command, env, stdout, stderr, error_code): 63*a65addddSAndroid Build Coastguard Worker self.command = command 64*a65addddSAndroid Build Coastguard Worker self.env = env 65*a65addddSAndroid Build Coastguard Worker self.stdout = stdout 66*a65addddSAndroid Build Coastguard Worker self.stderr = stderr 67*a65addddSAndroid Build Coastguard Worker self.error_code = error_code 68*a65addddSAndroid Build Coastguard Worker 69*a65addddSAndroid Build Coastguard Worker def __str__(self): 70*a65addddSAndroid Build Coastguard Worker return textwrap.dedent('''\ 71*a65addddSAndroid Build Coastguard Worker Ran command: {command} 72*a65addddSAndroid Build Coastguard Worker Exit code {error_code} 73*a65addddSAndroid Build Coastguard Worker Stdout: 74*a65addddSAndroid Build Coastguard Worker {stdout} 75*a65addddSAndroid Build Coastguard Worker 76*a65addddSAndroid Build Coastguard Worker Stderr: 77*a65addddSAndroid Build Coastguard Worker {stderr} 78*a65addddSAndroid Build Coastguard Worker ''').format(command=pretty_print_command(self.command, self.env), error_code=self.error_code, stdout=self.stdout, stderr=self.stderr) 79*a65addddSAndroid Build Coastguard Worker 80*a65addddSAndroid Build Coastguard Workerdef run_command(executable, args=[], modify_env=lambda env: env): 81*a65addddSAndroid Build Coastguard Worker command = [executable] + args 82*a65addddSAndroid Build Coastguard Worker modified_env = modify_env(os.environ) 83*a65addddSAndroid Build Coastguard Worker print('Executing command:', pretty_print_command(command, modified_env)) 84*a65addddSAndroid Build Coastguard Worker try: 85*a65addddSAndroid Build Coastguard Worker p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=modified_env) 86*a65addddSAndroid Build Coastguard Worker (stdout, stderr) = p.communicate() 87*a65addddSAndroid Build Coastguard Worker except Exception as e: 88*a65addddSAndroid Build Coastguard Worker raise Exception("While executing: %s" % command) 89*a65addddSAndroid Build Coastguard Worker if p.returncode != 0: 90*a65addddSAndroid Build Coastguard Worker raise CommandFailedException(command, modified_env, stdout, stderr, p.returncode) 91*a65addddSAndroid Build Coastguard Worker print('Execution successful.') 92*a65addddSAndroid Build Coastguard Worker print('stdout:') 93*a65addddSAndroid Build Coastguard Worker print(stdout) 94*a65addddSAndroid Build Coastguard Worker print('') 95*a65addddSAndroid Build Coastguard Worker print('stderr:') 96*a65addddSAndroid Build Coastguard Worker print(stderr) 97*a65addddSAndroid Build Coastguard Worker print('') 98*a65addddSAndroid Build Coastguard Worker return (stdout, stderr) 99*a65addddSAndroid Build Coastguard Worker 100*a65addddSAndroid Build Coastguard Workerdef run_compiled_executable(executable): 101*a65addddSAndroid Build Coastguard Worker if run_under_valgrind: 102*a65addddSAndroid Build Coastguard Worker args = VALGRIND_FLAGS.split() + [executable] 103*a65addddSAndroid Build Coastguard Worker run_command('valgrind', args = args, modify_env = modify_env_for_compiled_executables) 104*a65addddSAndroid Build Coastguard Worker else: 105*a65addddSAndroid Build Coastguard Worker run_command(executable, modify_env = modify_env_for_compiled_executables) 106*a65addddSAndroid Build Coastguard Worker 107*a65addddSAndroid Build Coastguard Workerclass CompilationFailedException(Exception): 108*a65addddSAndroid Build Coastguard Worker def __init__(self, command, env, error_message): 109*a65addddSAndroid Build Coastguard Worker self.command = command 110*a65addddSAndroid Build Coastguard Worker self.env = env 111*a65addddSAndroid Build Coastguard Worker self.error_message = error_message 112*a65addddSAndroid Build Coastguard Worker 113*a65addddSAndroid Build Coastguard Worker def __str__(self): 114*a65addddSAndroid Build Coastguard Worker return textwrap.dedent('''\ 115*a65addddSAndroid Build Coastguard Worker Ran command: {command} 116*a65addddSAndroid Build Coastguard Worker Error message: 117*a65addddSAndroid Build Coastguard Worker {error_message} 118*a65addddSAndroid Build Coastguard Worker ''').format(command=pretty_print_command(self.command, self.env), error_message=self.error_message) 119*a65addddSAndroid Build Coastguard Worker 120*a65addddSAndroid Build Coastguard Workerclass PosixCompiler: 121*a65addddSAndroid Build Coastguard Worker def __init__(self): 122*a65addddSAndroid Build Coastguard Worker self.executable = CXX 123*a65addddSAndroid Build Coastguard Worker self.name = CXX_COMPILER_NAME 124*a65addddSAndroid Build Coastguard Worker 125*a65addddSAndroid Build Coastguard Worker def compile_discarding_output(self, source, include_dirs, args=[]): 126*a65addddSAndroid Build Coastguard Worker try: 127*a65addddSAndroid Build Coastguard Worker args = args + ['-c', source, '-o', os.path.devnull] 128*a65addddSAndroid Build Coastguard Worker self._compile(include_dirs, args=args) 129*a65addddSAndroid Build Coastguard Worker except CommandFailedException as e: 130*a65addddSAndroid Build Coastguard Worker raise CompilationFailedException(e.command, e.env, e.stderr) 131*a65addddSAndroid Build Coastguard Worker 132*a65addddSAndroid Build Coastguard Worker def compile_and_link(self, source, include_dirs, output_file_name, args=[]): 133*a65addddSAndroid Build Coastguard Worker self._compile( 134*a65addddSAndroid Build Coastguard Worker include_dirs, 135*a65addddSAndroid Build Coastguard Worker args = ( 136*a65addddSAndroid Build Coastguard Worker [source] 137*a65addddSAndroid Build Coastguard Worker + ADDITIONAL_LINKER_FLAGS.split() 138*a65addddSAndroid Build Coastguard Worker + args 139*a65addddSAndroid Build Coastguard Worker + ['-o', output_file_name] 140*a65addddSAndroid Build Coastguard Worker )) 141*a65addddSAndroid Build Coastguard Worker 142*a65addddSAndroid Build Coastguard Worker def _compile(self, include_dirs, args): 143*a65addddSAndroid Build Coastguard Worker include_flags = ['-I%s' % include_dir for include_dir in include_dirs] 144*a65addddSAndroid Build Coastguard Worker args = ( 145*a65addddSAndroid Build Coastguard Worker FRUIT_TEST_COMPILE_FLAGS.split() 146*a65addddSAndroid Build Coastguard Worker + include_flags 147*a65addddSAndroid Build Coastguard Worker + ['-g0', '-Werror'] 148*a65addddSAndroid Build Coastguard Worker + args 149*a65addddSAndroid Build Coastguard Worker ) 150*a65addddSAndroid Build Coastguard Worker run_command(self.executable, args) 151*a65addddSAndroid Build Coastguard Worker 152*a65addddSAndroid Build Coastguard Worker def get_disable_deprecation_warning_flags(self): 153*a65addddSAndroid Build Coastguard Worker return ['-Wno-deprecated-declarations'] 154*a65addddSAndroid Build Coastguard Worker 155*a65addddSAndroid Build Coastguard Worker def get_disable_all_warnings_flags(self): 156*a65addddSAndroid Build Coastguard Worker return ['-Wno-error'] 157*a65addddSAndroid Build Coastguard Worker 158*a65addddSAndroid Build Coastguard Workerclass MsvcCompiler: 159*a65addddSAndroid Build Coastguard Worker def __init__(self): 160*a65addddSAndroid Build Coastguard Worker self.executable = CXX 161*a65addddSAndroid Build Coastguard Worker self.name = CXX_COMPILER_NAME 162*a65addddSAndroid Build Coastguard Worker 163*a65addddSAndroid Build Coastguard Worker def compile_discarding_output(self, source, include_dirs, args=[]): 164*a65addddSAndroid Build Coastguard Worker try: 165*a65addddSAndroid Build Coastguard Worker args = args + ['/c', source] 166*a65addddSAndroid Build Coastguard Worker self._compile(include_dirs, args = args) 167*a65addddSAndroid Build Coastguard Worker except CommandFailedException as e: 168*a65addddSAndroid Build Coastguard Worker # Note that we use stdout here, unlike above. MSVC reports compilation warnings and errors on stdout. 169*a65addddSAndroid Build Coastguard Worker raise CompilationFailedException(e.command, e.env, e.stdout) 170*a65addddSAndroid Build Coastguard Worker 171*a65addddSAndroid Build Coastguard Worker def compile_and_link(self, source, include_dirs, output_file_name, args=[]): 172*a65addddSAndroid Build Coastguard Worker self._compile( 173*a65addddSAndroid Build Coastguard Worker include_dirs, 174*a65addddSAndroid Build Coastguard Worker args = ( 175*a65addddSAndroid Build Coastguard Worker [source] 176*a65addddSAndroid Build Coastguard Worker + ADDITIONAL_LINKER_FLAGS.split() 177*a65addddSAndroid Build Coastguard Worker + args 178*a65addddSAndroid Build Coastguard Worker + ['/Fe' + output_file_name] 179*a65addddSAndroid Build Coastguard Worker )) 180*a65addddSAndroid Build Coastguard Worker 181*a65addddSAndroid Build Coastguard Worker def _compile(self, include_dirs, args): 182*a65addddSAndroid Build Coastguard Worker include_flags = ['-I%s' % include_dir for include_dir in include_dirs] 183*a65addddSAndroid Build Coastguard Worker args = ( 184*a65addddSAndroid Build Coastguard Worker FRUIT_TEST_COMPILE_FLAGS.split() 185*a65addddSAndroid Build Coastguard Worker + include_flags 186*a65addddSAndroid Build Coastguard Worker + ['/WX'] 187*a65addddSAndroid Build Coastguard Worker + args 188*a65addddSAndroid Build Coastguard Worker ) 189*a65addddSAndroid Build Coastguard Worker run_command(self.executable, args) 190*a65addddSAndroid Build Coastguard Worker 191*a65addddSAndroid Build Coastguard Worker def get_disable_deprecation_warning_flags(self): 192*a65addddSAndroid Build Coastguard Worker return ['/wd4996'] 193*a65addddSAndroid Build Coastguard Worker 194*a65addddSAndroid Build Coastguard Worker def get_disable_all_warnings_flags(self): 195*a65addddSAndroid Build Coastguard Worker return ['/WX:NO'] 196*a65addddSAndroid Build Coastguard Worker 197*a65addddSAndroid Build Coastguard Workerif CXX_COMPILER_NAME == 'MSVC': 198*a65addddSAndroid Build Coastguard Worker compiler = MsvcCompiler() 199*a65addddSAndroid Build Coastguard Worker if PATH_TO_COMPILED_FRUIT_LIB.endswith('.dll'): 200*a65addddSAndroid Build Coastguard Worker path_to_fruit_lib = PATH_TO_COMPILED_FRUIT_LIB[:-4] + '.lib' 201*a65addddSAndroid Build Coastguard Worker else: 202*a65addddSAndroid Build Coastguard Worker path_to_fruit_lib = PATH_TO_COMPILED_FRUIT_LIB 203*a65addddSAndroid Build Coastguard Worker if PATH_TO_COMPILED_TEST_HEADERS_LIB.endswith('.dll'): 204*a65addddSAndroid Build Coastguard Worker path_to_test_headers_lib = PATH_TO_COMPILED_TEST_HEADERS_LIB[:-4] + '.lib' 205*a65addddSAndroid Build Coastguard Worker else: 206*a65addddSAndroid Build Coastguard Worker path_to_test_headers_lib = PATH_TO_COMPILED_TEST_HEADERS_LIB 207*a65addddSAndroid Build Coastguard Worker fruit_tests_linker_flags = [path_to_fruit_lib, path_to_test_headers_lib] 208*a65addddSAndroid Build Coastguard Worker fruit_error_message_extraction_regex = 'error C2338: (.*)' 209*a65addddSAndroid Build Coastguard Workerelse: 210*a65addddSAndroid Build Coastguard Worker compiler = PosixCompiler() 211*a65addddSAndroid Build Coastguard Worker fruit_tests_linker_flags = [ 212*a65addddSAndroid Build Coastguard Worker '-lfruit', 213*a65addddSAndroid Build Coastguard Worker '-ltest_headers_copy', 214*a65addddSAndroid Build Coastguard Worker '-L' + PATH_TO_COMPILED_FRUIT, 215*a65addddSAndroid Build Coastguard Worker '-Wl,-rpath,' + PATH_TO_COMPILED_FRUIT, 216*a65addddSAndroid Build Coastguard Worker '-L' + PATH_TO_COMPILED_TEST_HEADERS, 217*a65addddSAndroid Build Coastguard Worker '-Wl,-rpath,' + PATH_TO_COMPILED_TEST_HEADERS, 218*a65addddSAndroid Build Coastguard Worker ] 219*a65addddSAndroid Build Coastguard Worker fruit_error_message_extraction_regex = 'static.assert(.*)' 220*a65addddSAndroid Build Coastguard Worker 221*a65addddSAndroid Build Coastguard Workerfruit_tests_include_dirs = ADDITIONAL_INCLUDE_DIRS.splitlines() + [ 222*a65addddSAndroid Build Coastguard Worker PATH_TO_FRUIT_TEST_HEADERS, 223*a65addddSAndroid Build Coastguard Worker PATH_TO_FRUIT_STATIC_HEADERS, 224*a65addddSAndroid Build Coastguard Worker PATH_TO_FRUIT_GENERATED_HEADERS, 225*a65addddSAndroid Build Coastguard Worker] 226*a65addddSAndroid Build Coastguard Worker 227*a65addddSAndroid Build Coastguard Worker_assert_helper = unittest.TestCase() 228*a65addddSAndroid Build Coastguard Worker 229*a65addddSAndroid Build Coastguard Workerdef modify_env_for_compiled_executables(env): 230*a65addddSAndroid Build Coastguard Worker env = env.copy() 231*a65addddSAndroid Build Coastguard Worker path_to_fruit_lib_dir = os.path.dirname(PATH_TO_COMPILED_FRUIT_LIB) 232*a65addddSAndroid Build Coastguard Worker path_to_fruit_test_headers_dir = os.path.dirname(PATH_TO_COMPILED_TEST_HEADERS_LIB) 233*a65addddSAndroid Build Coastguard Worker print('PATH_TO_COMPILED_FRUIT_LIB:', PATH_TO_COMPILED_FRUIT_LIB) 234*a65addddSAndroid Build Coastguard Worker print('PATH_TO_COMPILED_TEST_HEADERS_LIB:', PATH_TO_COMPILED_TEST_HEADERS_LIB) 235*a65addddSAndroid Build Coastguard Worker print('Adding directory to PATH:', path_to_fruit_lib_dir) 236*a65addddSAndroid Build Coastguard Worker print('Adding directory to PATH:', path_to_fruit_test_headers_dir) 237*a65addddSAndroid Build Coastguard Worker env["PATH"] += os.pathsep + path_to_fruit_lib_dir + os.pathsep + path_to_fruit_test_headers_dir 238*a65addddSAndroid Build Coastguard Worker return env 239*a65addddSAndroid Build Coastguard Worker 240*a65addddSAndroid Build Coastguard Workerdef _create_temporary_file(file_content, file_name_suffix=''): 241*a65addddSAndroid Build Coastguard Worker file_descriptor, file_name = tempfile.mkstemp(text=True, suffix=file_name_suffix) 242*a65addddSAndroid Build Coastguard Worker file = os.fdopen(file_descriptor, mode='w') 243*a65addddSAndroid Build Coastguard Worker file.write(file_content) 244*a65addddSAndroid Build Coastguard Worker file.close() 245*a65addddSAndroid Build Coastguard Worker return file_name 246*a65addddSAndroid Build Coastguard Worker 247*a65addddSAndroid Build Coastguard Workerdef _cap_to_lines(s, n): 248*a65addddSAndroid Build Coastguard Worker lines = s.splitlines() 249*a65addddSAndroid Build Coastguard Worker if len(lines) <= n: 250*a65addddSAndroid Build Coastguard Worker return s 251*a65addddSAndroid Build Coastguard Worker else: 252*a65addddSAndroid Build Coastguard Worker return '\n'.join(lines[0:n] + ['...']) 253*a65addddSAndroid Build Coastguard Worker 254*a65addddSAndroid Build Coastguard Workerdef _replace_using_test_params(s, test_params): 255*a65addddSAndroid Build Coastguard Worker for var_name, value in test_params.items(): 256*a65addddSAndroid Build Coastguard Worker if isinstance(value, str): 257*a65addddSAndroid Build Coastguard Worker s = re.sub(r'\b%s\b' % var_name, value, s) 258*a65addddSAndroid Build Coastguard Worker return s 259*a65addddSAndroid Build Coastguard Worker 260*a65addddSAndroid Build Coastguard Workerdef _construct_final_source_code(setup_source_code, source_code, test_params): 261*a65addddSAndroid Build Coastguard Worker setup_source_code = textwrap.dedent(setup_source_code) 262*a65addddSAndroid Build Coastguard Worker source_code = textwrap.dedent(source_code) 263*a65addddSAndroid Build Coastguard Worker source_code = _replace_using_test_params(source_code, test_params) 264*a65addddSAndroid Build Coastguard Worker return setup_source_code + source_code 265*a65addddSAndroid Build Coastguard Worker 266*a65addddSAndroid Build Coastguard Workerdef try_remove_temporary_file(filename): 267*a65addddSAndroid Build Coastguard Worker try: 268*a65addddSAndroid Build Coastguard Worker os.remove(filename) 269*a65addddSAndroid Build Coastguard Worker except: 270*a65addddSAndroid Build Coastguard Worker # When running Fruit tests on Windows using Appveyor, the remove command fails for temporary files sometimes. 271*a65addddSAndroid Build Coastguard Worker # This shouldn't cause the tests to fail, so we ignore the exception and go ahead. 272*a65addddSAndroid Build Coastguard Worker pass 273*a65addddSAndroid Build Coastguard Worker 274*a65addddSAndroid Build Coastguard Workerdef normalize_error_message_lines(lines): 275*a65addddSAndroid Build Coastguard Worker # Different compilers output a different number of spaces when pretty-printing types. 276*a65addddSAndroid Build Coastguard Worker # When using libc++, sometimes std::foo identifiers are reported as std::__1::foo. 277*a65addddSAndroid Build Coastguard Worker return [line.replace(' ', '').replace('std::__1::', 'std::') for line in lines] 278*a65addddSAndroid Build Coastguard Worker 279*a65addddSAndroid Build Coastguard Workerdef expect_compile_error_helper( 280*a65addddSAndroid Build Coastguard Worker check_error_fun, 281*a65addddSAndroid Build Coastguard Worker setup_source_code, 282*a65addddSAndroid Build Coastguard Worker source_code, 283*a65addddSAndroid Build Coastguard Worker test_params={}, 284*a65addddSAndroid Build Coastguard Worker ignore_deprecation_warnings=False, 285*a65addddSAndroid Build Coastguard Worker ignore_warnings=False): 286*a65addddSAndroid Build Coastguard Worker source_code = _construct_final_source_code(setup_source_code, source_code, test_params) 287*a65addddSAndroid Build Coastguard Worker 288*a65addddSAndroid Build Coastguard Worker source_file_name = _create_temporary_file(source_code, file_name_suffix='.cpp') 289*a65addddSAndroid Build Coastguard Worker 290*a65addddSAndroid Build Coastguard Worker try: 291*a65addddSAndroid Build Coastguard Worker args = [] 292*a65addddSAndroid Build Coastguard Worker if ignore_deprecation_warnings: 293*a65addddSAndroid Build Coastguard Worker args += compiler.get_disable_deprecation_warning_flags() 294*a65addddSAndroid Build Coastguard Worker if ignore_warnings: 295*a65addddSAndroid Build Coastguard Worker args += compiler.get_disable_all_warnings_flags() 296*a65addddSAndroid Build Coastguard Worker if ENABLE_COVERAGE: 297*a65addddSAndroid Build Coastguard Worker # When collecting coverage these arguments are enabled by default; however we must disable them in tests 298*a65addddSAndroid Build Coastguard Worker # expected to fail at compile-time because GCC would otherwise fail with an error like: 299*a65addddSAndroid Build Coastguard Worker # /tmp/tmp4m22cey7.cpp:1:0: error: cannot open /dev/null.gcno 300*a65addddSAndroid Build Coastguard Worker args += ['-fno-profile-arcs', '-fno-test-coverage'] 301*a65addddSAndroid Build Coastguard Worker compiler.compile_discarding_output( 302*a65addddSAndroid Build Coastguard Worker source=source_file_name, 303*a65addddSAndroid Build Coastguard Worker include_dirs=fruit_tests_include_dirs, 304*a65addddSAndroid Build Coastguard Worker args=args) 305*a65addddSAndroid Build Coastguard Worker raise Exception('The test should have failed to compile, but it compiled successfully') 306*a65addddSAndroid Build Coastguard Worker except CompilationFailedException as e1: 307*a65addddSAndroid Build Coastguard Worker e = e1 308*a65addddSAndroid Build Coastguard Worker 309*a65addddSAndroid Build Coastguard Worker error_message = e.error_message 310*a65addddSAndroid Build Coastguard Worker error_message_lines = error_message.splitlines() 311*a65addddSAndroid Build Coastguard Worker error_message_head = _cap_to_lines(error_message, 40) 312*a65addddSAndroid Build Coastguard Worker 313*a65addddSAndroid Build Coastguard Worker check_error_fun(e, error_message_lines, error_message_head) 314*a65addddSAndroid Build Coastguard Worker 315*a65addddSAndroid Build Coastguard Worker try_remove_temporary_file(source_file_name) 316*a65addddSAndroid Build Coastguard Worker 317*a65addddSAndroid Build Coastguard Workerdef apply_any_error_context_replacements(error_string, following_lines): 318*a65addddSAndroid Build Coastguard Worker if CXX_COMPILER_NAME == 'MSVC': 319*a65addddSAndroid Build Coastguard Worker # MSVC errors are of the form: 320*a65addddSAndroid Build Coastguard Worker # 321*a65addddSAndroid Build Coastguard Worker # C:\Path\To\header\foo.h(59): note: see reference to class template instantiation 'fruit::impl::NoBindingFoundError<fruit::Annotated<Annotation,U>>' being compiled 322*a65addddSAndroid Build Coastguard Worker # with 323*a65addddSAndroid Build Coastguard Worker # [ 324*a65addddSAndroid Build Coastguard Worker # Annotation=Annotation1, 325*a65addddSAndroid Build Coastguard Worker # U=std::function<std::unique_ptr<ScalerImpl,std::default_delete<ScalerImpl>> (double)> 326*a65addddSAndroid Build Coastguard Worker # ] 327*a65addddSAndroid Build Coastguard Worker # 328*a65addddSAndroid Build Coastguard Worker # So we need to parse the following few lines and use them to replace the placeholder types in the Fruit error type. 329*a65addddSAndroid Build Coastguard Worker replacement_lines = [] 330*a65addddSAndroid Build Coastguard Worker if len(following_lines) >= 4 and following_lines[0].strip() == 'with': 331*a65addddSAndroid Build Coastguard Worker assert following_lines[1].strip() == '[', 'Line was: ' + following_lines[1] 332*a65addddSAndroid Build Coastguard Worker for line in itertools.islice(following_lines, 2, None): 333*a65addddSAndroid Build Coastguard Worker line = line.strip() 334*a65addddSAndroid Build Coastguard Worker if line == ']': 335*a65addddSAndroid Build Coastguard Worker break 336*a65addddSAndroid Build Coastguard Worker if line.endswith(','): 337*a65addddSAndroid Build Coastguard Worker line = line[:-1] 338*a65addddSAndroid Build Coastguard Worker replacement_lines.append(line) 339*a65addddSAndroid Build Coastguard Worker 340*a65addddSAndroid Build Coastguard Worker for replacement_line in replacement_lines: 341*a65addddSAndroid Build Coastguard Worker match = re.search('([A-Za-z0-9_-]*)=(.*)', replacement_line) 342*a65addddSAndroid Build Coastguard Worker if not match: 343*a65addddSAndroid Build Coastguard Worker raise Exception('Failed to parse replacement line: %s' % replacement_line) 344*a65addddSAndroid Build Coastguard Worker (type_variable, type_expression) = match.groups() 345*a65addddSAndroid Build Coastguard Worker error_string = re.sub(r'\b' + type_variable + r'\b', type_expression, error_string) 346*a65addddSAndroid Build Coastguard Worker return error_string 347*a65addddSAndroid Build Coastguard Worker 348*a65addddSAndroid Build Coastguard Workerdef expect_generic_compile_error(expected_error_regex, setup_source_code, source_code, test_params={}): 349*a65addddSAndroid Build Coastguard Worker """ 350*a65addddSAndroid Build Coastguard Worker Tests that the given source produces the expected error during compilation. 351*a65addddSAndroid Build Coastguard Worker 352*a65addddSAndroid Build Coastguard Worker :param expected_fruit_error_regex: A regex used to match the Fruit error type, 353*a65addddSAndroid Build Coastguard Worker e.g. 'NoBindingFoundForAbstractClassError<ScalerImpl>'. 354*a65addddSAndroid Build Coastguard Worker Any identifiers contained in the regex will be replaced using test_params (where a replacement is defined). 355*a65addddSAndroid Build Coastguard Worker :param expected_fruit_error_desc_regex: A regex used to match the Fruit error description, 356*a65addddSAndroid Build Coastguard Worker e.g. 'No explicit binding was found for C, and C is an abstract class'. 357*a65addddSAndroid Build Coastguard Worker :param setup_source_code: The first part of the source code. This is dedented separately from source_code and it's 358*a65addddSAndroid Build Coastguard Worker *not* subject to test_params, unlike source_code. 359*a65addddSAndroid Build Coastguard Worker :param source_code: The second part of the source code. Any identifiers will be replaced using test_params 360*a65addddSAndroid Build Coastguard Worker (where a replacement is defined). This will be dedented. 361*a65addddSAndroid Build Coastguard Worker :param test_params: A dict containing the definition of some identifiers. Each identifier in 362*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex and source_code will be replaced (textually) with its definition (if a definition 363*a65addddSAndroid Build Coastguard Worker was provided). 364*a65addddSAndroid Build Coastguard Worker """ 365*a65addddSAndroid Build Coastguard Worker 366*a65addddSAndroid Build Coastguard Worker expected_error_regex = _replace_using_test_params(expected_error_regex, test_params) 367*a65addddSAndroid Build Coastguard Worker expected_error_regex = expected_error_regex.replace(' ', '') 368*a65addddSAndroid Build Coastguard Worker 369*a65addddSAndroid Build Coastguard Worker def check_error(e, error_message_lines, error_message_head): 370*a65addddSAndroid Build Coastguard Worker error_message_lines_with_replacements = [ 371*a65addddSAndroid Build Coastguard Worker apply_any_error_context_replacements(line, error_message_lines[line_number + 1:]) 372*a65addddSAndroid Build Coastguard Worker for line_number, line in enumerate(error_message_lines)] 373*a65addddSAndroid Build Coastguard Worker 374*a65addddSAndroid Build Coastguard Worker normalized_error_message_lines = normalize_error_message_lines(error_message_lines_with_replacements) 375*a65addddSAndroid Build Coastguard Worker 376*a65addddSAndroid Build Coastguard Worker for line in normalized_error_message_lines: 377*a65addddSAndroid Build Coastguard Worker if re.search(expected_error_regex, line): 378*a65addddSAndroid Build Coastguard Worker return 379*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 380*a65addddSAndroid Build Coastguard Worker Expected error {expected_error} but the compiler output did not contain that. 381*a65addddSAndroid Build Coastguard Worker Compiler command line: {compiler_command} 382*a65addddSAndroid Build Coastguard Worker Error message was: 383*a65addddSAndroid Build Coastguard Worker {error_message} 384*a65addddSAndroid Build Coastguard Worker ''').format(expected_error = expected_error_regex, compiler_command=e.command, error_message = error_message_head)) 385*a65addddSAndroid Build Coastguard Worker 386*a65addddSAndroid Build Coastguard Worker expect_compile_error_helper(check_error, setup_source_code, source_code, test_params) 387*a65addddSAndroid Build Coastguard Worker 388*a65addddSAndroid Build Coastguard Workerdef expect_compile_error( 389*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex, 390*a65addddSAndroid Build Coastguard Worker expected_fruit_error_desc_regex, 391*a65addddSAndroid Build Coastguard Worker setup_source_code, 392*a65addddSAndroid Build Coastguard Worker source_code, 393*a65addddSAndroid Build Coastguard Worker test_params={}, 394*a65addddSAndroid Build Coastguard Worker ignore_deprecation_warnings=False, 395*a65addddSAndroid Build Coastguard Worker ignore_warnings=False, 396*a65addddSAndroid Build Coastguard Worker disable_error_line_number_check=False): 397*a65addddSAndroid Build Coastguard Worker """ 398*a65addddSAndroid Build Coastguard Worker Tests that the given source produces the expected error during compilation. 399*a65addddSAndroid Build Coastguard Worker 400*a65addddSAndroid Build Coastguard Worker :param expected_fruit_error_regex: A regex used to match the Fruit error type, 401*a65addddSAndroid Build Coastguard Worker e.g. 'NoBindingFoundForAbstractClassError<ScalerImpl>'. 402*a65addddSAndroid Build Coastguard Worker Any identifiers contained in the regex will be replaced using test_params (where a replacement is defined). 403*a65addddSAndroid Build Coastguard Worker :param expected_fruit_error_desc_regex: A regex used to match the Fruit error description, 404*a65addddSAndroid Build Coastguard Worker e.g. 'No explicit binding was found for C, and C is an abstract class'. 405*a65addddSAndroid Build Coastguard Worker :param setup_source_code: The first part of the source code. This is dedented separately from source_code and it's 406*a65addddSAndroid Build Coastguard Worker *not* subject to test_params, unlike source_code. 407*a65addddSAndroid Build Coastguard Worker :param source_code: The second part of the source code. Any identifiers will be replaced using test_params 408*a65addddSAndroid Build Coastguard Worker (where a replacement is defined). This will be dedented. 409*a65addddSAndroid Build Coastguard Worker :param test_params: A dict containing the definition of some identifiers. Each identifier in 410*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex and source_code will be replaced (textually) with its definition (if a definition 411*a65addddSAndroid Build Coastguard Worker was provided). 412*a65addddSAndroid Build Coastguard Worker :param ignore_deprecation_warnings: A boolean. If True, deprecation warnings will be ignored. 413*a65addddSAndroid Build Coastguard Worker :param ignore_warnings: A boolean. If True, all warnings will be ignored. 414*a65addddSAndroid Build Coastguard Worker :param disable_error_line_number_check: A boolean. If True, the test will not fail if there are other diagnostic 415*a65addddSAndroid Build Coastguard Worker lines before the expected error. 416*a65addddSAndroid Build Coastguard Worker """ 417*a65addddSAndroid Build Coastguard Worker if '\n' in expected_fruit_error_regex: 418*a65addddSAndroid Build Coastguard Worker raise Exception('expected_fruit_error_regex should not contain newlines') 419*a65addddSAndroid Build Coastguard Worker if '\n' in expected_fruit_error_desc_regex: 420*a65addddSAndroid Build Coastguard Worker raise Exception('expected_fruit_error_desc_regex should not contain newlines') 421*a65addddSAndroid Build Coastguard Worker 422*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex = _replace_using_test_params(expected_fruit_error_regex, test_params) 423*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex = expected_fruit_error_regex.replace(' ', '') 424*a65addddSAndroid Build Coastguard Worker 425*a65addddSAndroid Build Coastguard Worker def check_error(e, error_message_lines, error_message_head): 426*a65addddSAndroid Build Coastguard Worker normalized_error_message_lines = normalize_error_message_lines(error_message_lines) 427*a65addddSAndroid Build Coastguard Worker 428*a65addddSAndroid Build Coastguard Worker for line_number, line in enumerate(normalized_error_message_lines): 429*a65addddSAndroid Build Coastguard Worker match = re.search('fruit::impl::(.*Error<.*>)', line) 430*a65addddSAndroid Build Coastguard Worker if match: 431*a65addddSAndroid Build Coastguard Worker actual_fruit_error_line_number = line_number 432*a65addddSAndroid Build Coastguard Worker actual_fruit_error = match.groups()[0] 433*a65addddSAndroid Build Coastguard Worker actual_fruit_error = apply_any_error_context_replacements(actual_fruit_error, normalized_error_message_lines[line_number + 1:]) 434*a65addddSAndroid Build Coastguard Worker break 435*a65addddSAndroid Build Coastguard Worker else: 436*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 437*a65addddSAndroid Build Coastguard Worker Expected error {expected_error} but the compiler output did not contain user-facing Fruit errors. 438*a65addddSAndroid Build Coastguard Worker Compiler command line: {compiler_command} 439*a65addddSAndroid Build Coastguard Worker Error message was: 440*a65addddSAndroid Build Coastguard Worker {error_message} 441*a65addddSAndroid Build Coastguard Worker ''').format(expected_error = expected_fruit_error_regex, compiler_command = e.command, error_message = error_message_head)) 442*a65addddSAndroid Build Coastguard Worker 443*a65addddSAndroid Build Coastguard Worker for line_number, line in enumerate(error_message_lines): 444*a65addddSAndroid Build Coastguard Worker match = re.search(fruit_error_message_extraction_regex, line) 445*a65addddSAndroid Build Coastguard Worker if match: 446*a65addddSAndroid Build Coastguard Worker actual_static_assert_error_line_number = line_number 447*a65addddSAndroid Build Coastguard Worker actual_static_assert_error = match.groups()[0] 448*a65addddSAndroid Build Coastguard Worker break 449*a65addddSAndroid Build Coastguard Worker else: 450*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 451*a65addddSAndroid Build Coastguard Worker Expected error {expected_error} but the compiler output did not contain static_assert errors. 452*a65addddSAndroid Build Coastguard Worker Compiler command line: {compiler_command} 453*a65addddSAndroid Build Coastguard Worker Error message was: 454*a65addddSAndroid Build Coastguard Worker {error_message} 455*a65addddSAndroid Build Coastguard Worker ''').format(expected_error = expected_fruit_error_regex, compiler_command=e.command, error_message = error_message_head)) 456*a65addddSAndroid Build Coastguard Worker 457*a65addddSAndroid Build Coastguard Worker try: 458*a65addddSAndroid Build Coastguard Worker regex_search_result = re.search(expected_fruit_error_regex, actual_fruit_error) 459*a65addddSAndroid Build Coastguard Worker except Exception as e: 460*a65addddSAndroid Build Coastguard Worker raise Exception('re.search() failed for regex \'%s\'' % expected_fruit_error_regex) from e 461*a65addddSAndroid Build Coastguard Worker if not regex_search_result: 462*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 463*a65addddSAndroid Build Coastguard Worker The compilation failed as expected, but with a different error type. 464*a65addddSAndroid Build Coastguard Worker Expected Fruit error type: {expected_fruit_error_regex} 465*a65addddSAndroid Build Coastguard Worker Error type was: {actual_fruit_error} 466*a65addddSAndroid Build Coastguard Worker Expected static assert error: {expected_fruit_error_desc_regex} 467*a65addddSAndroid Build Coastguard Worker Static assert was: {actual_static_assert_error} 468*a65addddSAndroid Build Coastguard Worker Error message was: 469*a65addddSAndroid Build Coastguard Worker {error_message} 470*a65addddSAndroid Build Coastguard Worker '''.format( 471*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex = expected_fruit_error_regex, 472*a65addddSAndroid Build Coastguard Worker actual_fruit_error = actual_fruit_error, 473*a65addddSAndroid Build Coastguard Worker expected_fruit_error_desc_regex = expected_fruit_error_desc_regex, 474*a65addddSAndroid Build Coastguard Worker actual_static_assert_error = actual_static_assert_error, 475*a65addddSAndroid Build Coastguard Worker error_message = error_message_head))) 476*a65addddSAndroid Build Coastguard Worker try: 477*a65addddSAndroid Build Coastguard Worker regex_search_result = re.search(expected_fruit_error_desc_regex, actual_static_assert_error) 478*a65addddSAndroid Build Coastguard Worker except Exception as e: 479*a65addddSAndroid Build Coastguard Worker raise Exception('re.search() failed for regex \'%s\'' % expected_fruit_error_desc_regex) from e 480*a65addddSAndroid Build Coastguard Worker if not regex_search_result: 481*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 482*a65addddSAndroid Build Coastguard Worker The compilation failed as expected, but with a different error message. 483*a65addddSAndroid Build Coastguard Worker Expected Fruit error type: {expected_fruit_error_regex} 484*a65addddSAndroid Build Coastguard Worker Error type was: {actual_fruit_error} 485*a65addddSAndroid Build Coastguard Worker Expected static assert error: {expected_fruit_error_desc_regex} 486*a65addddSAndroid Build Coastguard Worker Static assert was: {actual_static_assert_error} 487*a65addddSAndroid Build Coastguard Worker Error message: 488*a65addddSAndroid Build Coastguard Worker {error_message} 489*a65addddSAndroid Build Coastguard Worker '''.format( 490*a65addddSAndroid Build Coastguard Worker expected_fruit_error_regex = expected_fruit_error_regex, 491*a65addddSAndroid Build Coastguard Worker actual_fruit_error = actual_fruit_error, 492*a65addddSAndroid Build Coastguard Worker expected_fruit_error_desc_regex = expected_fruit_error_desc_regex, 493*a65addddSAndroid Build Coastguard Worker actual_static_assert_error = actual_static_assert_error, 494*a65addddSAndroid Build Coastguard Worker error_message = error_message_head))) 495*a65addddSAndroid Build Coastguard Worker 496*a65addddSAndroid Build Coastguard Worker # 6 is just a constant that works for both g++ (<=6.0.0 at least) and clang++ (<=4.0.0 at least). 497*a65addddSAndroid Build Coastguard Worker # It might need to be changed. 498*a65addddSAndroid Build Coastguard Worker if not disable_error_line_number_check and (actual_fruit_error_line_number > 6 or actual_static_assert_error_line_number > 6): 499*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 500*a65addddSAndroid Build Coastguard Worker The compilation failed with the expected message, but the error message contained too many lines before the relevant ones. 501*a65addddSAndroid Build Coastguard Worker The error type was reported on line {actual_fruit_error_line_number} of the message (should be <=6). 502*a65addddSAndroid Build Coastguard Worker The static assert was reported on line {actual_static_assert_error_line_number} of the message (should be <=6). 503*a65addddSAndroid Build Coastguard Worker Error message: 504*a65addddSAndroid Build Coastguard Worker {error_message} 505*a65addddSAndroid Build Coastguard Worker '''.format( 506*a65addddSAndroid Build Coastguard Worker actual_fruit_error_line_number = actual_fruit_error_line_number, 507*a65addddSAndroid Build Coastguard Worker actual_static_assert_error_line_number = actual_static_assert_error_line_number, 508*a65addddSAndroid Build Coastguard Worker error_message = error_message_head))) 509*a65addddSAndroid Build Coastguard Worker 510*a65addddSAndroid Build Coastguard Worker for line in error_message_lines[:max(actual_fruit_error_line_number, actual_static_assert_error_line_number)]: 511*a65addddSAndroid Build Coastguard Worker if re.search('fruit::impl::meta', line): 512*a65addddSAndroid Build Coastguard Worker raise Exception( 513*a65addddSAndroid Build Coastguard Worker 'The compilation failed with the expected message, but the error message contained some metaprogramming types in the output (besides Error). Error message:\n%s' + error_message_head) 514*a65addddSAndroid Build Coastguard Worker 515*a65addddSAndroid Build Coastguard Worker expect_compile_error_helper(check_error, setup_source_code, source_code, test_params, ignore_deprecation_warnings, ignore_warnings) 516*a65addddSAndroid Build Coastguard Worker 517*a65addddSAndroid Build Coastguard Worker 518*a65addddSAndroid Build Coastguard Workerdef expect_runtime_error( 519*a65addddSAndroid Build Coastguard Worker expected_error_regex, 520*a65addddSAndroid Build Coastguard Worker setup_source_code, 521*a65addddSAndroid Build Coastguard Worker source_code, 522*a65addddSAndroid Build Coastguard Worker test_params={}, 523*a65addddSAndroid Build Coastguard Worker ignore_deprecation_warnings=False): 524*a65addddSAndroid Build Coastguard Worker """ 525*a65addddSAndroid Build Coastguard Worker Tests that the given source (compiles successfully and) produces the expected error at runtime. 526*a65addddSAndroid Build Coastguard Worker 527*a65addddSAndroid Build Coastguard Worker :param expected_error_regex: A regex used to match the content of stderr. 528*a65addddSAndroid Build Coastguard Worker Any identifiers contained in the regex will be replaced using test_params (where a replacement is defined). 529*a65addddSAndroid Build Coastguard Worker :param setup_source_code: The first part of the source code. This is dedented separately from source_code and it's 530*a65addddSAndroid Build Coastguard Worker *not* subject to test_params, unlike source_code. 531*a65addddSAndroid Build Coastguard Worker :param source_code: The second part of the source code. Any identifiers will be replaced using test_params 532*a65addddSAndroid Build Coastguard Worker (where a replacement is defined). This will be dedented. 533*a65addddSAndroid Build Coastguard Worker :param test_params: A dict containing the definition of some identifiers. Each identifier in 534*a65addddSAndroid Build Coastguard Worker expected_error_regex and source_code will be replaced (textually) with its definition (if a definition 535*a65addddSAndroid Build Coastguard Worker was provided). 536*a65addddSAndroid Build Coastguard Worker """ 537*a65addddSAndroid Build Coastguard Worker expected_error_regex = _replace_using_test_params(expected_error_regex, test_params) 538*a65addddSAndroid Build Coastguard Worker source_code = _construct_final_source_code(setup_source_code, source_code, test_params) 539*a65addddSAndroid Build Coastguard Worker 540*a65addddSAndroid Build Coastguard Worker source_file_name = _create_temporary_file(source_code, file_name_suffix='.cpp') 541*a65addddSAndroid Build Coastguard Worker executable_suffix = {'posix': '', 'nt': '.exe'}[os.name] 542*a65addddSAndroid Build Coastguard Worker output_file_name = _create_temporary_file('', executable_suffix) 543*a65addddSAndroid Build Coastguard Worker 544*a65addddSAndroid Build Coastguard Worker args = fruit_tests_linker_flags.copy() 545*a65addddSAndroid Build Coastguard Worker if ignore_deprecation_warnings: 546*a65addddSAndroid Build Coastguard Worker args += compiler.get_disable_deprecation_warning_flags() 547*a65addddSAndroid Build Coastguard Worker compiler.compile_and_link( 548*a65addddSAndroid Build Coastguard Worker source=source_file_name, 549*a65addddSAndroid Build Coastguard Worker include_dirs=fruit_tests_include_dirs, 550*a65addddSAndroid Build Coastguard Worker output_file_name=output_file_name, 551*a65addddSAndroid Build Coastguard Worker args=args) 552*a65addddSAndroid Build Coastguard Worker 553*a65addddSAndroid Build Coastguard Worker try: 554*a65addddSAndroid Build Coastguard Worker run_compiled_executable(output_file_name) 555*a65addddSAndroid Build Coastguard Worker raise Exception('The test should have failed at runtime, but it ran successfully') 556*a65addddSAndroid Build Coastguard Worker except CommandFailedException as e1: 557*a65addddSAndroid Build Coastguard Worker e = e1 558*a65addddSAndroid Build Coastguard Worker 559*a65addddSAndroid Build Coastguard Worker stderr = e.stderr 560*a65addddSAndroid Build Coastguard Worker stderr_head = _cap_to_lines(stderr, 40) 561*a65addddSAndroid Build Coastguard Worker 562*a65addddSAndroid Build Coastguard Worker if '\n' in expected_error_regex: 563*a65addddSAndroid Build Coastguard Worker regex_flags = re.MULTILINE 564*a65addddSAndroid Build Coastguard Worker else: 565*a65addddSAndroid Build Coastguard Worker regex_flags = 0 566*a65addddSAndroid Build Coastguard Worker 567*a65addddSAndroid Build Coastguard Worker try: 568*a65addddSAndroid Build Coastguard Worker regex_search_result = re.search(expected_error_regex, stderr, flags=regex_flags) 569*a65addddSAndroid Build Coastguard Worker except Exception as e: 570*a65addddSAndroid Build Coastguard Worker raise Exception('re.search() failed for regex \'%s\'' % expected_error_regex) from e 571*a65addddSAndroid Build Coastguard Worker if not regex_search_result: 572*a65addddSAndroid Build Coastguard Worker raise Exception(textwrap.dedent('''\ 573*a65addddSAndroid Build Coastguard Worker The test failed as expected, but with a different message. 574*a65addddSAndroid Build Coastguard Worker Expected: {expected_error_regex} 575*a65addddSAndroid Build Coastguard Worker Was: 576*a65addddSAndroid Build Coastguard Worker {stderr} 577*a65addddSAndroid Build Coastguard Worker '''.format(expected_error_regex = expected_error_regex, stderr = stderr_head))) 578*a65addddSAndroid Build Coastguard Worker 579*a65addddSAndroid Build Coastguard Worker # Note that we don't delete the temporary files if the test failed. This is intentional, keeping them around helps debugging the failure. 580*a65addddSAndroid Build Coastguard Worker if not ENABLE_COVERAGE: 581*a65addddSAndroid Build Coastguard Worker try_remove_temporary_file(source_file_name) 582*a65addddSAndroid Build Coastguard Worker try_remove_temporary_file(output_file_name) 583*a65addddSAndroid Build Coastguard Worker 584*a65addddSAndroid Build Coastguard Worker 585*a65addddSAndroid Build Coastguard Workerdef expect_success(setup_source_code, source_code, test_params={}, ignore_deprecation_warnings=False): 586*a65addddSAndroid Build Coastguard Worker """ 587*a65addddSAndroid Build Coastguard Worker Tests that the given source compiles and runs successfully. 588*a65addddSAndroid Build Coastguard Worker 589*a65addddSAndroid Build Coastguard Worker :param setup_source_code: The first part of the source code. This is dedented separately from source_code and it's 590*a65addddSAndroid Build Coastguard Worker *not* subject to test_params, unlike source_code. 591*a65addddSAndroid Build Coastguard Worker :param source_code: The second part of the source code. Any identifiers will be replaced using test_params 592*a65addddSAndroid Build Coastguard Worker (where a replacement is defined). This will be dedented. 593*a65addddSAndroid Build Coastguard Worker :param test_params: A dict containing the definition of some identifiers. Each identifier in 594*a65addddSAndroid Build Coastguard Worker source_code will be replaced (textually) with its definition (if a definition was provided). 595*a65addddSAndroid Build Coastguard Worker """ 596*a65addddSAndroid Build Coastguard Worker source_code = _construct_final_source_code(setup_source_code, source_code, test_params) 597*a65addddSAndroid Build Coastguard Worker 598*a65addddSAndroid Build Coastguard Worker if 'main(' not in source_code: 599*a65addddSAndroid Build Coastguard Worker source_code += textwrap.dedent(''' 600*a65addddSAndroid Build Coastguard Worker int main() { 601*a65addddSAndroid Build Coastguard Worker } 602*a65addddSAndroid Build Coastguard Worker ''') 603*a65addddSAndroid Build Coastguard Worker 604*a65addddSAndroid Build Coastguard Worker source_file_name = _create_temporary_file(source_code, file_name_suffix='.cpp') 605*a65addddSAndroid Build Coastguard Worker executable_suffix = {'posix': '', 'nt': '.exe'}[os.name] 606*a65addddSAndroid Build Coastguard Worker output_file_name = _create_temporary_file('', executable_suffix) 607*a65addddSAndroid Build Coastguard Worker 608*a65addddSAndroid Build Coastguard Worker args = fruit_tests_linker_flags.copy() 609*a65addddSAndroid Build Coastguard Worker if ignore_deprecation_warnings: 610*a65addddSAndroid Build Coastguard Worker args += compiler.get_disable_deprecation_warning_flags() 611*a65addddSAndroid Build Coastguard Worker compiler.compile_and_link( 612*a65addddSAndroid Build Coastguard Worker source=source_file_name, 613*a65addddSAndroid Build Coastguard Worker include_dirs=fruit_tests_include_dirs, 614*a65addddSAndroid Build Coastguard Worker output_file_name=output_file_name, 615*a65addddSAndroid Build Coastguard Worker args=args) 616*a65addddSAndroid Build Coastguard Worker 617*a65addddSAndroid Build Coastguard Worker run_compiled_executable(output_file_name) 618*a65addddSAndroid Build Coastguard Worker 619*a65addddSAndroid Build Coastguard Worker # Note that we don't delete the temporary files if the test failed. This is intentional, keeping them around helps debugging the failure. 620*a65addddSAndroid Build Coastguard Worker if not ENABLE_COVERAGE: 621*a65addddSAndroid Build Coastguard Worker try_remove_temporary_file(source_file_name) 622*a65addddSAndroid Build Coastguard Worker try_remove_temporary_file(output_file_name) 623*a65addddSAndroid Build Coastguard Worker 624*a65addddSAndroid Build Coastguard Worker 625*a65addddSAndroid Build Coastguard Worker# Note: this is not the main function of this file, it's meant to be used as main function from test_*.py files. 626*a65addddSAndroid Build Coastguard Workerdef main(): 627*a65addddSAndroid Build Coastguard Worker absltest.main(*sys.argv) 628