mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 03:53:42 +00:00
Add a shim for internal/fuzz
This simply shadows the real code temporarily to see what else is broken. It only defines a single type to fix testing/internal/testdeps.
This commit is contained in:
committed by
Ron Evans
parent
20a27746b2
commit
9cedd78d9c
@@ -0,0 +1,143 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// InternalFuzzTarget is an internal type but exported because it is
|
||||
// cross-package; it is part of the implementation of the "go test" command.
|
||||
type InternalFuzzTarget struct {
|
||||
Name string
|
||||
Fn func(f *F)
|
||||
}
|
||||
|
||||
// F is a type passed to fuzz tests.
|
||||
//
|
||||
// Fuzz tests run generated inputs against a provided fuzz target, which can
|
||||
// find and report potential bugs in the code being tested.
|
||||
//
|
||||
// A fuzz test runs the seed corpus by default, which includes entries provided
|
||||
// by (*F).Add and entries in the testdata/fuzz/<FuzzTestName> directory. After
|
||||
// any necessary setup and calls to (*F).Add, the fuzz test must then call
|
||||
// (*F).Fuzz to provide the fuzz target. See the testing package documentation
|
||||
// for an example, and see the F.Fuzz and F.Add method documentation for
|
||||
// details.
|
||||
//
|
||||
// *F methods can only be called before (*F).Fuzz. Once the test is
|
||||
// executing the fuzz target, only (*T) methods can be used. The only *F methods
|
||||
// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
|
||||
type F struct {
|
||||
common
|
||||
fuzzContext *fuzzContext
|
||||
testContext *testContext
|
||||
|
||||
// inFuzzFn is true when the fuzz function is running. Most F methods cannot
|
||||
// be called when inFuzzFn is true.
|
||||
inFuzzFn bool
|
||||
|
||||
// corpus is a set of seed corpus entries, added with F.Add and loaded
|
||||
// from testdata.
|
||||
corpus []corpusEntry
|
||||
|
||||
result fuzzResult
|
||||
fuzzCalled bool
|
||||
}
|
||||
|
||||
// corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry.
|
||||
// We use a type alias because we don't want to export this type, and we can't
|
||||
// import internal/fuzz from testing.
|
||||
type corpusEntry = struct {
|
||||
Parent string
|
||||
Path string
|
||||
Data []byte
|
||||
Values []interface{}
|
||||
Generation int
|
||||
IsSeed bool
|
||||
}
|
||||
|
||||
// Add will add the arguments to the seed corpus for the fuzz test. This will be
|
||||
// a no-op if called after or within the fuzz target, and args must match the
|
||||
// arguments for the fuzz target.
|
||||
func (f *F) Add(args ...interface{}) {
|
||||
var values []interface{}
|
||||
for i := range args {
|
||||
if t := reflect.TypeOf(args[i]); !supportedTypes[t] {
|
||||
panic(fmt.Sprintf("testing: unsupported type to Add %v", t))
|
||||
}
|
||||
values = append(values, args[i])
|
||||
}
|
||||
f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Path: fmt.Sprintf("seed#%d", len(f.corpus))})
|
||||
}
|
||||
|
||||
// supportedTypes represents all of the supported types which can be fuzzed.
|
||||
var supportedTypes = map[reflect.Type]bool{
|
||||
reflect.TypeOf(([]byte)("")): true,
|
||||
reflect.TypeOf((string)("")): true,
|
||||
reflect.TypeOf((bool)(false)): true,
|
||||
reflect.TypeOf((byte)(0)): true,
|
||||
reflect.TypeOf((rune)(0)): true,
|
||||
reflect.TypeOf((float32)(0)): true,
|
||||
reflect.TypeOf((float64)(0)): true,
|
||||
reflect.TypeOf((int)(0)): true,
|
||||
reflect.TypeOf((int8)(0)): true,
|
||||
reflect.TypeOf((int16)(0)): true,
|
||||
reflect.TypeOf((int32)(0)): true,
|
||||
reflect.TypeOf((int64)(0)): true,
|
||||
reflect.TypeOf((uint)(0)): true,
|
||||
reflect.TypeOf((uint8)(0)): true,
|
||||
reflect.TypeOf((uint16)(0)): true,
|
||||
reflect.TypeOf((uint32)(0)): true,
|
||||
reflect.TypeOf((uint64)(0)): true,
|
||||
}
|
||||
|
||||
// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of
|
||||
// arguments, those arguments will be added to the seed corpus.
|
||||
//
|
||||
// ff must be a function with no return value whose first argument is *T and
|
||||
// whose remaining arguments are the types to be fuzzed.
|
||||
// For example:
|
||||
//
|
||||
// f.Fuzz(func(t *testing.T, b []byte, i int) { ... })
|
||||
//
|
||||
// The following types are allowed: []byte, string, bool, byte, rune, float32,
|
||||
// float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64.
|
||||
// More types may be supported in the future.
|
||||
//
|
||||
// ff must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip. Use
|
||||
// the corresponding *T method instead. The only *F methods that are allowed in
|
||||
// the (*F).Fuzz function are (*F).Failed and (*F).Name.
|
||||
//
|
||||
// This function should be fast and deterministic, and its behavior should not
|
||||
// depend on shared state. No mutatable input arguments, or pointers to them,
|
||||
// should be retained between executions of the fuzz function, as the memory
|
||||
// backing them may be mutated during a subsequent invocation. ff must not
|
||||
// modify the underlying data of the arguments provided by the fuzzing engine.
|
||||
//
|
||||
// When fuzzing, F.Fuzz does not return until a problem is found, time runs out
|
||||
// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz
|
||||
// should be called exactly once, unless F.Skip or F.Fail is called beforehand.
|
||||
func (f *F) Fuzz(ff interface{}) {
|
||||
f.failed = true
|
||||
f.result.N = 0
|
||||
f.result.T = 0
|
||||
f.result.Error = errors.New("operation not implemented")
|
||||
return
|
||||
}
|
||||
|
||||
// fuzzContext holds fields common to all fuzz tests.
|
||||
type fuzzContext struct {
|
||||
deps testDeps
|
||||
mode fuzzMode
|
||||
}
|
||||
|
||||
type fuzzMode uint8
|
||||
|
||||
// fuzzResult contains the results of a fuzz run.
|
||||
type fuzzResult struct {
|
||||
N int // The number of iterations.
|
||||
T time.Duration // The total time taken.
|
||||
Error error // Error is the error from the failing input
|
||||
}
|
||||
@@ -430,15 +430,6 @@ type testDeps interface {
|
||||
MatchString(pat, str string) (bool, error)
|
||||
}
|
||||
|
||||
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
|
||||
Init()
|
||||
return &M{
|
||||
Tests: tests,
|
||||
Benchmarks: benchmarks,
|
||||
deps: deps.(testDeps),
|
||||
}
|
||||
}
|
||||
|
||||
// Run runs the tests. It returns an exit code to pass to os.Exit.
|
||||
func (m *M) Run() (code int) {
|
||||
defer func() {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package testing
|
||||
|
||||
// MainStart is meant for use by tests generated by 'go test'.
|
||||
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
|
||||
// It may change signature from release to release.
|
||||
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, fuzzTargets []InternalFuzzTarget, examples []InternalExample) *M {
|
||||
Init()
|
||||
return &M{
|
||||
Tests: tests,
|
||||
Benchmarks: benchmarks,
|
||||
deps: deps.(testDeps),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package testing
|
||||
|
||||
// MainStart is meant for use by tests generated by 'go test'.
|
||||
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
|
||||
// It may change signature from release to release.
|
||||
func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
|
||||
Init()
|
||||
return &M{
|
||||
Tests: tests,
|
||||
Benchmarks: benchmarks,
|
||||
deps: deps.(testDeps),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user