Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 import logging | |
| 5 import os | 6 import os |
| 6 import re | 7 import re |
| 7 | 8 |
| 8 from waterfall import extractor_util | 9 from waterfall import extractor_util |
| 10 from waterfall import waterfall_config | |
| 9 from waterfall.extractor import Extractor | 11 from waterfall.extractor import Extractor |
| 10 from waterfall.failure_signal import FailureSignal | 12 from waterfall.failure_signal import FailureSignal |
| 11 | 13 |
| 12 | 14 |
| 13 class GeneralExtractor(Extractor): | 15 class GeneralExtractor(Extractor): |
| 14 """A general extractor. | 16 """A general extractor. |
| 15 | 17 |
| 16 It extracts file name and line numbers. | 18 It extracts file name and line numbers. |
| 17 """ | 19 """ |
| 18 INDIRECT_LEAK_MARKER_PATTERN = re.compile( | 20 INDIRECT_LEAK_MARKER_PATTERN = re.compile( |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 WINDOWS_LINK_FAILURE_PATTERN = re.compile(r'/OUT:([^\s-]+)') | 124 WINDOWS_LINK_FAILURE_PATTERN = re.compile(r'/OUT:([^\s-]+)') |
| 123 | 125 |
| 124 NINJA_FAILURE_END_LINE_PREFIX = 'ninja: build stopped' | 126 NINJA_FAILURE_END_LINE_PREFIX = 'ninja: build stopped' |
| 125 NINJA_ERROR_LINE_PREFIX = 'ninja: error' | 127 NINJA_ERROR_LINE_PREFIX = 'ninja: error' |
| 126 ERROR_LINE_END_PATTERN = re.compile(r'^\d+ errors? generated.') | 128 ERROR_LINE_END_PATTERN = re.compile(r'^\d+ errors? generated.') |
| 127 IOS_ERROR_LINE_START_PREFIX = 'CompileC' | 129 IOS_ERROR_LINE_START_PREFIX = 'CompileC' |
| 128 | 130 |
| 129 IOS_BUILDER_NAMES_FOR_COMPILE = ['iOS_Simulator_(dbg)', 'iOS_Device'] | 131 IOS_BUILDER_NAMES_FOR_COMPILE = ['iOS_Simulator_(dbg)', 'iOS_Device'] |
| 130 MAC_MASTER_NAME_FOR_COMPILE = 'chromium.mac' | 132 MAC_MASTER_NAME_FOR_COMPILE = 'chromium.mac' |
| 131 | 133 |
| 134 STRICT_COMPILE_FAILURE_PATTEN = re.compile( | |
|
chanli
2016/03/15 06:07:49
nit: It seems that the first 2 lines of compile pa
stgao
2016/03/15 18:32:21
Done.
| |
| 135 r'^FAILED: \S*/b/build/goma/gomacc ' | |
| 136 '\S*third_party/llvm-build/Release\+Asserts/bin/clang\+\+ ' | |
| 137 '-MMD -MF (obj/[^\s-]+\.o)\.d .* ' | |
| 138 '-c ([^\s-]+(?:cc|c|cpp)) -o (obj/[^\s-]+\.o)$' | |
|
chanli
2016/03/15 06:07:49
I think this one can be simplified a little as :
r
stgao
2016/03/15 18:32:21
Actually, I went with the \number approach before
| |
| 139 ) | |
| 140 | |
| 141 STRICT_LINK_FAILURE_PATTEN = re.compile( | |
|
lijeffrey
2016/03/15 07:12:26
I'm thinking, would it make sense to make these pa
stgao
2016/03/15 18:32:21
I'd not make them into the config. Because this is
| |
| 142 r'^FAILED: \S*/b/build/goma/gomacc ' | |
| 143 '\S*third_party/llvm-build/Release\+Asserts/bin/clang\+\+ -Wl,.* ' | |
| 144 '-o (\S+) -Wl,--start-group .*$' | |
| 145 ) | |
| 146 | |
| 147 def ExtractFailedOutputNodes(self, line, signal): | |
| 148 match = self.STRICT_COMPILE_FAILURE_PATTEN.match(line) | |
| 149 if match: | |
| 150 dep_obj_name = match.group(1) | |
| 151 source = match.group(2) | |
| 152 target = match.group(3) | |
| 153 if dep_obj_name == target: | |
| 154 signal.AddTarget({ | |
| 155 'target': target, | |
| 156 'source': source, | |
| 157 }) | |
| 158 else: | |
| 159 logging.error('Unexpected compile failure pattern:%s', line) | |
| 160 else: | |
| 161 match = self.STRICT_LINK_FAILURE_PATTEN.match(line) | |
| 162 if match: | |
| 163 target = match.group(1) | |
| 164 signal.AddTarget({ | |
| 165 'target': target, | |
| 166 }) | |
| 167 | |
| 132 def GetFailedTarget(self, line, signal): | 168 def GetFailedTarget(self, line, signal): |
| 133 match = self.LINUX_FAILED_SOURCE_TARGET_PATTERN.search(line) | 169 match = self.LINUX_FAILED_SOURCE_TARGET_PATTERN.search(line) |
| 134 | 170 |
| 135 if match: | 171 if match: |
| 136 # For non-windows builds, build lines should contain either gomacc or | 172 # For non-windows builds, build lines should contain either gomacc or |
| 137 # clang++, so only search for source/target files after the call to | 173 # clang++, so only search for source/target files after the call to |
| 138 # gomacc/clang++ to avoid extracting false positives in the failure line. | 174 # gomacc/clang++ to avoid extracting false positives in the failure line. |
| 139 build_line_match = self.LINUX_BUILD_COMMAND_PATTERN.search(line) | 175 build_line_match = self.LINUX_BUILD_COMMAND_PATTERN.search(line) |
| 140 if not build_line_match: | 176 if not build_line_match: |
| 141 return | 177 return |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 | 228 |
| 193 if failure_started: | 229 if failure_started: |
| 194 if line.startswith(self.IOS_ERROR_LINE_START_PREFIX): | 230 if line.startswith(self.IOS_ERROR_LINE_START_PREFIX): |
| 195 failure_started = False | 231 failure_started = False |
| 196 for l in error_lines[:-4]: | 232 for l in error_lines[:-4]: |
| 197 self.ExtractFiles(l, signal) | 233 self.ExtractFiles(l, signal) |
| 198 error_lines = [] | 234 error_lines = [] |
| 199 else: | 235 else: |
| 200 error_lines.append(line) | 236 error_lines.append(line) |
| 201 else: | 237 else: |
| 238 strict_regex = waterfall_config.EnableStrictRegexForCompileLinkFailures( | |
| 239 master_name, bot_name) | |
| 202 for line in failure_log.splitlines(): | 240 for line in failure_log.splitlines(): |
| 203 if line.startswith(self.FAILURE_START_LINE_PREFIX): | 241 if line.startswith(self.FAILURE_START_LINE_PREFIX): |
| 204 self.GetFailedTarget(line, signal) | 242 if strict_regex: |
| 243 self.ExtractFailedOutputNodes(line, signal) | |
|
chanli
2016/03/15 06:07:49
What if strict_regex is true but the line doesn't
stgao
2016/03/15 18:32:21
Then we ignore and let "analyze" to figure out wha
| |
| 244 else: | |
| 245 self.GetFailedTarget(line, signal) | |
| 205 if not failure_started: | 246 if not failure_started: |
| 206 failure_started = True | 247 failure_started = True |
| 207 continue # pragma: no cover | 248 continue # pragma: no cover |
| 208 elif self.FAILURE_WITH_ERROR_PATTERN.match(line): | 249 elif self.FAILURE_WITH_ERROR_PATTERN.match(line): |
| 209 # It is possible the target and source file associated with a compile | 250 # It is possible the target and source file associated with a compile |
| 210 # failure is logged outside a 'FAILED: ... 1 error generated' block, | 251 # failure is logged outside a 'FAILED: ... 1 error generated' block, |
| 211 # so extract regardless of failure_started. | 252 # so extract regardless of failure_started. |
| 212 self.GetFailedTarget(line, signal) | 253 if not strict_regex: |
| 254 self.GetFailedTarget(line, signal) | |
| 213 elif failure_started and self.ERROR_LINE_END_PATTERN.match(line): | 255 elif failure_started and self.ERROR_LINE_END_PATTERN.match(line): |
| 214 failure_started = False | 256 failure_started = False |
| 215 elif failure_started and line.startswith( | 257 elif failure_started and line.startswith( |
| 216 self.NINJA_FAILURE_END_LINE_PREFIX): # pragma: no cover | 258 self.NINJA_FAILURE_END_LINE_PREFIX): # pragma: no cover |
| 217 break | 259 break |
| 218 if failure_started or line.startswith(self.NINJA_ERROR_LINE_PREFIX): | 260 if failure_started or line.startswith(self.NINJA_ERROR_LINE_PREFIX): |
| 219 # either within the compile errors or is a ninja error. | 261 # either within the compile errors or is a ninja error. |
| 220 self.ExtractFiles(line, signal) | 262 self.ExtractFiles(line, signal) |
| 221 | 263 |
| 222 return signal | 264 return signal |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 474 def ExtractSignal(master_name, bot_name, step_name, test_name, failure_log): | 516 def ExtractSignal(master_name, bot_name, step_name, test_name, failure_log): |
| 475 """Uses an appropriate extractor to extract failure signals. | 517 """Uses an appropriate extractor to extract failure signals. |
| 476 | 518 |
| 477 Returns: | 519 Returns: |
| 478 A FailureSignal. | 520 A FailureSignal. |
| 479 """ | 521 """ |
| 480 # Fall back to a general-but-maybe-not-accurate extractor. | 522 # Fall back to a general-but-maybe-not-accurate extractor. |
| 481 extractor_class = EXTRACTORS.get(step_name, GeneralExtractor) | 523 extractor_class = EXTRACTORS.get(step_name, GeneralExtractor) |
| 482 return extractor_class().Extract( | 524 return extractor_class().Extract( |
| 483 failure_log, test_name, step_name, bot_name, master_name) | 525 failure_log, test_name, step_name, bot_name, master_name) |
| OLD | NEW |