-
Notifications
You must be signed in to change notification settings - Fork 5
/
bench.go
104 lines (93 loc) · 3.26 KB
/
bench.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import (
"hash/fnv"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/pkg/errors"
)
// expandPackages expands the package filter into all of the packages that it
// references using `go list`.
func expandPackages(pkgFilter []string) ([]string, error) {
args := []string{"go", "list"}
args = append(args, pkgFilter...)
pkgs, err := capture(args...)
if err != nil {
return nil, errors.Wrap(err, "expanding packages")
}
return strings.Split(pkgs, "\n"), nil
}
// testDir returns the directory to store benchdiff artifacts and binaries for
// specified git ref.
func testDir(ref string) string {
return filepath.Join("benchdiff", ref)
}
// testArtifactsDir returns the directory to store benchdiff artifacts for
// specified git ref.
func testArtifactsDir(ref string) string {
return filepath.Join(testDir(ref), "artifacts")
}
func hash(s []string) string {
h := fnv.New32a()
for _, ss := range s {
h.Write([]byte(ss))
}
u := h.Sum32()
return strconv.Itoa(int(u))
}
// testArtifactsDir returns the directory to store benchdiff binaries for
// specified git ref.
func testBinDir(ref string, pkgFilter []string) string {
return filepath.Join(testDir(ref), "bin", hash(pkgFilter))
}
// pkgToTestBin translates a Go package name into a test binary name.
func pkgToTestBin(pkg string) string {
// Strip github.com prefix.
f := strings.TrimPrefix(pkg, "github.com")
// Turn forward-slashes into underscores.
f = strings.ReplaceAll(f, "/", "_")
// Trim leading underscores.
return strings.TrimLeft(f, "_")
}
// testBinToPkg translates a test binary name to a Go package name. This
// tranlation does not round-trip, but comes close enough.
func testBinToPkg(bin string) string {
return strings.ReplaceAll(bin, "_", "/")
}
// buildTestBin builds a test binary for the specified package and moves it to
// the destination directory if successful.
func buildTestBin(pkg, dst string, useBazel bool) (string, bool, error) {
dstFile := pkgToTestBin(pkg) // cockroachdb_cockroach_pkg_util_log
var srcFile string
if !useBazel {
srcFile = dstFile
// Capture to silence warnings from pkgs with no test files.
if _, err := capture("go", "test", "-c", "-o", dstFile, pkg); err != nil {
return "", false, errors.Wrap(err, "building test binary")
}
} else {
relPkg := strings.TrimPrefix(pkg, "github.com/cockroachdb/cockroach/")
pathList := strings.Split(relPkg, string(filepath.Separator)) // ['pkg','util','log']
last := pathList[len(pathList)-1] // 'log'
// `bazel build //pkg/util/log:log_test`.
if _, err := capture("bazel", "build", "//"+relPkg+":"+last+"_test"); err != nil {
return "", false, errors.Wrap(err, "building test binary")
}
// `_bazel/bin/pkg/util/log/log_test_/log_test`.
out := append([]string{"_bazel", "bin"}, pathList...)
out = append(out, last+"_test_", last+"_test")
srcFile = filepath.Join(out...)
}
// If there were no tests in the package, no file will have been created.
if _, err := os.Stat(srcFile); err != nil {
if os.IsNotExist(err) {
return "", false, nil
}
return "", false, errors.Wrap(err, "looking for test binary")
}
if err := spawn("mv", srcFile, filepath.Join(dst, dstFile)); err != nil {
return "", false, errors.Wrap(err, "moving test binary")
}
return dstFile, true, nil
}