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 logging |
| 6 import os | 6 import os |
| 7 import re | 7 import re |
| 8 | 8 |
| 9 from waterfall import extractor_util | 9 from waterfall import extractor_util |
| 10 from waterfall import waterfall_config | 10 from waterfall import waterfall_config |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 match = self.WINDOWS_LINK_FAILURE_PATTERN.search(line) | 210 match = self.WINDOWS_LINK_FAILURE_PATTERN.search(line) |
| 211 if match: | 211 if match: |
| 212 # Failure is a linker error. | 212 # Failure is a linker error. |
| 213 target = match.group(1) | 213 target = match.group(1) |
| 214 signal.AddTarget({'target': target}) | 214 signal.AddTarget({'target': target}) |
| 215 | 215 |
| 216 def Extract(self, failure_log, test_name, step_name, bot_name, master_name): | 216 def Extract(self, failure_log, test_name, step_name, bot_name, master_name): |
| 217 signal = FailureSignal() | 217 signal = FailureSignal() |
| 218 failure_started = False | 218 failure_started = False |
| 219 is_build_command_line = False | 219 is_build_command_line = False |
| 220 failed_output_nodes = set() | |
| 220 | 221 |
| 221 if (master_name == self.MAC_MASTER_NAME_FOR_COMPILE and | 222 if (master_name == self.MAC_MASTER_NAME_FOR_COMPILE and |
| 222 bot_name in self.IOS_BUILDER_NAMES_FOR_COMPILE): | 223 bot_name in self.IOS_BUILDER_NAMES_FOR_COMPILE): |
| 223 error_lines = [] | 224 error_lines = [] |
| 224 for line in reversed(failure_log.splitlines()): | 225 for line in reversed(failure_log.splitlines()): |
| 225 if (not failure_started and | 226 if (not failure_started and |
| 226 self.ERROR_LINE_END_PATTERN1.match(line)): | 227 self.ERROR_LINE_END_PATTERN1.match(line)): |
| 227 failure_started = True | 228 failure_started = True |
| 228 continue | 229 continue |
| 229 | 230 |
| 230 if failure_started: | 231 if failure_started: |
| 231 if line.startswith(self.IOS_ERROR_LINE_START_PREFIX): | 232 if line.startswith(self.IOS_ERROR_LINE_START_PREFIX): |
| 232 failure_started = False | 233 failure_started = False |
| 233 for l in error_lines[:-4]: | 234 for l in error_lines[:-4]: |
| 234 self.ExtractFiles(l, signal) | 235 self.ExtractFiles(l, signal) |
| 235 error_lines = [] | 236 error_lines = [] |
| 236 else: | 237 else: |
| 237 error_lines.append(line) | 238 error_lines.append(line) |
| 238 else: | 239 else: |
| 239 strict_regex = waterfall_config.EnableStrictRegexForCompileLinkFailures( | 240 strict_regex = waterfall_config.EnableStrictRegexForCompileLinkFailures( |
| 240 master_name, bot_name) | 241 master_name, bot_name) |
| 241 for line in failure_log.splitlines(): | 242 for line in failure_log.splitlines(): |
| 242 if line.startswith(self.FAILURE_START_LINE_PREFIX): | 243 if line.startswith(self.FAILURE_START_LINE_PREFIX): |
| 243 if not failure_started: | 244 if not failure_started: |
| 244 failure_started = True | 245 failure_started = True |
| 246 line = line[len(self.FAILURE_START_LINE_PREFIX):] | |
| 247 while line: | |
|
chanli
2016/04/30 02:24:58
Is it possible that the line is like:
FAILED: a.o
stgao
2016/05/01 05:12:28
In theory, this is possible.
But in practice, when
| |
| 248 quote_index = line.find('"') | |
|
lijeffrey
2016/04/30 03:44:25
nit: it seems since this is a temporary solution,
stgao
2016/05/01 05:12:28
This is a good idea.
Done, but with additional ch
| |
| 249 if quote_index < 0: | |
| 250 sub_part = line | |
| 251 remaining_part = None | |
| 252 else: | |
| 253 sub_part = line[:quote_index] | |
| 254 match_quote_index = line.find('"', quote_index + 1) | |
| 255 if match_quote_index < 0: # Unexpected format. | |
| 256 failed_output_nodes.clear() | |
| 257 break | |
| 258 failed_output_nodes.add( | |
| 259 line[quote_index + 1: match_quote_index]) | |
| 260 remaining_part = line[match_quote_index + 1:] | |
| 261 line = remaining_part | |
| 262 | |
| 263 for node in sub_part.split(' '): | |
| 264 node = node.strip() | |
| 265 if node: | |
| 266 failed_output_nodes.add(node) | |
| 267 | |
| 245 is_build_command_line = True | 268 is_build_command_line = True |
| 246 continue | 269 continue |
| 247 elif is_build_command_line: | 270 elif is_build_command_line: |
| 248 if strict_regex: | 271 if strict_regex: |
| 249 self.ExtractFailedOutputNodes(line, signal) | 272 self.ExtractFailedOutputNodes(line, signal) |
| 250 else: | 273 else: |
| 251 self.GetFailedTarget(line, signal) | 274 self.GetFailedTarget(line, signal) |
| 252 is_build_command_line = False | 275 is_build_command_line = False |
| 253 continue | 276 continue |
| 254 elif self.FAILURE_WITH_ERROR_PATTERN.match(line): | 277 elif self.FAILURE_WITH_ERROR_PATTERN.match(line): |
| 255 # It is possible the target and source file associated with a compile | 278 # It is possible the target and source file associated with a compile |
| 256 # failure is logged outside a 'FAILED: ... 1 error generated' block, | 279 # failure is logged outside a 'FAILED: ... 1 error generated' block, |
| 257 # so extract targets regardless of failure_started. | 280 # so extract targets regardless of failure_started. |
| 258 if not strict_regex: | 281 if not strict_regex: |
| 259 self.GetFailedTarget(line, signal) | 282 self.GetFailedTarget(line, signal) |
| 260 elif (failure_started and | 283 elif (failure_started and |
| 261 (self.ERROR_LINE_END_PATTERN1.match(line) or | 284 (self.ERROR_LINE_END_PATTERN1.match(line) or |
| 262 self.ERROR_LINE_END_PATTERN2.search(line) or | 285 self.ERROR_LINE_END_PATTERN2.search(line) or |
| 263 self.OUTSIDE_FAILURE_LINE_PATTERN.match(line))): | 286 self.OUTSIDE_FAILURE_LINE_PATTERN.match(line))): |
| 264 failure_started = False | 287 failure_started = False |
| 265 elif failure_started and line.startswith( | 288 elif failure_started and line.startswith( |
| 266 self.NINJA_FAILURE_END_LINE_PREFIX): # pragma: no cover | 289 self.NINJA_FAILURE_END_LINE_PREFIX): # pragma: no cover |
| 267 break | 290 break |
| 268 | 291 |
| 269 if failure_started or line.startswith(self.NINJA_ERROR_LINE_PREFIX): | 292 if failure_started or line.startswith(self.NINJA_ERROR_LINE_PREFIX): |
| 270 # either within the compile errors or is a ninja error. | 293 # either within the compile errors or is a ninja error. |
| 271 self.ExtractFiles(line, signal) | 294 self.ExtractFiles(line, signal) |
| 272 | 295 |
| 296 signal.failed_output_nodes = sorted(failed_output_nodes) | |
| 273 return signal | 297 return signal |
| 274 | 298 |
| 275 | 299 |
| 276 class CheckPermExtractor(Extractor): | 300 class CheckPermExtractor(Extractor): |
| 277 """For CheckPerm, only extracts files.""" | 301 """For CheckPerm, only extracts files.""" |
| 278 | 302 |
| 279 def Extract(self, failure_log, *_): | 303 def Extract(self, failure_log, *_): |
| 280 signal = FailureSignal() | 304 signal = FailureSignal() |
| 281 | 305 |
| 282 for line in reversed(failure_log.splitlines()): | 306 for line in reversed(failure_log.splitlines()): |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 def ExtractSignal(master_name, bot_name, step_name, test_name, failure_log): | 549 def ExtractSignal(master_name, bot_name, step_name, test_name, failure_log): |
| 526 """Uses an appropriate extractor to extract failure signals. | 550 """Uses an appropriate extractor to extract failure signals. |
| 527 | 551 |
| 528 Returns: | 552 Returns: |
| 529 A FailureSignal. | 553 A FailureSignal. |
| 530 """ | 554 """ |
| 531 # Fall back to a general-but-maybe-not-accurate extractor. | 555 # Fall back to a general-but-maybe-not-accurate extractor. |
| 532 extractor_class = EXTRACTORS.get(step_name, GeneralExtractor) | 556 extractor_class = EXTRACTORS.get(step_name, GeneralExtractor) |
| 533 return extractor_class().Extract( | 557 return extractor_class().Extract( |
| 534 failure_log, test_name, step_name, bot_name, master_name) | 558 failure_log, test_name, step_name, bot_name, master_name) |
| OLD | NEW |