1
0
mirror of https://github.com/golang/go synced 2024-09-30 04:34:33 -06:00

cmd/go: consolidate fuzz-support checks

We had been repeating conditions for specific platforms and
architectures to gate fuzzing tests, but the more of those tests we
add the more we will have to update if the set of supported platforms
and archictures expands over time.

We also ought to provide a friendlier error message when
'go test -fuzz' is used on non-supported platforms.

This change adds predicates in cmd/internal/sys, which already
contains similar predicates for related functionality (such as the
race detector), and uses those predicates in 'go test' and TestScript.

For #48495

Change-Id: If24c3997aeb4d201258e21e5b6cf4f7c08fbadd7
Reviewed-on: https://go-review.googlesource.com/c/go/+/359481
Trust: Bryan C. Mills <bcmills@google.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
This commit is contained in:
Bryan C. Mills 2021-10-28 15:00:33 -04:00
parent 834e36ec77
commit e741e2fe0e
28 changed files with 96 additions and 80 deletions

View File

@ -43,10 +43,12 @@ func init() {
}
var (
canRace = false // whether we can run the race detector
canCgo = false // whether we can use cgo
canMSan = false // whether we can run the memory sanitizer
canASan = false // whether we can run the address sanitizer
canRace = false // whether we can run the race detector
canCgo = false // whether we can use cgo
canMSan = false // whether we can run the memory sanitizer
canASan = false // whether we can run the address sanitizer
canFuzz = false // whether we can search for new fuzz failures
fuzzInstrumented = false // whether fuzzing uses instrumentation
)
var exeSuffix string = func() string {
@ -206,6 +208,8 @@ func TestMain(m *testing.M) {
if isAlpineLinux() || runtime.Compiler == "gccgo" {
canRace = false
}
canFuzz = sys.FuzzSupported(runtime.GOOS, runtime.GOARCH)
fuzzInstrumented = sys.FuzzInstrumented(runtime.GOOS, runtime.GOARCH)
}
// Don't let these environment variables confuse the test.
os.Setenv("GOENV", "off")

View File

@ -31,9 +31,10 @@ import (
"cmd/go/internal/lockedfile"
"cmd/go/internal/modload"
"cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/go/internal/trace"
"cmd/go/internal/work"
"cmd/go/internal/str"
"cmd/internal/sys"
"cmd/internal/test2json"
)
@ -651,8 +652,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
if testO != "" && len(pkgs) != 1 {
base.Fatalf("cannot use -o flag with multiple packages")
}
if testFuzz != "" && len(pkgs) != 1 {
base.Fatalf("cannot use -fuzz flag with multiple packages")
if testFuzz != "" {
if !sys.FuzzSupported(cfg.Goos, cfg.Goarch) {
base.Fatalf("-fuzz flag is not supported on %s/%s", cfg.Goos, cfg.Goarch)
}
if len(pkgs) != 1 {
base.Fatalf("cannot use -fuzz flag with multiple packages")
}
}
if testProfile() != "" && len(pkgs) != 1 {
base.Fatalf("cannot use %s flag with multiple packages", testProfile())

View File

@ -67,20 +67,7 @@ func BuildInit() {
// instrumentation is added. 'go test -fuzz' still works without coverage,
// but it generates random inputs without guidance, so it's much less effective.
func fuzzInstrumentFlags() []string {
// TODO: expand the set of supported platforms, with testing. Nothing about
// the instrumentation is OS specific, but only amd64 and arm64 are
// supported in the runtime. See src/runtime/libfuzzer*.
//
// Keep in sync with build constraints in
// internal/fuzz/counters_{un,}supported.go
switch cfg.Goos {
case "darwin", "freebsd", "linux", "windows":
default:
return nil
}
switch cfg.Goarch {
case "amd64", "arm64":
default:
if !sys.FuzzInstrumented(cfg.Goos, cfg.Goarch) {
return nil
}
return []string{"-d=libfuzzer"}

View File

@ -357,6 +357,10 @@ Script:
ok = canASan
case "race":
ok = canRace
case "fuzz":
ok = canFuzz
case "fuzz-instrumented":
ok = fuzzInstrumented
case "net":
ok = testenv.HasExternalNetwork()
case "link":

View File

@ -80,6 +80,8 @@ should only run when the condition is satisfied. The available conditions are:
- Test environment details:
- [short] for testing.Short()
- [cgo], [msan], [asan], [race] for whether cgo, msan, asan, and the race detector can be used
- [fuzz] for whether 'go test -fuzz' can be used at all
- [fuzz-instrumented] for whether 'go test -fuzz' uses coverage-instrumented binaries
- [net] for whether the external network can be used
- [link] for testenv.HasLink()
- [root] for os.Geteuid() == 0

View File

@ -1,5 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
# Test that running a fuzz target that returns without failing or calling
# f.Fuzz fails and causes a non-zero exit status.
@ -495,4 +494,4 @@ go test fuzz v1
[]byte("12345")
-- corpustesting/testdata/fuzz/FuzzWrongType/1 --
go test fuzz v1
int("00000")
int("00000")

View File

@ -1,9 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
# Instrumentation not supported on other archs.
# See #14565.
[!amd64] [!arm64] skip
[!fuzz-instrumented] skip
[short] skip
env GOCACHE=$WORK/cache

View File

@ -1,6 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# Run chatty fuzz targets with an error.

View File

@ -1,5 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# Cleanup should run after F.Skip.

View File

@ -1,6 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# The fuzz function should be able to detect whether -timeout

View File

@ -1,6 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# There are no seed values, so 'go test' should finish quickly.

View File

@ -6,7 +6,7 @@
# This is unlikely, but possible. It's difficult to simulate interruptions
# due to ^C and EOF errors which are more common. We don't report those.
[short] skip
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
# If the I/O error occurs before F.Fuzz is called, the coordinator should
# stop the worker and say that.

View File

@ -1,5 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
# Matches only fuzz targets to test.
go test standalone_fuzz_test.go

View File

@ -1,6 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# We clean the fuzz cache during this test. Don't clean the user's cache.

View File

@ -1,8 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
# Instrumentation only supported on 64-bit architectures.
[!amd64] [!arm64] skip
[!fuzz-instrumented] skip
# Test that when an interesting value is discovered (one that expands coverage),
# the fuzzing engine minimizes it before writing it to the cache.

View File

@ -2,9 +2,7 @@
# enabled, and multiple package or multiple fuzz targets match.
# TODO(#46312): support fuzzing multiple targets in multiple packages.
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# With fuzzing disabled, multiple targets can be tested.

View File

@ -1,5 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
# Tests that a crash caused by a mutator-discovered input writes the bad input
# to testdata, and fails+reports correctly. This tests the end-to-end behavior

View File

@ -1,5 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
# Check that if a worker does not call F.Fuzz or calls F.Fail first,
# 'go test' exits non-zero and no crasher is recorded.

View File

@ -1,5 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
# Test basic fuzzing mutator behavior.
#

View File

@ -1,7 +1,7 @@
# NOTE: this test is skipped on Windows, since there's no concept of signals.
# When a process terminates another process, it provides an exit code.
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!freebsd] [!linux] skip
[windows] skip
[!fuzz] skip
[short] skip
# FuzzNonCrash sends itself a signal that does not appear to be a crash.

View File

@ -1,6 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
# When running seed inputs, T.Parallel should let multiple inputs run in

View File

@ -1,6 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
[!fuzz] skip
[short] skip
env GOCACHE=$WORK/cache
@ -142,4 +140,4 @@ go test fuzz v1
string("fails")
-- testdata/fuzz/FuzzFoo/thispasses --
go test fuzz v1
string("passes")
string("passes")

View File

@ -1,10 +1,4 @@
# TODO(jayconrod): support shared memory on more platforms.
[!darwin] [!linux] [!windows] skip
# Instrumentation not supported on other archs.
# See #14565.
[!amd64] [!arm64] skip
[!fuzz-instrumented] skip
[short] skip
env GOCACHE=$WORK/cache
@ -206,4 +200,4 @@ go test fuzz v1
int(10)
-- cache-file-bytes --
go test fuzz v1
[]byte("11111111111111111111")
[]byte("11111111111111111111")

View File

@ -1,5 +1,5 @@
[!fuzz] skip
[short] skip
[!darwin] [!linux] [!windows] skip
go test -fuzz=FuzzA -fuzztime=100x fuzz_setenv_test.go

View File

@ -0,0 +1,18 @@
[fuzz] skip
! go test -fuzz=. -fuzztime=1x
! stdout .
stderr '^-fuzz flag is not supported on '$GOOS'/'$GOARCH'$'
-- go.mod --
module example
go 1.18
-- fuzz_test.go --
package example
import "testing"
func FuzzTrivial(f *testing.F) {
f.Fuzz(func(t *testing.T, _ []byte) {})
}

View File

@ -45,6 +45,29 @@ func ASanSupported(goos, goarch string) bool {
}
}
// FuzzSupported reports whether goos/goarch supports fuzzing
// ('go test -fuzz=.').
func FuzzSupported(goos, goarch string) bool {
switch goos {
case "darwin", "linux", "windows":
return true
default:
return false
}
}
// FuzzInstrumented reports whether fuzzing on goos/goarch uses coverage
// instrumentation. (FuzzInstrumented implies FuzzSupported.)
func FuzzInstrumented(goos, goarch string) bool {
switch goarch {
case "amd64", "arm64":
// TODO(#14565): support more architectures.
return FuzzSupported(goos, goarch)
default:
return false
}
}
// MustLinkExternal reports whether goos/goarch requires external linking.
// (This is the opposite of internal/testenv.CanInternalLink. Keep them in sync.)
func MustLinkExternal(goos, goarch string) bool {

View File

@ -2,6 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// TODO: expand the set of supported platforms, with testing. Nothing about
// the instrumentation is OS specific, but only amd64 and arm64 are
// supported in the runtime. See src/runtime/libfuzzer*.
//
// If you update this constraint, also update cmd/internal/sys.FuzzInstrumeted.
//
//go:build !((darwin || linux || windows || freebsd) && (amd64 || arm64))
package fuzz

View File

@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// TODO(jayconrod): support more platforms.
// If you update this constraint, also update cmd/internal/sys.FuzzSupported.
//
//go:build !darwin && !linux && !windows
package fuzz