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

Side by Side Diff: appengine/findit/waterfall/extractors.py

Issue 1933013003: [Findit] Extract failed output nodes from stdio log of compile step. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Address comments. Created 4 years, 7 months 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 unified diff | Download patch
« no previous file with comments | « no previous file | appengine/findit/waterfall/failure_signal.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 'target': object_file, 206 'target': object_file,
207 'source': source_file 207 'source': source_file
208 }) 208 })
209 else: 209 else:
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 _GetFailedOutputNodes(self, line):
217 """Returns the list of failed output nodes."""
218 # Possible format:
219 # FAILED: obj/path/to/file.o
220 # FAILED: target.exe
221 # FAILED: "target with space in name"
222 failed_output_nodes = []
223
224 while line:
225 quote_index = line.find('"')
226 if quote_index < 0:
227 sub_part = line
228 remaining_part = None
229 else:
230 sub_part = line[:quote_index]
231 match_quote_index = line.find('"', quote_index + 1)
232 if match_quote_index < 0:
233 return [] # Return an empty list for unexpected format.
234 failed_output_nodes.append(
235 line[quote_index + 1: match_quote_index])
236 remaining_part = line[match_quote_index + 1:]
237 line = remaining_part
238
239 for node in sub_part.split(' '):
240 node = node.strip()
241 if node:
242 failed_output_nodes.append(node)
243
244 return failed_output_nodes
245
216 def Extract(self, failure_log, test_name, step_name, bot_name, master_name): 246 def Extract(self, failure_log, test_name, step_name, bot_name, master_name):
217 signal = FailureSignal() 247 signal = FailureSignal()
218 failure_started = False 248 failure_started = False
219 is_build_command_line = False 249 is_build_command_line = False
250 failed_output_nodes = []
220 251
221 if (master_name == self.MAC_MASTER_NAME_FOR_COMPILE and 252 if (master_name == self.MAC_MASTER_NAME_FOR_COMPILE and
222 bot_name in self.IOS_BUILDER_NAMES_FOR_COMPILE): 253 bot_name in self.IOS_BUILDER_NAMES_FOR_COMPILE):
223 error_lines = [] 254 error_lines = []
224 for line in reversed(failure_log.splitlines()): 255 for line in reversed(failure_log.splitlines()):
225 if (not failure_started and 256 if (not failure_started and
226 self.ERROR_LINE_END_PATTERN1.match(line)): 257 self.ERROR_LINE_END_PATTERN1.match(line)):
227 failure_started = True 258 failure_started = True
228 continue 259 continue
229 260
230 if failure_started: 261 if failure_started:
231 if line.startswith(self.IOS_ERROR_LINE_START_PREFIX): 262 if line.startswith(self.IOS_ERROR_LINE_START_PREFIX):
232 failure_started = False 263 failure_started = False
233 for l in error_lines[:-4]: 264 for l in error_lines[:-4]:
234 self.ExtractFiles(l, signal) 265 self.ExtractFiles(l, signal)
235 error_lines = [] 266 error_lines = []
236 else: 267 else:
237 error_lines.append(line) 268 error_lines.append(line)
238 else: 269 else:
239 strict_regex = waterfall_config.EnableStrictRegexForCompileLinkFailures( 270 strict_regex = waterfall_config.EnableStrictRegexForCompileLinkFailures(
240 master_name, bot_name) 271 master_name, bot_name)
241 for line in failure_log.splitlines(): 272 for line in failure_log.splitlines():
242 if line.startswith(self.FAILURE_START_LINE_PREFIX): 273 if line.startswith(self.FAILURE_START_LINE_PREFIX):
243 if not failure_started: 274 if not failure_started:
244 failure_started = True 275 failure_started = True
276 line = line[len(self.FAILURE_START_LINE_PREFIX):]
277 failed_output_nodes.extend(self._GetFailedOutputNodes(line))
245 is_build_command_line = True 278 is_build_command_line = True
246 continue 279 continue
247 elif is_build_command_line: 280 elif is_build_command_line:
248 if strict_regex: 281 if strict_regex:
249 self.ExtractFailedOutputNodes(line, signal) 282 self.ExtractFailedOutputNodes(line, signal)
250 else: 283 else:
251 self.GetFailedTarget(line, signal) 284 self.GetFailedTarget(line, signal)
252 is_build_command_line = False 285 is_build_command_line = False
253 continue 286 continue
254 elif self.FAILURE_WITH_ERROR_PATTERN.match(line): 287 elif self.FAILURE_WITH_ERROR_PATTERN.match(line):
255 # It is possible the target and source file associated with a compile 288 # It is possible the target and source file associated with a compile
256 # failure is logged outside a 'FAILED: ... 1 error generated' block, 289 # failure is logged outside a 'FAILED: ... 1 error generated' block,
257 # so extract targets regardless of failure_started. 290 # so extract targets regardless of failure_started.
258 if not strict_regex: 291 if not strict_regex:
259 self.GetFailedTarget(line, signal) 292 self.GetFailedTarget(line, signal)
260 elif (failure_started and 293 elif (failure_started and
261 (self.ERROR_LINE_END_PATTERN1.match(line) or 294 (self.ERROR_LINE_END_PATTERN1.match(line) or
262 self.ERROR_LINE_END_PATTERN2.search(line) or 295 self.ERROR_LINE_END_PATTERN2.search(line) or
263 self.OUTSIDE_FAILURE_LINE_PATTERN.match(line))): 296 self.OUTSIDE_FAILURE_LINE_PATTERN.match(line))):
264 failure_started = False 297 failure_started = False
265 elif failure_started and line.startswith( 298 elif failure_started and line.startswith(
266 self.NINJA_FAILURE_END_LINE_PREFIX): # pragma: no cover 299 self.NINJA_FAILURE_END_LINE_PREFIX): # pragma: no cover
267 break 300 break
268 301
269 if failure_started or line.startswith(self.NINJA_ERROR_LINE_PREFIX): 302 if failure_started or line.startswith(self.NINJA_ERROR_LINE_PREFIX):
270 # either within the compile errors or is a ninja error. 303 # either within the compile errors or is a ninja error.
271 self.ExtractFiles(line, signal) 304 self.ExtractFiles(line, signal)
272 305
306 signal.failed_output_nodes = sorted(set(failed_output_nodes))
273 return signal 307 return signal
274 308
275 309
276 class CheckPermExtractor(Extractor): 310 class CheckPermExtractor(Extractor):
277 """For CheckPerm, only extracts files.""" 311 """For CheckPerm, only extracts files."""
278 312
279 def Extract(self, failure_log, *_): 313 def Extract(self, failure_log, *_):
280 signal = FailureSignal() 314 signal = FailureSignal()
281 315
282 for line in reversed(failure_log.splitlines()): 316 for line in reversed(failure_log.splitlines()):
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 def ExtractSignal(master_name, bot_name, step_name, test_name, failure_log): 559 def ExtractSignal(master_name, bot_name, step_name, test_name, failure_log):
526 """Uses an appropriate extractor to extract failure signals. 560 """Uses an appropriate extractor to extract failure signals.
527 561
528 Returns: 562 Returns:
529 A FailureSignal. 563 A FailureSignal.
530 """ 564 """
531 # Fall back to a general-but-maybe-not-accurate extractor. 565 # Fall back to a general-but-maybe-not-accurate extractor.
532 extractor_class = EXTRACTORS.get(step_name, GeneralExtractor) 566 extractor_class = EXTRACTORS.get(step_name, GeneralExtractor)
533 return extractor_class().Extract( 567 return extractor_class().Extract(
534 failure_log, test_name, step_name, bot_name, master_name) 568 failure_log, test_name, step_name, bot_name, master_name)
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/waterfall/failure_signal.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698