def RunTest(test): command = [test_runner, test] + test_runner_runtime_options if test_runner_under_valgrind: command = ['valgrind'] + command p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p_out, p_err = p.communicate() rc = p.poll() if rc == 0: with n_tests_passed.get_lock(): n_tests_passed.value += 1 else: with n_tests_failed.get_lock(): n_tests_failed.value += 1 printer.__print_lock__.acquire() printer.UpdateProgress(start_time, n_tests_passed.value, n_tests_failed.value, n_tests, test, prevent_next_overwrite = (rc != 0), has_lock = True, prefix = progress_prefix) if rc != 0: printer.Print('FAILED: ' + test, has_lock = True) printer.Print(printer.COLOUR_RED + ' '.join(command) + printer.NO_COLOUR, has_lock = True) printer.Print(p_out, has_lock = True) printer.__print_lock__.release()
def Run(self, jobs, verbose, run_function): def InitGlobals(): # Initialisation. self.start_time = time.time() self.n_tests = len(self.queue) if self.n_tests == 0: printer.Print('No tests to run.') return False Test.n_tests_passed.value = 0 Test.n_tests_failed.value = 0 Test.n_tests_skipped.value = 0 self.tests_skipped.clear() return True thread_pool.Multithread(run_function, self.queue, jobs, InitGlobals) printer.UpdateProgress(self.start_time, Test.n_tests_passed.value, Test.n_tests_failed.value, self.n_tests, Test.n_tests_skipped.value, self.n_known_failures, '== Done ==', prevent_next_overwrite=True, prefix=self.progress_prefix) n_tests_features = 0 features = set() for reason, n_tests in list(self.tests_skipped.items()): m = re.match(REGEXP_MISSING_FEATURES, reason) if m: if verbose: printer.Print( "%d tests skipped because the following features are not " "available '%s'" % (n_tests, m.group(1))) else: n_tests_features += n_tests features.update(m.group(1).split(', ')) else: printer.Print("%d tests skipped because '%s'" % (n_tests, reason)) n_tests_other = 0 if n_tests_features > 0: printer.Print("%d tests skipped because the CPU does not support " "the following features: '%s'" % (n_tests_features, ", ".join(features))) for reason, n_tests in list(self.known_failures.items()): printer.Print("%d tests skipped because '%s'" % (n_tests, reason)) # Empty the queue now that the tests have been run. self.queue = [] # `0` indicates success return Test.n_tests_failed.value
def RunTest(test): command = test.args['command'] p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p_out, p_err = p.communicate() rc = p.poll() if rc == 0: skipped = False lines = p_out.split('\n') skipped_id = "SKIPPED: " for i in range(len(lines)): if lines[i].startswith(skipped_id): skipped = True reason = lines[i][len(skipped_id):] with Test.n_tests_skipped.get_lock(): Test.n_tests_skipped.value += 1 test.shared.tests_skipped.setdefault(reason, 0) test.shared.tests_skipped[reason] += 1 break if not skipped: with Test.n_tests_passed.get_lock(): Test.n_tests_passed.value += 1 else: with Test.n_tests_failed.get_lock(): Test.n_tests_failed.value += 1 printer.__print_lock__.acquire() printer.UpdateProgress(test.shared.start_time, Test.n_tests_passed.value, Test.n_tests_failed.value, test.shared.n_tests, Test.n_tests_skipped.value, test.shared.n_known_failures, test.name, prevent_next_overwrite=(rc != 0), has_lock=True, prefix=test.shared.progress_prefix) if rc != 0: printer.Print('FAILED: ' + test.name, has_lock=True) printer.Print(printer.COLOUR_RED + ' '.join(command) + printer.NO_COLOUR, has_lock=True) printer.Print(p_out, has_lock=True) printer.__print_lock__.release()
def Lint(filename, progress_prefix = ''): command = ['cpplint.py', filename] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) outerr, _ = process.communicate() if process.returncode == 0: printer.PrintOverwritableLine( progress_prefix + "Done processing %s" % filename, type = printer.LINE_TYPE_LINTER) return (filename, 0) if progress_prefix: outerr = re.sub('^', progress_prefix, outerr, flags=re.MULTILINE) printer.Print(outerr) # Find the number of errors in this file. res = re.search('Total errors found: (\d+)', outerr) if res: n_errors_str = res.string[res.start(1):res.end(1)] n_errors = int(n_errors_str) else: print("Couldn't parse cpplint.py output.") n_errors = -1 return (filename, n_errors)
def ClangTidyFiles(files, clang_tidy, jobs=1, progress_prefix=''): if not ClangTidyIsAvailable(clang_tidy): error_message = "`{}` version {}.{} not found. Please ensure it " \ "is installed, in your PATH and the correct version." \ .format(clang_tidy, CLANG_TIDY_VERSION_MAJOR, CLANG_TIDY_VERSION_MINOR) print(printer.COLOUR_RED + error_message + printer.NO_COLOUR) return -1 opts = [ '--', '-DVIXL_INCLUDE_TARGET_AARCH64', '-DVIXL_CODE_BUFFER_MALLOC', '-DVIXL_DEBUG', '-DVIXL_INCLUDE_SIMLUATOR_AARCH64', '-DVIXL_INCLUDE_TARGET_A32', '-DVIXL_INCLUDE_TARGET_T32', '-DVIXL_INCLUDE_TARGET_A64' ] opts += ['-I%s' % config.dir_src_vixl] opts += ['-I%s' % config.dir_tests] opts += ['-I%s' % config.dir_aarch64_examples] opts += ['-I%s' % config.dir_aarch32_examples] to_check = FilterFiles(files) printer.Print("clang-tidy: %d files to check" % len(to_check)) queue = TestQueue(prefix=progress_prefix) for file in to_check: for cpp_version in config.tested_cpp_standards: command = [clang_tidy, file] + opts + ['-std=%s' % cpp_version] queue.AddTest(file, command=command) return queue.Run(jobs, True, RunTest)
def LintFiles(files, jobs = 1, progress_prefix = '', cached_results = None): if not IsCppLintAvailable(): print( printer.COLOUR_RED + \ ("cpplint.py not found. Please ensure the depot" " tools are installed and in your PATH. See" " http://dev.chromium.org/developers/how-tos/install-depot-tools for" " details.") + \ printer.NO_COLOUR) return -1 # Filter out directories. files = filter(os.path.isfile, files) # Filter out files for which we have a cached correct result. if cached_results is not None and len(cached_results) != 0: n_input_files = len(files) files = filter(lambda f: ShouldLint(f, cached_results), files) n_skipped_files = n_input_files - len(files) if n_skipped_files != 0: printer.Print( progress_prefix + 'Skipping %d correct files that were already processed.' % n_skipped_files) pool = multiprocessing.Pool(jobs) # The '.get(9999999)' is workaround to allow killing the test script with # ctrl+C from the shell. This bug is documented at # http://bugs.python.org/issue8296. tasks = [(f, progress_prefix) for f in files] # Run under a try-catch to avoid flooding the output when the script is # interrupted from the keyboard with ctrl+C. try: results = pool.map_async(LintWrapper, tasks).get(9999999) pool.close() pool.join() except KeyboardInterrupt: pool.terminate() sys.exit(1) n_errors = sum(map(lambda (filename, errors): errors, results)) if cached_results is not None: for filename, errors in results: if errors == 0: with open(filename, 'rb') as f: filename = os.path.realpath(filename) file_hash = hashlib.md5(f.read()).hexdigest() cached_results[filename] = file_hash printer.PrintOverwritableLine( progress_prefix + 'Total errors found: %d' % n_errors) printer.EnsureNewLine() return n_errors
def GetDefaultTrackedFiles(): if git.is_git_repository_root(config.dir_root): default_tracked_files = git.get_tracked_files().split() default_tracked_files = filter(is_linter_input, default_tracked_files) return 0, default_tracked_files else: printer.Print(printer.COLOUR_ORANGE + 'WARNING: This script is not run ' \ 'from its Git repository. The linter will not run.' + \ printer.NO_COLOUR) return 1, []
def GetDefaultFilesToLint(): if git.is_git_repository_root(config.dir_root): files = git.get_tracked_files().split() files = filter(IsLinterInput, files) files = FilterOutTestTraceHeaders(files) return 0, files else: printer.Print(printer.COLOUR_ORANGE + 'WARNING: This script is not run ' \ 'from its Git repository. The linter will not run.' + \ printer.NO_COLOUR) return 1, []
def InitGlobals(): # Initialisation. self.start_time = time.time() self.n_tests = len(self.queue) if self.n_tests == 0: printer.Print('No tests to run.') return False Test.n_tests_passed.value = 0 Test.n_tests_failed.value = 0 Test.n_tests_skipped.value = 0 self.tests_skipped.clear() return True
def RunTest(test): cmd = " ".join(test.args['command']) rc, p_out = util.getstatusoutput(cmd) if rc != 0: # This usually happens when the compiler hits a '#error' because of # a missing define. printer.Print("%sFATAL ERROR: failed to run command '%s': %s%s" % (printer.COLOUR_RED, cmd, p_out, printer.NO_COLOUR)) p_out = FilterClangTidyLines(p_out.split('\n')) failed = (len(p_out) > 0) or (rc != 0) if failed: with Test.n_tests_failed.get_lock(): Test.n_tests_failed.value += 1 else: with Test.n_tests_passed.get_lock(): Test.n_tests_passed.value += 1 printer.__print_lock__.acquire() printer.UpdateProgress(test.shared.start_time, Test.n_tests_passed.value, Test.n_tests_failed.value, test.shared.n_tests, Test.n_tests_skipped.value, test.shared.n_known_failures, test.name, prevent_next_overwrite=failed, has_lock=True, prefix=test.shared.progress_prefix) if failed: printer.Print(printer.COLOUR_RED + 'FAILED: ' + cmd + printer.NO_COLOUR, has_lock=True) printer.Print(p_out, has_lock=True) printer.__print_lock__.release()
def RunTests(test_runner_command, filters, runtime_options, under_valgrind=False, jobs=1, prefix=''): global test_runner global test_runner_runtime_options global test_runner_under_valgrind global n_tests global start_time global progress_prefix tests = GetTests(test_runner_command, filters) tests = FilterKnownTestFailures(tests, under_valgrind=under_valgrind) if n_tests == 0: printer.Print('No tests to run.') return 0 with __run_tests_lock__: # Initialisation. start_time = time.time() test_runner = test_runner_command test_runner_runtime_options = runtime_options test_runner_under_valgrind = under_valgrind n_tests = len(tests) n_tests_passed.value = 0 n_tests_failed.value = 0 progress_prefix = prefix pool = multiprocessing.Pool(jobs) # The '.get(9999999)' is a workaround to allow killing the test script with # ctrl+C from the shell. This bug is documented at # http://bugs.python.org/issue8296. work = pool.map_async(RunTest, tests).get(9999999) pool.close() pool.join() printer.UpdateProgress(start_time, n_tests_passed.value, n_tests_failed.value, n_tests, '== Done ==', prevent_next_overwrite=True, prefix=progress_prefix) # `0` indicates success return n_tests_failed.value
def ClangFormat(filename, in_place=False, progress_prefix=''): rc = 0 printer.PrintOverwritableLine('Processing %s' % filename, type=printer.LINE_TYPE_LINTER) cmd_format = ['clang-format-3.6', filename] temp_file, temp_file_name = tempfile.mkstemp(prefix='clang_format_') cmd_format_string = '$ ' + ' '.join(cmd_format) + ' > %s' % temp_file_name p_format = subprocess.Popen(cmd_format, stdout=temp_file, stderr=subprocess.STDOUT) rc += p_format.wait() cmd_diff = ['diff', '--unified', filename, temp_file_name] cmd_diff_string = '$ ' + ' '.join(cmd_diff) p_diff = subprocess.Popen(cmd_diff, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if util.IsCommandAvailable('colordiff') and not is_output_redirected: p_colordiff = subprocess.Popen(['colordiff', '--unified'], stdin=p_diff.stdout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, unused = p_colordiff.communicate() else: out, unused = p_diff.communicate() rc += p_diff.wait() if in_place: cmd_format = ['clang-format-3.6', '-i', filename] p_format = subprocess.Popen(cmd_format, stdout=temp_file, stderr=subprocess.STDOUT) if rc != 0: printer.Print('Incorrectly formatted file: ' + filename + '\n' + \ cmd_format_string + '\n' + \ cmd_diff_string + '\n' + \ out) os.remove(temp_file_name) return 0 if rc == 0 else 1
def AddTests(self, test_runner_command, filters, runtime_options, under_valgrind): tests = GetTests(test_runner_command, filters) n_tests_total = len(tests) tests, skipped = FilterKnownTestFailures(tests, under_valgrind = under_valgrind) for n_tests, reason in skipped: if n_tests > 0: self.AddKnownFailures(reason, n_tests) if len(tests) == 0: printer.Print('No tests to run.') return base_command = [] if under_valgrind: base_command += ['valgrind'] base_command += [test_runner_command] for test in tests: command = base_command + [test] + runtime_options self.AddTest(test, command = command)
def PrintStatus(success): printer.Print('\n$ ' + ' '.join(sys.argv)) if success: printer.Print('SUCCESS') else: printer.Print('FAILURE')
def RunCommand(command, environment_options=None): # Create a copy of the environment. We do not want to pollute the environment # of future commands run. environment = os.environ # Configure the environment. # TODO: We currently pass the options as strings, so we need to parse them. We # should instead pass them as a data structure and build the string option # later. `environment_options` looks like `['CXX=compiler', 'OPT=val']`. if environment_options: for option in environment_options: opt, val = option.split('=') environment[opt] = val printable_command = '' if environment_options: printable_command += ' '.join(environment_options) + ' ' printable_command += ' '.join(command) printable_command_orange = \ printer.COLOUR_ORANGE + printable_command + printer.NO_COLOUR printer.PrintOverwritableLine(printable_command_orange) sys.stdout.flush() # Start a process for the command. # Interleave `stderr` and `stdout`. p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=environment) # We want to be able to display a continuously updated 'work indicator' while # the process is running. Since the process can hang if the `stdout` pipe is # full, we need to pull from it regularly. We cannot do so via the # `readline()` function because it is blocking, and would thus cause the # indicator to not be updated properly. So use file control mechanisms # instead. indicator = ' (still working: %d seconds elapsed)' # Mark the process output as non-blocking. flags = fcntl.fcntl(p.stdout, fcntl.F_GETFL) fcntl.fcntl(p.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) t_start = time.time() t_last_indication = t_start process_output = '' # Keep looping as long as the process is running. while p.poll() is None: # Avoid polling too often. time.sleep(0.1) # Update the progress indicator. t_current = time.time() if (t_current - t_start >= 2) and (t_current - t_last_indication >= 1): printer.PrintOverwritableLine(printable_command_orange + indicator % int(t_current - t_start)) sys.stdout.flush() t_last_indication = t_current # Pull from the process output. while True: try: line = os.read(p.stdout.fileno(), 1024) except OSError: line = '' break if line == '': break process_output += line # The process has exited. Don't forget to retrieve the rest of its output. out, err = p.communicate() rc = p.poll() process_output += out if rc == 0: printer.Print(printer.COLOUR_GREEN + printable_command + printer.NO_COLOUR) else: printer.Print(printer.COLOUR_RED + printable_command + printer.NO_COLOUR) printer.Print(process_output) return rc
# Avoid going through the build stage if we are not using the build # result. if not (args.notest and args.nobench): build_rc = BuildAll(build_options, args.jobs) # Don't run the tests for this configuration if the build failed. if build_rc != 0: rc |= build_rc continue # Use the realpath of the test executable so that the commands printed # can be copy-pasted and run. test_executable = os.path.realpath( join(config.dir_build_latest, 'test', 'test-runner')) if not args.notest: printer.Print(test_executable) for runtime_options in test_runtime_combinations: if not args.notest: runtime_options = [ x for x in runtime_options if x is not None ] prefix = ' ' + ' '.join(runtime_options) + ' ' rc |= threaded_tests.RunTests(test_executable, args.filters, list(runtime_options), args.under_valgrind, jobs=args.jobs, prefix=prefix) if not args.nobench:
def RunTest(test): filename = test.args['filename'] clang_format = test.args['clang_format'] in_place = test.args['in_place'] rc = 0 cmd_format = [clang_format, filename] temp_file, temp_file_name = tempfile.mkstemp(prefix='clang_format_') cmd_format_string = '$ ' + ' '.join(cmd_format) + ' > %s' % temp_file_name p_format = subprocess.Popen(cmd_format, stdout=temp_file, stderr=subprocess.STDOUT) rc += p_format.wait() cmd_diff = ['diff', '--unified', filename, temp_file_name] cmd_diff_string = '$ ' + ' '.join(cmd_diff) p_diff = subprocess.Popen(cmd_diff, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if util.IsCommandAvailable('colordiff') and not is_output_redirected: p_colordiff = subprocess.Popen(['colordiff', '--unified'], stdin=p_diff.stdout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, unused = p_colordiff.communicate() else: out, unused = p_diff.communicate() rc += p_diff.wait() if in_place: cmd_format = [clang_format, '-i', filename] p_format = subprocess.Popen(cmd_format, stdout=temp_file, stderr=subprocess.STDOUT) if rc != 0: with Test.n_tests_failed.get_lock(): Test.n_tests_failed.value += 1 else: with Test.n_tests_passed.get_lock(): Test.n_tests_passed.value += 1 printer.__print_lock__.acquire() printer.UpdateProgress(test.shared.start_time, Test.n_tests_passed.value, Test.n_tests_failed.value, test.shared.n_tests, Test.n_tests_skipped.value, test.shared.n_known_failures, test.name, prevent_next_overwrite=rc != 0, has_lock=True, prefix=test.shared.progress_prefix) if rc != 0: printer.Print('Incorrectly formatted file: ' + filename + '\n' + \ cmd_format_string + '\n' + \ cmd_diff_string + '\n' + \ out, has_lock = True) printer.__print_lock__.release() os.remove(temp_file_name)