| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Generates annotated output. | 5 """Generates annotated output. |
| 6 | 6 |
| 7 TODO(stip): Move the gtest_utils gtest parser selection code from runtest.py | 7 TODO(stip): Move the gtest_utils gtest parser selection code from runtest.py |
| 8 to here. | 8 to here. |
| 9 TODO(stip): Move the perf dashboard code from runtest.py to here. | 9 TODO(stip): Move the perf dashboard code from runtest.py to here. |
| 10 """ | 10 """ |
| 11 | 11 |
| 12 import re | 12 import re |
| 13 | 13 |
| 14 from slave import process_log_utils | 14 from slave import performance_log_processor |
| 15 from slave import slave_utils | 15 from slave import slave_utils |
| 16 | 16 |
| 17 | 17 |
| 18 def getText(result, observer, name): | 18 def getText(result, observer, name): |
| 19 """Generate a text summary for the waterfall. | 19 """Generate a text summary for the waterfall. |
| 20 | 20 |
| 21 Updates the waterfall with any unusual test output, with a link to logs of | 21 Updates the waterfall with any unusual test output, with a link to logs of |
| 22 failed test steps. | 22 failed test steps. |
| 23 """ | 23 """ |
| 24 GTEST_DASHBOARD_BASE = ('http://test-results.appspot.com' | 24 GTEST_DASHBOARD_BASE = ('http://test-results.appspot.com' |
| (...skipping 14 matching lines...) Expand all Loading... |
| 39 disabled = observer.DisabledTests() | 39 disabled = observer.DisabledTests() |
| 40 if disabled: | 40 if disabled: |
| 41 basic_info.append('%s disabled' % str(disabled)) | 41 basic_info.append('%s disabled' % str(disabled)) |
| 42 | 42 |
| 43 flaky = observer.FlakyTests() | 43 flaky = observer.FlakyTests() |
| 44 if flaky: | 44 if flaky: |
| 45 basic_info.append('%s flaky' % str(flaky)) | 45 basic_info.append('%s flaky' % str(flaky)) |
| 46 | 46 |
| 47 failed_test_count = len(observer.FailedTests()) | 47 failed_test_count = len(observer.FailedTests()) |
| 48 if failed_test_count == 0: | 48 if failed_test_count == 0: |
| 49 if result == process_log_utils.SUCCESS: | 49 if result == performance_log_processor.SUCCESS: |
| 50 return basic_info | 50 return basic_info |
| 51 elif result == process_log_utils.WARNINGS: | 51 elif result == performance_log_processor.WARNINGS: |
| 52 return basic_info + ['warnings'] | 52 return basic_info + ['warnings'] |
| 53 | 53 |
| 54 if observer.RunningTests(): | 54 if observer.RunningTests(): |
| 55 basic_info += ['did not complete'] | 55 basic_info += ['did not complete'] |
| 56 | 56 |
| 57 # TODO(xusydoc): see if 'crashed or hung' should be tracked by RunningTests(). | 57 # TODO(xusydoc): see if 'crashed or hung' should be tracked by RunningTests(). |
| 58 if failed_test_count: | 58 if failed_test_count: |
| 59 failure_text = ['failed %d' % failed_test_count] | 59 failure_text = ['failed %d' % failed_test_count] |
| 60 if observer.master_name: | 60 if observer.master_name: |
| 61 # Include the link to the flakiness dashboard. | 61 # Include the link to the flakiness dashboard. |
| 62 failure_text.append('<div class="BuildResultInfo">') | 62 failure_text.append('<div class="BuildResultInfo">') |
| 63 failure_text.append('<a href="%s#master=%s&testType=%s' | 63 failure_text.append('<a href="%s#master=%s&testType=%s' |
| 64 '&tests=%s">' % (GTEST_DASHBOARD_BASE, | 64 '&tests=%s">' % (GTEST_DASHBOARD_BASE, |
| 65 observer.master_name, | 65 observer.master_name, |
| 66 name, | 66 name, |
| 67 ','.join(observer.FailedTests()))) | 67 ','.join(observer.FailedTests()))) |
| 68 failure_text.append('Flakiness dashboard') | 68 failure_text.append('Flakiness dashboard') |
| 69 failure_text.append('</a>') | 69 failure_text.append('</a>') |
| 70 failure_text.append('</div>') | 70 failure_text.append('</div>') |
| 71 else: | 71 else: |
| 72 failure_text = ['crashed or hung'] | 72 failure_text = ['crashed or hung'] |
| 73 return basic_info + failure_text | 73 return basic_info + failure_text |
| 74 | 74 |
| 75 | 75 |
| 76 def annotate(test_name, result, results_tracker, full_name=False, | 76 def annotate(test_name, result, log_processor, full_name=False, |
| 77 perf_dashboard_id=None): | 77 perf_dashboard_id=None): |
| 78 """Given a test result and tracker, update the waterfall with test results.""" | 78 """Given a test result and tracker, update the waterfall with test results.""" |
| 79 | 79 |
| 80 # Always print raw exit code of the subprocess. This is very helpful | 80 # Always print raw exit code of the subprocess. This is very helpful |
| 81 # for debugging, especially when one gets the "crashed or hung" message | 81 # for debugging, especially when one gets the "crashed or hung" message |
| 82 # with no output (exit code can have some clues, especially on Windows). | 82 # with no output (exit code can have some clues, especially on Windows). |
| 83 print 'exit code (as seen by runtest.py): %d' % result | 83 print 'exit code (as seen by runtest.py): %d' % result |
| 84 | 84 |
| 85 get_text_result = process_log_utils.SUCCESS | 85 get_text_result = performance_log_processor.SUCCESS |
| 86 | 86 |
| 87 for failure in sorted(results_tracker.FailedTests()): | 87 for failure in sorted(log_processor.FailedTests()): |
| 88 if full_name: | 88 if full_name: |
| 89 testabbr = re.sub(r'[^\w\.\-]', '_', failure) | 89 testabbr = re.sub(r'[^\w\.\-]', '_', failure) |
| 90 else: | 90 else: |
| 91 testabbr = re.sub(r'[^\w\.\-]', '_', failure.split('.')[-1]) | 91 testabbr = re.sub(r'[^\w\.\-]', '_', failure.split('.')[-1]) |
| 92 slave_utils.WriteLogLines(testabbr, | 92 slave_utils.WriteLogLines(testabbr, |
| 93 results_tracker.FailureDescription(failure)) | 93 log_processor.FailureDescription(failure)) |
| 94 for suppression_hash in sorted(results_tracker.SuppressionHashes()): | 94 for suppression_hash in sorted(log_processor.SuppressionHashes()): |
| 95 slave_utils.WriteLogLines(suppression_hash, | 95 slave_utils.WriteLogLines(suppression_hash, |
| 96 results_tracker.Suppression(suppression_hash)) | 96 log_processor.Suppression(suppression_hash)) |
| 97 | 97 |
| 98 if results_tracker.ParsingErrors(): | 98 if log_processor.ParsingErrors(): |
| 99 # Generate a log file containing the list of errors. | 99 # Generate a log file containing the list of errors. |
| 100 slave_utils.WriteLogLines('log parsing error(s)', | 100 slave_utils.WriteLogLines('log parsing error(s)', |
| 101 results_tracker.ParsingErrors()) | 101 log_processor.ParsingErrors()) |
| 102 | 102 |
| 103 results_tracker.ClearParsingErrors() | 103 log_processor.ClearParsingErrors() |
| 104 | 104 |
| 105 if hasattr(results_tracker, 'evaluateCommand'): | 105 if hasattr(log_processor, 'evaluateCommand'): |
| 106 parser_result = results_tracker.evaluateCommand('command') | 106 parser_result = log_processor.evaluateCommand('command') |
| 107 if parser_result > result: | 107 if parser_result > result: |
| 108 result = parser_result | 108 result = parser_result |
| 109 | 109 |
| 110 if result == process_log_utils.SUCCESS: | 110 if result == performance_log_processor.SUCCESS: |
| 111 if (len(results_tracker.ParsingErrors()) or | 111 if (len(log_processor.ParsingErrors()) or |
| 112 len(results_tracker.FailedTests()) or | 112 len(log_processor.FailedTests()) or |
| 113 len(results_tracker.SuppressionHashes())): | 113 len(log_processor.SuppressionHashes())): |
| 114 print '@@@STEP_WARNINGS@@@' | 114 print '@@@STEP_WARNINGS@@@' |
| 115 get_text_result = process_log_utils.WARNINGS | 115 get_text_result = performance_log_processor.WARNINGS |
| 116 elif result == slave_utils.WARNING_EXIT_CODE: | 116 elif result == slave_utils.WARNING_EXIT_CODE: |
| 117 print '@@@STEP_WARNINGS@@@' | 117 print '@@@STEP_WARNINGS@@@' |
| 118 get_text_result = process_log_utils.WARNINGS | 118 get_text_result = performance_log_processor.WARNINGS |
| 119 else: | 119 else: |
| 120 print '@@@STEP_FAILURE@@@' | 120 print '@@@STEP_FAILURE@@@' |
| 121 get_text_result = process_log_utils.FAILURE | 121 get_text_result = performance_log_processor.FAILURE |
| 122 | 122 |
| 123 for desc in getText(get_text_result, results_tracker, test_name): | 123 for desc in getText(get_text_result, log_processor, test_name): |
| 124 print '@@@STEP_TEXT@%s@@@' % desc | 124 print '@@@STEP_TEXT@%s@@@' % desc |
| 125 | 125 |
| 126 if hasattr(results_tracker, 'PerformanceLogs'): | 126 if hasattr(log_processor, 'PerformanceLogs'): |
| 127 if not perf_dashboard_id: | 127 if not perf_dashboard_id: |
| 128 raise Exception('runtest.py error: perf step specified but' | 128 raise Exception('runtest.py error: perf step specified but' |
| 129 'no test_id in factory_properties!') | 129 'no test_id in factory_properties!') |
| 130 for logname, log in results_tracker.PerformanceLogs().iteritems(): | 130 for logname, log in log_processor.PerformanceLogs().iteritems(): |
| 131 lines = [str(l).rstrip() for l in log] | 131 lines = [str(l).rstrip() for l in log] |
| 132 slave_utils.WriteLogLines(logname, lines, perf=perf_dashboard_id) | 132 slave_utils.WriteLogLines(logname, lines, perf=perf_dashboard_id) |
| OLD | NEW |