Skip to content

Commit

Permalink
cmd/govulncheck: make fixup part of a test case
Browse files Browse the repository at this point in the history
Change-Id: I01eeeef443fd0b1e180c90b35240f1f17c211b19
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/571540
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Maceo Thompson <maceothompson@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
  • Loading branch information
zpavlinovic committed Mar 28, 2024
1 parent 84e1906 commit df69562
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 80 deletions.
86 changes: 6 additions & 80 deletions cmd/govulncheck/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"runtime"
"sync"
"testing"
Expand All @@ -33,83 +32,6 @@ import (

var update = flag.Bool("update", false, "update test files with results")

type fixup struct {
pattern string
compiled *regexp.Regexp
replace string
replaceFunc func(b []byte) []byte
}

var fixups = []fixup{
{
// modifies position lines to mask actual line and column with <l> and
// <c> placeholders, resp.
pattern: `\.go:(\d+):(\d+):`,
replace: `.go:<l>:<c>:`,
}, {
// modify position lines in json
pattern: `\"line\":(\s)*(\d+)`,
replace: `"line": <l>`,
}, {
// modify position columns in json
pattern: `\"column\":(\s)*(\d+)`,
replace: `"column": <c>`,
}, {
// modify position offset in json
pattern: `\"offset\":(\s)*(\d+)`,
replace: `"offset": <o>`,
}, {
// There was a one-line change in container/heap/heap.go between 1.18
// and 1.19 that makes the stack traces different. Ignore it.
pattern: `heap\.go:(\d+)`,
replace: `N`,
}, {
pattern: `Scanning your code and (\d+) packages across (\d+)`,
replace: `Scanning your code and P packages across M`,
}, {
pattern: `Scanner: govulncheck@v.*`,
replace: `Scanner: govulncheck@v1.0.0`,
}, {
pattern: `"([^"]*") is a file`,
replace: `govulncheck: myfile is a file`,
}, {
pattern: `"scanner_version": "[^"]*"`,
replace: `"scanner_version": "v0.0.0-00000000000-20000101010101"`,
}, {
pattern: `file:///(.*)/testdata/(.*)/vulndb`,
replace: `testdata/vulndb`,
}, {
pattern: `package (.*) is not in (GOROOT|std) (.*)`,
replace: `package foo is not in GOROOT (/tmp/foo)`,
}, {
pattern: `modified (.*)\)`,
replace: `modified 01 Jan 21 00:00 UTC)`,
}, {
pattern: `Go: (go1.[\.\d]*|devel).*`,
replace: `Go: go1.18`,
}, {
pattern: `"go_version": "go[^\s"]*"`,
replace: `"go_version": "go1.18"`,
},
}

func (f *fixup) init() {
f.compiled = regexp.MustCompile(f.pattern)
}

func (f *fixup) apply(data []byte) []byte {
if f.replaceFunc != nil {
return f.compiled.ReplaceAllFunc(data, f.replaceFunc)
}
return f.compiled.ReplaceAll(data, []byte(f.replace))
}

func init() {
for i := range fixups {
fixups[i].init()
}
}

// testCase models a group of tests in cmd/govulncheck testdata.
type testCase struct {
dir string // subdirectory in testdata containing tests
Expand Down Expand Up @@ -175,6 +97,10 @@ func runTestCase(t *testing.T, testDir string, tc testCase) {
if err != nil {
t.Fatalf("failed to create vulndb url: %v", err)
}
fixups, err := loadFixups(filepath.Join(testCaseDir, "fixups.json"))
if err != nil {
t.Fatalf("failed to load fixups: %v", err)
}

moduleDirs, err := filepath.Glob(filepath.Join(modulesDir, "*"))
if err != nil {
Expand All @@ -196,7 +122,7 @@ func runTestCase(t *testing.T, testDir string, tc testCase) {

os.Setenv("moddir", modulesDir)
os.Setenv("testdir", testfilesDir)
runTestSuite(t, testfilesDir, govulndbURI.String(), *update)
runTestSuite(t, testfilesDir, govulndbURI.String(), fixups, *update)
}

// Limit the number of concurrent scans. Scanning is implemented using
Expand All @@ -220,7 +146,7 @@ var (
// testSuite creates a cmdtest suite from testfilesDir. It also defines
// a govulncheck command on the suite that runs govulncheck against
// vulnerability database available at vulndbDir.
func runTestSuite(t *testing.T, testfilesDir string, vulndbDir string, update bool) {
func runTestSuite(t *testing.T, testfilesDir string, vulndbDir string, fixups []fixup, update bool) {
parallelLimiterInit.Do(func() {
limit := (runtime.GOMAXPROCS(0) + 3) / 4
if limit > 2 && unsafe.Sizeof(uintptr(0)) < 8 {
Expand Down
41 changes: 41 additions & 0 deletions cmd/govulncheck/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
package main

import (
"encoding/json"
"errors"
"os"
"path/filepath"
"regexp"
"testing"
)

Expand Down Expand Up @@ -64,3 +67,41 @@ func copyFile(src, dest string) error {
}
return os.WriteFile(dest, b, 0644)
}

type fixup struct {
Pattern string `json:"pattern,omitempty"`
Replace string `json:"replace,omitempty"`
compiled *regexp.Regexp
replaceFunc func(b []byte) []byte
}

func (f *fixup) init() {
f.compiled = regexp.MustCompile(f.Pattern)
}

func (f *fixup) apply(data []byte) []byte {
if f.replaceFunc != nil {
return f.compiled.ReplaceAllFunc(data, f.replaceFunc)
}
return f.compiled.ReplaceAll(data, []byte(f.Replace))
}

// loadFixups loads and initializes fixups from path. If there is
// nothing at path, returns nil, nil.
func loadFixups(path string) ([]fixup, error) {
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
return nil, nil // no fixups, which is ok
}
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var fixups []fixup
if err := json.Unmarshal(b, &fixups); err != nil {
return nil, err
}
for i := range fixups {
fixups[i].init()
}
return fixups, nil
}
58 changes: 58 additions & 0 deletions cmd/govulncheck/testdata/common/fixups.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"pattern": "\\.go:(\\d+):(\\d+):",
"replace": ".go:\u003cl\u003e:\u003cc\u003e:"
},
{
"pattern": "\\\"line\\\":(\\s)*(\\d+)",
"replace": "\"line\": \u003cl\u003e"
},
{
"pattern": "\\\"column\\\":(\\s)*(\\d+)",
"replace": "\"column\": \u003cc\u003e"
},
{
"pattern": "\\\"offset\\\":(\\s)*(\\d+)",
"replace": "\"offset\": \u003co\u003e"
},
{
"pattern": "heap\\.go:(\\d+)",
"replace": "N"
},
{
"pattern": "Scanning your code and (\\d+) packages across (\\d+)",
"replace": "Scanning your code and P packages across M"
},
{
"pattern": "Scanner: govulncheck@v.*",
"replace": "Scanner: govulncheck@v1.0.0"
},
{
"pattern": "\"([^\"]*\") is a file",
"replace": "govulncheck: myfile is a file"
},
{
"pattern": "\"scanner_version\": \"[^\"]*\"",
"replace": "\"scanner_version\": \"v0.0.0-00000000000-20000101010101\""
},
{
"pattern": "file:///(.*)/testdata/(.*)/vulndb",
"replace": "testdata/vulndb"
},
{
"pattern": "package (.*) is not in (GOROOT|std) (.*)",
"replace": "package foo is not in GOROOT (/tmp/foo)"
},
{
"pattern": "modified (.*)\\)",
"replace": "modified 01 Jan 21 00:00 UTC)"
},
{
"pattern": "Go: (go1.[\\.\\d]*|devel).*",
"replace": "Go: go1.18"
},
{
"pattern": "\"go_version\": \"go[^\\s\"]*\"",
"replace": "\"go_version\": \"go1.18\""
}
]
58 changes: 58 additions & 0 deletions cmd/govulncheck/testdata/stdlib/fixups.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"pattern": "\\.go:(\\d+):(\\d+):",
"replace": ".go:\u003cl\u003e:\u003cc\u003e:"
},
{
"pattern": "\\\"line\\\":(\\s)*(\\d+)",
"replace": "\"line\": \u003cl\u003e"
},
{
"pattern": "\\\"column\\\":(\\s)*(\\d+)",
"replace": "\"column\": \u003cc\u003e"
},
{
"pattern": "\\\"offset\\\":(\\s)*(\\d+)",
"replace": "\"offset\": \u003co\u003e"
},
{
"pattern": "heap\\.go:(\\d+)",
"replace": "N"
},
{
"pattern": "Scanning your code and (\\d+) packages across (\\d+)",
"replace": "Scanning your code and P packages across M"
},
{
"pattern": "Scanner: govulncheck@v.*",
"replace": "Scanner: govulncheck@v1.0.0"
},
{
"pattern": "\"([^\"]*\") is a file",
"replace": "govulncheck: myfile is a file"
},
{
"pattern": "\"scanner_version\": \"[^\"]*\"",
"replace": "\"scanner_version\": \"v0.0.0-00000000000-20000101010101\""
},
{
"pattern": "file:///(.*)/testdata/(.*)/vulndb",
"replace": "testdata/vulndb"
},
{
"pattern": "package (.*) is not in (GOROOT|std) (.*)",
"replace": "package foo is not in GOROOT (/tmp/foo)"
},
{
"pattern": "modified (.*)\\)",
"replace": "modified 01 Jan 21 00:00 UTC)"
},
{
"pattern": "Go: (go1.[\\.\\d]*|devel).*",
"replace": "Go: go1.18"
},
{
"pattern": "\"go_version\": \"go[^\\s\"]*\"",
"replace": "\"go_version\": \"go1.18\""
}
]
58 changes: 58 additions & 0 deletions cmd/govulncheck/testdata/strip/fixups.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
[
{
"pattern": "\\.go:(\\d+):(\\d+):",
"replace": ".go:\u003cl\u003e:\u003cc\u003e:"
},
{
"pattern": "\\\"line\\\":(\\s)*(\\d+)",
"replace": "\"line\": \u003cl\u003e"
},
{
"pattern": "\\\"column\\\":(\\s)*(\\d+)",
"replace": "\"column\": \u003cc\u003e"
},
{
"pattern": "\\\"offset\\\":(\\s)*(\\d+)",
"replace": "\"offset\": \u003co\u003e"
},
{
"pattern": "heap\\.go:(\\d+)",
"replace": "N"
},
{
"pattern": "Scanning your code and (\\d+) packages across (\\d+)",
"replace": "Scanning your code and P packages across M"
},
{
"pattern": "Scanner: govulncheck@v.*",
"replace": "Scanner: govulncheck@v1.0.0"
},
{
"pattern": "\"([^\"]*\") is a file",
"replace": "govulncheck: myfile is a file"
},
{
"pattern": "\"scanner_version\": \"[^\"]*\"",
"replace": "\"scanner_version\": \"v0.0.0-00000000000-20000101010101\""
},
{
"pattern": "file:///(.*)/testdata/(.*)/vulndb",
"replace": "testdata/vulndb"
},
{
"pattern": "package (.*) is not in (GOROOT|std) (.*)",
"replace": "package foo is not in GOROOT (/tmp/foo)"
},
{
"pattern": "modified (.*)\\)",
"replace": "modified 01 Jan 21 00:00 UTC)"
},
{
"pattern": "Go: (go1.[\\.\\d]*|devel).*",
"replace": "Go: go1.18"
},
{
"pattern": "\"go_version\": \"go[^\\s\"]*\"",
"replace": "\"go_version\": \"go1.18\""
}
]

0 comments on commit df69562

Please sign in to comment.