From 77022ee5c2c60e17afaf9ab46ebcb5789725d8ff Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Tue, 5 Mar 2024 12:49:31 +0100 Subject: syz-manager/http.go: implement doCoverJSON --- pkg/cover/html.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++-- pkg/cover/report.go | 6 +++-- 2 files changed, 66 insertions(+), 4 deletions(-) (limited to 'pkg') diff --git a/pkg/cover/html.go b/pkg/cover/html.go index b8249203e..e25c9fbf3 100644 --- a/pkg/cover/html.go +++ b/pkg/cover/html.go @@ -8,7 +8,6 @@ import ( "bytes" "encoding/csv" "encoding/json" - "errors" "fmt" "html" "html/template" @@ -212,8 +211,69 @@ 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) + } + } +} + +// DoCoverJSON is a handler for "/cover&json=1". func (rg *ReportGenerator) DoCoverJSON(w io.Writer, params CoverHandlerParams) error { - return errors.New("DoCoverJSON is not implemented") + 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), + } + } + 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, + }, + } + }) + if err = json.NewEncoder(w).Encode(c); err != nil { + return fmt.Errorf("failed to json.Encode(): %w", err) + } + return nil } func (rg *ReportGenerator) DoRawCover(w io.Writer, params CoverHandlerParams) error { diff --git a/pkg/cover/report.go b/pkg/cover/report.go index 9d03811ad..dd301937e 100644 --- a/pkg/cover/report.go +++ b/pkg/cover/report.go @@ -87,11 +87,13 @@ func coverageCallbackMismatch(debug bool, numPCs int, unmatchedProgPCs map[uint6 len(unmatchedProgPCs), numPCs, debugStr) } -func (rg *ReportGenerator) prepareFileMap(progs []Prog, debug bool) (map[string]*file, error) { +type fileMap map[string]*file + +func (rg *ReportGenerator) prepareFileMap(progs []Prog, debug bool) (fileMap, error) { if err := rg.lazySymbolize(progs); err != nil { return nil, err } - files := make(map[string]*file) + files := make(fileMap) for _, unit := range rg.Units { files[unit.Name] = &file{ module: unit.Module.Name, -- cgit mrf-deployment