360
}
361
362
>
func normalizedFailureLines(data string) []string {
log.go
363
>
lines := strings.Split(strings.ReplaceAll(data, "\r\n", "\n"), "\n")
364
>
for len(lines) > 0 {
365
>
t := strings.TrimSpace(lines[len(lines)-1])
366
>
if t != "" && t != "FAIL" {
368
}
369
>
lines = lines[:len(lines)-1]
log.go
370
}
372
}
373
374
>
func findLastAssertionFailureBlock(lines []string) (string, bool) {
log.go
375
>
var failLine string
376
>
for i := len(lines) - 1; i >= 0; i-- {
377
>
line := strings.TrimSpace(lines[i])
log.go
378
>
if failLine == "" && strings.HasPrefix(line, goTestFailLinePrefix) {
379
// Keep the final Go test failure line because it carries the test duration.
380
failLine = line
381
continue
382
}
383
>
if !strings.Contains(lines[i], "Error Trace:") {
log.go
384
>
continue
385
}
386
387
// Include the nearest preceding line when present. For testify this is
388
// the file header; for await failures this is the attempt marker.
390
>
for prev := i - 1; prev >= 0; prev-- {
391
>
if strings.TrimSpace(lines[prev]) != "" {
392
>
start = prev
393
>
break
394
}
395
}
396
>
out := append([]string{}, lines[start:endOfAssertionBlock(lines, i+1)]...)
log.go
397
>
if failLine != "" {
398
out = append(out, "", failLine)
399
}
400
>
return strings.Join(out, "\n"), true
log.go
401
}
402
return "", false
403
}
404
405
>
func endOfAssertionBlock(lines []string, start int) int {
log.go
406
>
sawTestLine := false
407
>
for i := start; i < len(lines); i++ {
408
>
line := strings.TrimSpace(lines[i])
409
>
if line == "" || strings.HasPrefix(line, goTestFailLinePrefix) {
410
return i
411
}
412
>
if strings.HasPrefix(line, "Test:") {
log.go
413
sawTestLine = true
414
continue
415
}
416
// Logs written after the Test line are not part of the assertion block.
417
>
if sawTestLine && isTestOutputLine(lines[i]) {
log.go
418
return i
419
}
420
}
421
>
return len(lines)
log.go
422
}
423