Skip to content

Commit 516063a

Browse files
committed
bisect, cmd/bisect: add new library and tool
cmd/bisect automates culprit finding in a large set of independent changes that together provoke a failure (either when all enabled or when all disabled, but not both). By repeating a target command with different subsets of the changes enabled, bisect identifies the smallest number of changes that need to be toggled away from the passing state to cause the failing state. Package bisect provides functionality to help target commands that want to support running under cmd/bisect. This is based on work done by khr and drchase in the Go compiler and by drchase in github.com/dr2chase/gossahash, but generalized to support other kinds of targets and simplify the invocation. This tool will be useful for finding call sites where a GODEBUG setting changes a test outcome, as well as source code locations where applying per-iteration loop semantics changes a test outcome. Package bisect could use some direct tests of its own, but it is tested quite a bit via the cmd/bisect test. Change-Id: Id29efad9936bebee17c1475d92cb167019905aa4 Reviewed-on: https://go-review.googlesource.com/c/tools/+/491875 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> gopls-CI: kokoro <noreply+kokoro@google.com> Reviewed-by: David Chase <drchase@google.com>
1 parent 58fedf6 commit 516063a

20 files changed

+2107
-0
lines changed

bisect/bisect.go

Lines changed: 503 additions & 0 deletions
Large diffs are not rendered by default.

bisect/bisect_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package bisect
6+
7+
import (
8+
"os"
9+
"path/filepath"
10+
"strings"
11+
"testing"
12+
)
13+
14+
// In order for package bisect to be copied into the standard library
15+
// and used by very low-level packages such as internal/godebug,
16+
// it needs to have no imports at all.
17+
func TestNoImports(t *testing.T) {
18+
files, err := filepath.Glob("*.go")
19+
if err != nil {
20+
t.Fatal(err)
21+
}
22+
for _, file := range files {
23+
if strings.HasSuffix(file, "_test.go") {
24+
continue
25+
}
26+
data, err := os.ReadFile(file)
27+
if err != nil {
28+
t.Error(err)
29+
continue
30+
}
31+
if strings.Contains(string(data), "\nimport") {
32+
t.Errorf("%s contains imports; package bisect must not import other packages", file)
33+
}
34+
}
35+
}

cmd/bisect/go119.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build !go1.20
6+
7+
package main
8+
9+
import "os/exec"
10+
11+
func cmdInterrupt(cmd *exec.Cmd) {
12+
// cmd.Cancel and cmd.WaitDelay not available before Go 1.20.
13+
}

cmd/bisect/go120.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build go1.20
6+
7+
package main
8+
9+
import (
10+
"os"
11+
"os/exec"
12+
"time"
13+
)
14+
15+
func cmdInterrupt(cmd *exec.Cmd) {
16+
cmd.Cancel = func() error {
17+
// On timeout, send interrupt,
18+
// in hopes of shutting down process tree.
19+
// Ignore errors sending signal; it's all best effort
20+
// and not even implemented on Windows.
21+
// TODO(rsc): Maybe use a new process group and kill the whole group?
22+
cmd.Process.Signal(os.Interrupt)
23+
return nil
24+
}
25+
cmd.WaitDelay = 2 * time.Second
26+
}

0 commit comments

Comments
 (0)