github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/pkg/report/title_stat.go (about) 1 // Copyright 2025 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package report 5 6 import ( 7 "encoding/json" 8 "errors" 9 "fmt" 10 "maps" 11 "os" 12 ) 13 14 func AddTitleStat(file string, reps []*Report) error { 15 var titles []string 16 for _, rep := range reps { 17 titles = append(titles, rep.Title) 18 } 19 stat, err := ReadStatFile(file) 20 if err != nil { 21 return fmt.Errorf("report.ReadStatFile: %w", err) 22 } 23 stat.add(titles) 24 if err := writeStatFile(file, stat); err != nil { 25 return fmt.Errorf("writeStatFile: %w", err) 26 } 27 return nil 28 } 29 30 func ReadStatFile(file string) (*titleStat, error) { 31 stat := &titleStat{} 32 if _, err := os.Stat(file); errors.Is(err, os.ErrNotExist) { 33 return stat, nil 34 } 35 data, err := os.ReadFile(file) 36 if err != nil { 37 return nil, err 38 } 39 if len(data) == 0 { 40 return stat, nil 41 } 42 if err := json.Unmarshal(data, stat); err != nil { 43 return nil, err 44 } 45 return stat, nil 46 } 47 48 func writeStatFile(file string, stat *titleStat) error { 49 data, err := json.MarshalIndent(stat, "", "\t") 50 if err != nil { 51 return err 52 } 53 if err := os.WriteFile(file, data, 0644); err != nil { 54 return err 55 } 56 return nil 57 } 58 59 type titleStatNodes map[string]*titleStat 60 61 type titleStat struct { 62 Count int 63 Nodes titleStatNodes 64 } 65 66 func (ts *titleStat) add(reps []string) { 67 if len(reps) == 0 { 68 return 69 } 70 if ts.Nodes == nil { 71 ts.Nodes = make(titleStatNodes) 72 } 73 if ts.Nodes[reps[0]] == nil { 74 ts.Nodes[reps[0]] = &titleStat{} 75 } 76 ts.Nodes[reps[0]].Count++ 77 ts.Nodes[reps[0]].add(reps[1:]) 78 } 79 80 func (ts *titleStat) visit(cb func(int, ...string), titles ...string) { 81 if len(ts.Nodes) == 0 { 82 cb(ts.Count, titles...) 83 return 84 } 85 for title := range maps.Keys(ts.Nodes) { 86 ts.Nodes[title].visit(cb, append(titles, title)...) 87 } 88 }