| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Implements a simple "negative compile" test for C++ on linux. | 6 """Implements a simple "negative compile" test for C++ on linux. |
| 7 | 7 |
| 8 Sometimes a C++ API needs to ensure that various usages cannot compile. To | 8 Sometimes a C++ API needs to ensure that various usages cannot compile. To |
| 9 enable unittesting of these assertions, we use this python script to | 9 enable unittesting of these assertions, we use this python script to |
| 10 invoke gcc on a source file and assert that compilation fails. | 10 invoke gcc on a source file and assert that compilation fails. |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 was aborted. If the test completed successfully, | 205 was aborted. If the test completed successfully, |
| 206 this value is 0. | 206 this value is 0. |
| 207 'finished_at': A timestamp in seconds since the epoch for when this | 207 'finished_at': A timestamp in seconds since the epoch for when this |
| 208 test was successfully complete. If the test is aborted, | 208 test was successfully complete. If the test is aborted, |
| 209 or running, this value is 0. | 209 or running, this value is 0. |
| 210 'expectations': A dictionary with the test expectations. See | 210 'expectations': A dictionary with the test expectations. See |
| 211 ParseExpectation() for the structure. | 211 ParseExpectation() for the structure. |
| 212 } | 212 } |
| 213 """ | 213 """ |
| 214 # TODO(ajwong): Get the compiler from gyp. | 214 # TODO(ajwong): Get the compiler from gyp. |
| 215 cmdline = [os.path.join(os.path.dirname(os.path.realpath(__file__)), | 215 llvm_path = os.path.join( |
| 216 '../third_party/llvm-build/Release+Asserts/bin', | 216 os.path.dirname(os.path.realpath(__file__)), |
| 217 'clang++')] | 217 '..', 'third_party', 'llvm-build', 'Release+Asserts', 'bin') |
| 218 if os.name == 'nt': |
| 219 clang = os.path.join(llvm_path, 'clang-cl.exe') |
| 220 else: |
| 221 clang = os.path.join(llvm_path, 'clang++') |
| 222 cmdline = [clang] |
| 218 cmdline.extend(shlex.split(cflags)) | 223 cmdline.extend(shlex.split(cflags)) |
| 219 name = config['name'] | 224 name = config['name'] |
| 220 expectations = config['expectations'] | 225 expectations = config['expectations'] |
| 221 if expectations is not None: | 226 if expectations is not None: |
| 222 cmdline.append('-D%s' % name) | 227 cmdline.append('-D%s' % name) |
| 223 cmdline.extend(['-std=c++11', '-o', '/dev/null', '-c', '-x', 'c++', | 228 if os.name == 'nt': |
| 224 sourcefile_path]) | 229 cmdline.extend(['/TP', '/c', sourcefile_path]) |
| 230 else: |
| 231 cmdline.extend(['-std=c++11', '-o', '/dev/null', '-c', '-x', 'c++', |
| 232 sourcefile_path]) |
| 225 | 233 |
| 226 process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, | 234 process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, |
| 227 stderr=subprocess.PIPE) | 235 stderr=subprocess.PIPE) |
| 228 now = time.time() | 236 now = time.time() |
| 229 return {'proc': process, | 237 return {'proc': process, |
| 230 'cmdline': ' '.join(cmdline), | 238 'cmdline': ' '.join(cmdline), |
| 231 'name': name, | 239 'name': name, |
| 232 'suite_name': config['suite_name'], | 240 'suite_name': config['suite_name'], |
| 233 'terminate_timeout': now + NCTEST_TERMINATE_TIMEOUT_SEC, | 241 'terminate_timeout': now + NCTEST_TERMINATE_TIMEOUT_SEC, |
| 234 'kill_timeout': now + NCTEST_KILL_TIMEOUT_SEC, | 242 'kill_timeout': now + NCTEST_KILL_TIMEOUT_SEC, |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 finished_tests = [] | 375 finished_tests = [] |
| 368 busy_loop_timeout = time.time() + BUSY_LOOP_MAX_TIME_SEC | 376 busy_loop_timeout = time.time() + BUSY_LOOP_MAX_TIME_SEC |
| 369 while len(finished_tests) == 0: | 377 while len(finished_tests) == 0: |
| 370 # If we don't make progress for too long, assume the code is just dead. | 378 # If we don't make progress for too long, assume the code is just dead. |
| 371 assert busy_loop_timeout > time.time() | 379 assert busy_loop_timeout > time.time() |
| 372 | 380 |
| 373 # Select on the output pipes. | 381 # Select on the output pipes. |
| 374 read_set = [] | 382 read_set = [] |
| 375 for test in executing_tests.values(): | 383 for test in executing_tests.values(): |
| 376 read_set.extend([test['proc'].stderr, test['proc'].stdout]) | 384 read_set.extend([test['proc'].stderr, test['proc'].stdout]) |
| 377 select.select(read_set, [], read_set, NCTEST_TERMINATE_TIMEOUT_SEC) | 385 if os.name == 'nt': |
| 386 # select cannot handle pipes on Windows. |
| 387 time.sleep(0.1) |
| 388 else: |
| 389 select.select(read_set, [], read_set, NCTEST_TERMINATE_TIMEOUT_SEC) |
| 378 | 390 |
| 379 # Now attempt to process results. | 391 # Now attempt to process results. |
| 380 now = time.time() | 392 now = time.time() |
| 381 for test in executing_tests.values(): | 393 for test in executing_tests.values(): |
| 382 proc = test['proc'] | 394 proc = test['proc'] |
| 383 if proc.poll() is not None: | 395 if proc.poll() is not None: |
| 384 test['finished_at'] = now | 396 test['finished_at'] = now |
| 385 finished_tests.append(test) | 397 finished_tests.append(test) |
| 386 elif test['terminate_timeout'] < now: | 398 elif test['terminate_timeout'] < now: |
| 387 proc.terminate() | 399 proc.terminate() |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 resultfile = StringIO.StringIO() | 438 resultfile = StringIO.StringIO() |
| 427 resultlog = StringIO.StringIO() | 439 resultlog = StringIO.StringIO() |
| 428 resultfile.write(RESULT_FILE_HEADER % sourcefile_path) | 440 resultfile.write(RESULT_FILE_HEADER % sourcefile_path) |
| 429 | 441 |
| 430 # Run the no-compile tests, but ensure we do not run more than |parallelism| | 442 # Run the no-compile tests, but ensure we do not run more than |parallelism| |
| 431 # tests at once. | 443 # tests at once. |
| 432 timings['header_written'] = time.time() | 444 timings['header_written'] = time.time() |
| 433 executing_tests = {} | 445 executing_tests = {} |
| 434 finished_tests = [] | 446 finished_tests = [] |
| 435 | 447 |
| 448 cflags_extra = '' |
| 449 if os.name != 'nt': |
| 450 cflags_extra = ' -MMD -MF %s.d -MT %s' % (resultfile_path, resultfile_path) |
| 451 |
| 436 test = StartTest( | 452 test = StartTest( |
| 437 sourcefile_path, | 453 sourcefile_path, |
| 438 cflags + ' -MMD -MF %s.d -MT %s' % (resultfile_path, resultfile_path), | 454 cflags + cflags_extra, |
| 439 { 'name': 'NCTEST_SANITY', | 455 { 'name': 'NCTEST_SANITY', |
| 440 'suite_name': suite_name, | 456 'suite_name': suite_name, |
| 441 'expectations': None, | 457 'expectations': None, |
| 442 }) | 458 }) |
| 443 executing_tests[test['name']] = test | 459 executing_tests[test['name']] = test |
| 444 | 460 |
| 445 for config in test_configs: | 461 for config in test_configs: |
| 446 # CompleteAtLeastOneTest blocks until at least one test finishes. Thus, this | 462 # CompleteAtLeastOneTest blocks until at least one test finishes. Thus, this |
| 447 # acts as a semaphore. We cannot use threads + a real semaphore because | 463 # acts as a semaphore. We cannot use threads + a real semaphore because |
| 448 # subprocess forks, which can cause all sorts of hilarity with threads. | 464 # subprocess forks, which can cause all sorts of hilarity with threads. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 if return_code == 0: | 496 if return_code == 0: |
| 481 with open(resultfile_path, 'w') as fd: | 497 with open(resultfile_path, 'w') as fd: |
| 482 fd.write(resultfile.getvalue()) | 498 fd.write(resultfile.getvalue()) |
| 483 | 499 |
| 484 resultfile.close() | 500 resultfile.close() |
| 485 sys.exit(return_code) | 501 sys.exit(return_code) |
| 486 | 502 |
| 487 | 503 |
| 488 if __name__ == '__main__': | 504 if __name__ == '__main__': |
| 489 main() | 505 main() |
| OLD | NEW |