From 0a84219ec0829db2fb2d804eb0a9cbc0c5e6b4b1 Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Wed, 20 Mar 2024 15:36:37 +0100 Subject: syz-ci, pkg/cover: stream coverage from manager to gcs --- pkg/cover/html.go | 6 ++--- pkg/cover/manager_to_ci.go | 51 +++++++++++++++++++++++++++++++++++++++++ pkg/cover/manager_to_ci_test.go | 47 +++++++++++++++++++++++++++++++++++++ pkg/cover/report_test.go | 8 +++---- 4 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 pkg/cover/manager_to_ci.go create mode 100644 pkg/cover/manager_to_ci_test.go (limited to 'pkg') diff --git a/pkg/cover/html.go b/pkg/cover/html.go index bba3dc07b..6e266ebce 100644 --- a/pkg/cover/html.go +++ b/pkg/cover/html.go @@ -211,8 +211,7 @@ func (rg *ReportGenerator) DoRawCoverFiles(w io.Writer, params CoverHandlerParam return nil } -type coverageInfo struct { - Version int `json:"version"` +type CoverageInfo struct { FilePath string `json:"file_path"` FuncName string `json:"func_name"` StartLine int `json:"sl"` @@ -245,8 +244,7 @@ func (rg *ReportGenerator) DoCoverJSONL(w io.Writer, params CoverHandlerParams) } pcProgCount := FileByFrame(fm, &frame).lines[frame.StartLine].pcProgCount hitCount := pcProgCount[frame.PC] - covInfo := &coverageInfo{ - Version: 1, + covInfo := &CoverageInfo{ FilePath: frame.Name, FuncName: frame.FuncName, StartLine: frame.Range.StartLine, diff --git a/pkg/cover/manager_to_ci.go b/pkg/cover/manager_to_ci.go new file mode 100644 index 000000000..4b6f1d9ef --- /dev/null +++ b/pkg/cover/manager_to_ci.go @@ -0,0 +1,51 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package cover + +import ( + "encoding/json" + "fmt" + "io" +) + +// CIDetails fields will be added to every CSV line. +type CIDetails struct { + Version int `json:"version"` + Timestamp string `json:"timestamp"` + FuzzingMinutes int `json:"fuzzing_minutes"` + Arch string `json:"arch"` + BuildID string `json:"build_id"` + Manager string `json:"manager"` + KernelRepo string `json:"kernel_repo"` + KernelBranch string `json:"kernel_branch"` + KernelCommit string `json:"kernel_commit"` +} + +type dbCoverageRecord struct { + CIDetails + CoverageInfo +} + +func writeJSLine(w io.Writer, covInfo dbCoverageRecord) error { + bs, err := json.Marshal(covInfo) + if err != nil { + return fmt.Errorf("failed to marshal covInfo: %w", err) + } + bs = append(bs, '\n') + if _, err = w.Write(bs); err != nil { + return fmt.Errorf("failed to write js data: %w", err) + } + return nil +} + +func WriteCIJSONLine(w io.Writer, managerCover CoverageInfo, ciDetails CIDetails) error { + dbLine := dbCoverageRecord{ + CIDetails: ciDetails, + CoverageInfo: managerCover, + } + if err := writeJSLine(w, dbLine); err != nil { + return fmt.Errorf("failed to serialize func line: %w", err) + } + return nil +} diff --git a/pkg/cover/manager_to_ci_test.go b/pkg/cover/manager_to_ci_test.go new file mode 100644 index 000000000..3bb26beca --- /dev/null +++ b/pkg/cover/manager_to_ci_test.go @@ -0,0 +1,47 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package cover + +import ( + "bytes" + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestWriteCIJSONLine(t *testing.T) { + expectedJSON := + `{"version":1,` + + `"timestamp":"2014-04-14 00:00:00.000",` + + `"fuzzing_minutes":360,` + + `"arch":"x86",` + + `"build_id":"sample_buildid",` + + `"manager":"sample_manager",` + + `"kernel_repo":"sample_repo_path",` + + `"kernel_branch":"",` + + `"kernel_commit":"",` + + `"file_path":"main.c",` + + `"func_name":"main",` + + `"sl":1,"sc":0,"el":1,"ec":-1,` + + `"hit_count":1,` + + `"inline":false,` + + `"pc":12345} +` + + covInfo := CoverageInfo{} + assert.NoError(t, json.Unmarshal(sampleCoverJSON, &covInfo)) + + buf := new(bytes.Buffer) + assert.NoError(t, WriteCIJSONLine(buf, covInfo, CIDetails{ + Version: 1, + Timestamp: "2014-04-14 00:00:00.000", + FuzzingMinutes: 360, + Arch: "x86", + BuildID: "sample_buildid", + Manager: "sample_manager", + KernelRepo: "sample_repo_path", + })) + assert.Equal(t, expectedJSON, buf.String()) +} diff --git a/pkg/cover/report_test.go b/pkg/cover/report_test.go index e9b224fa5..43769cf46 100644 --- a/pkg/cover/report_test.go +++ b/pkg/cover/report_test.go @@ -429,13 +429,13 @@ func checkCSVReport(t *testing.T, CSVReport []byte) { } } +var sampleCoverJSON = []byte(`{"file_path":"main.c","func_name":"main",` + + `"sl":1,"sc":0,"el":1,"ec":-1,"hit_count":1,"inline":false,"pc":12345}`) + // nolint:lll func checkJSONLReport(t *testing.T, r []byte) { - expected := []byte(`{"version":1,"file_path":"main.c","func_name":"main",` + - `"sl":1,"sc":0,"el":1,"ec":-1,"hit_count":1,"inline":false,"pc":12345}`) - compacted := new(bytes.Buffer) - if err := json.Compact(compacted, expected); err != nil { + if err := json.Compact(compacted, sampleCoverJSON); err != nil { t.Errorf("failed to prepare compacted json: %v", err) } compacted.Write([]byte("\n")) -- cgit mrf-deployment