OLD | NEW |
(Empty) | |
| 1 package deduplicator |
| 2 |
| 3 import ( |
| 4 "fmt" |
| 5 |
| 6 "go.skia.org/infra/fuzzer/go/frontend/data" |
| 7 "go.skia.org/infra/go/util" |
| 8 ) |
| 9 |
| 10 const _MAX_STACKTRACE_LINES = 4 |
| 11 |
| 12 type Deduplicator struct { |
| 13 seen map[string]bool |
| 14 } |
| 15 |
| 16 func New() *Deduplicator { |
| 17 return &Deduplicator{ |
| 18 seen: make(map[string]bool), |
| 19 } |
| 20 } |
| 21 |
| 22 func (d *Deduplicator) Clear() { |
| 23 d.seen = make(map[string]bool) |
| 24 } |
| 25 |
| 26 func (d *Deduplicator) IsUnique(report data.FuzzReport) bool { |
| 27 // Empty stacktraces should be manually deduplicated. |
| 28 if report.DebugStackTrace.IsEmpty() && report.ReleaseStackTrace.IsEmpty(
) { |
| 29 return true |
| 30 } |
| 31 // Other flags should also be looked at manually. |
| 32 if util.In("Other", report.DebugFlags) || util.In("Other", report.Releas
eFlags) { |
| 33 return true |
| 34 } |
| 35 if k := key(report); d.seen[k] { |
| 36 return false |
| 37 } else { |
| 38 d.seen[k] = true |
| 39 return true |
| 40 } |
| 41 } |
| 42 |
| 43 func key(r data.FuzzReport) string { |
| 44 ds := trim(r.DebugStackTrace) |
| 45 rs := trim(r.ReleaseStackTrace) |
| 46 return fmt.Sprintf("C:%s,F:%q,F:%q,S:%s,S:%s", r.FuzzCategory, r.DebugFl
ags, r.ReleaseFlags, ds.String(), rs.String()) |
| 47 } |
| 48 |
| 49 // trim returns a copy of the given stacktrace, with the line numbers removed an
d all but the |
| 50 // first _MAX_STACKTRACE_LINES stacktraces removed. |
| 51 func trim(st data.StackTrace) data.StackTrace { |
| 52 if frames := st.Frames; len(frames) > _MAX_STACKTRACE_LINES { |
| 53 st.Frames = st.Frames[0:_MAX_STACKTRACE_LINES] |
| 54 } |
| 55 // copy the frames, so we don't accidentally change the real report. |
| 56 st.Frames = append([]data.StackTraceFrame(nil), st.Frames...) |
| 57 // Remove line numbers from our deduping criteria. |
| 58 for i := range st.Frames { |
| 59 st.Frames[i].LineNumber = 0 |
| 60 } |
| 61 return st |
| 62 } |
OLD | NEW |