Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Unified Diff: tools/command_tester.py

Issue 8439032: Add option to command tester for running a test multiple times. Use that (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: xxx Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/command_tester.py
===================================================================
--- tools/command_tester.py (revision 7086)
+++ tools/command_tester.py (working copy)
@@ -105,9 +105,17 @@
'filter_inverse': False,
'filter_group_only': False,
- # Script for processing output along with its arguments.
- 'process_output': '',
+ # Number of times a test is run.
+ # This is useful for getting multiple samples for time perf tests.
+ 'num_runs': '1',
Nick Bray 2011/11/07 23:39:09 Make this an integer. The option parser will do t
jvoung - send to chromium... 2011/11/09 00:50:54 Done. Leaving capture_output, track_cmdtime, alone
+ # Scripts for processing output along with its arguments.
+ # This script is given the output of a single run.
+ 'process_output_single': '',
+ # This script is given the concatenated output of all |num_runs|, after
+ # having been filtered by |process_output_single| for individual runs.
+ 'process_output_combined': '',
+
'time_warning': 0,
'time_error': 0,
@@ -128,7 +136,12 @@
# The buildbots expect test names in the format "suite_name.test_name", so we
# prefix the test name with a bogus suite name (nacl).
def RunMessage():
- return '[ RUN ] nacl.%s' % GlobalSettings['name']
+ num_runs = int(GlobalSettings['num_runs'])
+ if num_runs > 1:
+ run_message_extra = ' (run %d times)' % num_runs
+ else:
+ run_message_extra = ''
+ return '[ RUN ] nacl.%s%s' % (GlobalSettings['name'], run_message_extra)
Nick Bray 2011/11/07 23:39:09 It might be clearer to produce the base string and
jvoung - send to chromium... 2011/11/09 00:50:54 Done.
def FailureMessage(total_time):
return '[ FAILED ] nacl.%s (%d ms)' % (GlobalSettings['name'],
@@ -310,6 +323,14 @@
# statuses (STATUS_*) more recognisable.
return '%i (0x%x)' % (number, number & 0xffffffff)
+def PrintStdStreams(stdout, stderr):
+ if stdout:
Nick Bray 2011/11/07 23:39:09 The case in which stdout is printed has changed.
jvoung - send to chromium... 2011/11/09 00:50:54 Leaving this the same as before for now, as noted
+ Banner('Stdout for %s:' % os.path.basename(GlobalSettings['name']))
+ Print(stdout)
+ if stderr:
Nick Bray 2011/11/07 23:39:09 is not None? != ''? It's hard to tell what your in
jvoung - send to chromium... 2011/11/09 00:50:54 Hmm... I don't remember why I did that change anym
+ Banner('Stderr for %s:' % os.path.basename(GlobalSettings['name']))
+ Print(stderr)
+
def CheckExitStatus(failed, req_status, using_nacl_signal_handler,
exit_status, stdout, stderr):
expected_sigtype = 'normal'
@@ -368,11 +389,7 @@
failed = True
if failed:
- if stderr is not None:
- Banner('Stdout')
- Print(stdout)
- Banner('Stderr')
- Print(stderr)
+ PrintStdStreams(stdout, stderr)
return not failed
def CheckTimeBounds(total_time):
@@ -407,60 +424,55 @@
return False
return True
-def ProcessLogOutput(stdout, stderr):
- output_processor = GlobalSettings['process_output']
- if output_processor:
+def ProcessLogOutputSingle(stdout, stderr):
+ output_processor = GlobalSettings['process_output_single']
+ if not output_processor:
+ return (True, stdout, stderr)
+ else:
output_processor_cmd = DestringifyList(output_processor)
- # Also, get the output from logout (to get NaClLog output in Windows).
+ # Also, get the output from log_file to get NaClLog output in Windows.
log_output = open(GlobalSettings['log_file']).read()
# Assume the log processor does not care about the order of the lines.
all_output = log_output + stdout + stderr
- if not test_lib.RunCmdWithInput(output_processor_cmd, all_output):
- return False
- return True
+ _, retcode, failed, new_stdout, new_stderr = \
+ test_lib.RunTestWithInputOutput(output_processor_cmd, all_output)
+ # Print the result, since we have done some processing and we need
+ # to have the processed data. However, if we intend to process it some
+ # more later via process_output_combined, do not duplicate the data here.
+ # Only print out the final result!
+ if not GlobalSettings['process_output_combined']:
+ PrintStdStreams(new_stdout, new_stderr)
+ if retcode != 0 or failed:
+ return (False, new_stdout, new_stderr)
+ else:
+ return (True, new_stdout, new_stderr)
-def main(argv):
- global GlobalPlatform
- global GlobalReportStream
- command = ProcessOptions(argv)
-
- if GlobalSettings['report']:
- GlobalReportStream.append(open(GlobalSettings['report'], 'w'))
-
- if not GlobalSettings['name']:
- GlobalSettings['name'] = command[0]
- GlobalSettings['name'] = os.path.basename(GlobalSettings['name'])
-
- Print(RunMessage())
-
- if GlobalSettings['osenv']:
- Banner('setting environment')
- env_vars = DestringifyList(GlobalSettings['osenv'])
+def ProcessLogOutputCombined(stdout, stderr):
+ output_processor = GlobalSettings['process_output_combined']
+ if not output_processor:
+ return True
else:
- env_vars = []
- for env_var in env_vars:
- key, val = env_var.split('=', 1)
- Print('[%s] = [%s]' % (key, val))
- os.putenv(key, val)
+ output_processor_cmd = DestringifyList(output_processor)
+ all_output = stdout + stderr
+ _, retcode, failed, new_stdout, new_stderr = \
+ test_lib.RunTestWithInputOutput(output_processor_cmd, all_output)
+ # Print the result, since we have done some processing.
+ PrintStdStreams(new_stdout, new_stderr)
+ if retcode != 0 or failed:
+ return False
+ else:
+ return True
- stdin_data = ''
- if GlobalSettings['stdin']:
- stdin_data = open(GlobalSettings['stdin'])
-
- if GlobalSettings['log_file']:
- try:
- os.unlink(GlobalSettings['log_file']) # might not pre-exist
- except OSError:
- pass
-
- run_under = GlobalSettings['run_under']
- if run_under:
- command = run_under.split(',') + command
-
- Banner('running %s' % str(command))
- # print the command in copy-and-pastable fashion
- print " ".join(env_vars + command)
-
+def DoRun(command, stdin_data):
+ """
+ Run the command, given stdin_data. Returns a return code (0 is good)
+ and optionally a captured version of stdout, stderr from the run
+ (if the global setting capture_output is true).
+ """
+ # Initialize stdout, stderr to indicate we have not captured
+ # any of stdout or stderr.
+ stdout = ''
+ stderr = ''
if not int(GlobalSettings['capture_output']):
# We are only blurting out the stdout and stderr, not capturing it
# for comparison, etc.
@@ -470,7 +482,8 @@
and not GlobalSettings['filter_regex']
and not GlobalSettings['filter_inverse']
and not GlobalSettings['filter_group_only']
- and not GlobalSettings['process_output']
+ and not GlobalSettings['process_output_single']
+ and not GlobalSettings['process_output_combined']
)
# If python ever changes popen.stdout.read() to not risk deadlock,
# we could stream and capture, and use RunTestWithInputOutput instead.
@@ -482,36 +495,100 @@
GlobalSettings['using_nacl_signal_handler'],
exit_status, None, None):
Print(FailureMessage(total_time))
- return -1
+ return (-1, stdout, stderr)
else:
(total_time, exit_status,
failed, stdout, stderr) = test_lib.RunTestWithInputOutput(
command, stdin_data)
PrintTotalTime(total_time)
+ # CheckExitStatus may spew stdout/stderr when there is an error.
+ # Otherwise, we do not spew stdout/stderr in this case (capture_output).
if not CheckExitStatus(failed,
GlobalSettings['exit_status'],
GlobalSettings['using_nacl_signal_handler'],
exit_status, stdout, stderr):
Print(FailureMessage(total_time))
- return -1
+ return (-1, stdout, stderr)
if not CheckGoldenOutput(stdout, stderr):
Print(FailureMessage(total_time))
- return -1
- if not ProcessLogOutput(stdout, stderr):
- Print(FailureMessage(total_time))
- return -1
+ return (-1, stdout, stderr)
+ success, stdout, stderr = ProcessLogOutputSingle(stdout, stderr)
+ if not success:
+ Print(FailureMessage(total_time) + ' ProcessLogOutputSingle failed!')
+ return (-1, stdout, stderr)
if not CheckTimeBounds(total_time):
Print(FailureMessage(total_time))
- return -1
+ return (-1, stdout, stderr)
Print(SuccessMessage(total_time))
+ return (0, stdout, stderr)
+
+
+def main(argv):
Nick Bray 2011/11/07 23:39:09 Capitalize
jvoung - send to chromium... 2011/11/09 00:50:54 capitalize Main? ok.
+ global GlobalPlatform
Nick Bray 2011/11/07 23:39:09 Do not declare globals unless you assign directly
jvoung - send to chromium... 2011/11/09 00:50:54 Done.
+ global GlobalReportStream
+ command = ProcessOptions(argv)
+
+ if GlobalSettings['report']:
+ GlobalReportStream.append(open(GlobalSettings['report'], 'w'))
+
+ if not GlobalSettings['name']:
+ GlobalSettings['name'] = command[0]
+ GlobalSettings['name'] = os.path.basename(GlobalSettings['name'])
+
+ Print(RunMessage())
+
+ if GlobalSettings['osenv']:
+ Banner('setting environment')
+ env_vars = DestringifyList(GlobalSettings['osenv'])
+ else:
+ env_vars = []
+ for env_var in env_vars:
+ key, val = env_var.split('=', 1)
+ Print('[%s] = [%s]' % (key, val))
+ os.putenv(key, val)
Nick Bray 2011/11/07 23:39:09 putenv considered harmful. Assign to os.environ?
jvoung - send to chromium... 2011/11/09 00:50:54 Don't know the specifics (does it sometimes not wo
+
+ stdin_data = ''
+ if GlobalSettings['stdin']:
+ stdin_data = open(GlobalSettings['stdin'])
+
+ run_under = GlobalSettings['run_under']
+ if run_under:
+ command = run_under.split(',') + command
+
+ Banner('running %s' % str(command))
+ # print the command in copy-and-pastable fashion
+ print " ".join(env_vars + command)
+
+ # Concatenate output when running multiple times (e.g., for timing).
+ combined_stdout = ''
+ combined_stderr = ''
+ cur_runs = 0
+ num_runs = int(GlobalSettings['num_runs'])
+ while cur_runs < num_runs:
+ cur_runs += 1
+ # Clear out previous log_file.
+ if GlobalSettings['log_file']:
+ try:
+ os.unlink(GlobalSettings['log_file']) # might not pre-exist
+ except OSError:
+ pass
+ ret_code, stdout, stderr = DoRun(command, stdin_data)
+ if ret_code != 0:
+ return ret_code
+ combined_stdout += stdout
+ combined_stderr += stderr
+ # Process the log output after all the runs.
+ success = ProcessLogOutputCombined(combined_stdout, combined_stderr)
+ if not success:
+ # Bogus time, since only ProcessLogOutputCombined failed.
+ Print(FailureMessage(0.0) + ' ProcessLogOutputCombined failed!')
+ return -1
return 0
-
if __name__ == '__main__':
retval = main(sys.argv[1:])
# Add some whitepsace to make the logs easier to read.
sys.stdout.write('\n\n')
sys.exit(retval)
-

Powered by Google App Engine
This is Rietveld 408576698