aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/cover/html.go
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2024-03-15 11:13:29 +0100
committerTaras Madan <tarasmadan@google.com>2024-03-19 11:15:33 +0000
commite104824c06ba54122c1d17b5b26dd21c57e427b6 (patch)
tree3ee1c9f7210e8fc7d5afa2a9eb9b2fadb07bb76b /pkg/cover/html.go
parent41ee133f71cd3d24faeac9b158c749637acb8e8d (diff)
pkg/cover: export the frames data as jsonl
jsonl is new-line-new-json format. It is good for streaming because you can read data line-by-line. This pipeline will stream a lot eventually (x00 megabytes).
Diffstat (limited to 'pkg/cover/html.go')
-rw-r--r--pkg/cover/html.go85
1 files changed, 34 insertions, 51 deletions
diff --git a/pkg/cover/html.go b/pkg/cover/html.go
index e25c9fbf3..1411bdf62 100644
--- a/pkg/cover/html.go
+++ b/pkg/cover/html.go
@@ -211,67 +211,50 @@ func (rg *ReportGenerator) DoRawCoverFiles(w io.Writer, params CoverHandlerParam
return nil
}
-type covCallbacksStat struct {
- TotalCount int `json:"total_cb_count"`
- CoveredCount int `json:"covered_cb_count"`
-}
-
-type covFuncDetails struct {
- covCallbacksStat
-}
-
-type covFileDetails struct {
- covCallbacksStat
- Functions map[string]*covFuncDetails `json:"functions,omitempty"`
-}
-
type coverageInfo struct {
- Version int `json:"version"`
- covCallbacksStat
- Files map[string]*covFileDetails `json:"files,omitempty"`
-}
-
-type visitFuncCb func(filePath, funcName string, funcObj *function)
-
-func forEachFunction(fm fileMap, cb visitFuncCb) {
- for filePath, fileObj := range fm {
- for _, funcObj := range fileObj.functions {
- cb(filePath, funcObj.name, funcObj)
- }
- }
+ Version int `json:"version"`
+ FilePath string `json:"file_path"`
+ FuncName string `json:"func_name"`
+ StartLine int `json:"sl"`
+ StartCol int `json:"sc"`
+ EndLine int `json:"el"`
+ EndCol int `json:"ec"`
+ HitCount int `json:"hit_count"`
+ Inline bool `json:"inline"`
+ PC uint64 `json:"pc"`
}
-// DoCoverJSON is a handler for "/cover&json=1".
-func (rg *ReportGenerator) DoCoverJSON(w io.Writer, params CoverHandlerParams) error {
+// DoCoverJSONL is a handler for "/cover?jsonl=1".
+func (rg *ReportGenerator) DoCoverJSONL(w io.Writer, params CoverHandlerParams) error {
var progs = fixUpPCs(rg.target.Arch, params.Progs, params.CoverFilter)
fm, err := rg.prepareFileMap(progs, params.Debug)
if err != nil {
return fmt.Errorf("failed to rg.prepareFileMap(): %w", err)
}
- c := &coverageInfo{
- Version: 1,
- Files: make(map[string]*covFileDetails),
- }
- forEachFunction(fm, func(filePath, funcName string, funcObj *function) {
- if _, ok := c.Files[filePath]; !ok {
- c.Files[filePath] = &covFileDetails{
- Functions: make(map[string]*covFuncDetails),
- }
+
+ encoder := json.NewEncoder(w)
+ for _, frame := range rg.Frames {
+ endCol := frame.Range.EndCol
+ if endCol == backend.LineEnd {
+ endCol = -1
}
- c.TotalCount += funcObj.pcs
- c.CoveredCount += funcObj.covered
- fileCbStat := c.Files[filePath]
- fileCbStat.TotalCount += funcObj.pcs
- fileCbStat.CoveredCount += funcObj.covered
- fileCbStat.Functions[funcName] = &covFuncDetails{
- covCallbacksStat: covCallbacksStat{
- TotalCount: funcObj.pcs,
- CoveredCount: funcObj.covered,
- },
+ pcProgCount := FileByFrame(fm, &frame).lines[frame.StartLine].pcProgCount
+ hitCount := pcProgCount[frame.PC]
+ covInfo := &coverageInfo{
+ Version: 1,
+ FilePath: frame.Name,
+ FuncName: frame.FuncName,
+ StartLine: frame.Range.StartLine,
+ StartCol: frame.Range.StartCol,
+ EndLine: frame.Range.EndLine,
+ EndCol: endCol,
+ HitCount: hitCount,
+ Inline: frame.Inline,
+ PC: frame.PC,
+ }
+ if err = encoder.Encode(covInfo); err != nil {
+ return fmt.Errorf("failed to json.Encode(): %w", err)
}
- })
- if err = json.NewEncoder(w).Encode(c); err != nil {
- return fmt.Errorf("failed to json.Encode(): %w", err)
}
return nil
}