|
| 1 | +package testing |
| 2 | + |
| 3 | +// FIXME: These are only the types and functions necessary to compile; they are not properly used or implemented. |
| 4 | + |
| 5 | +import ( |
| 6 | + "errors" |
| 7 | + "fmt" |
| 8 | + "reflect" |
| 9 | + "time" |
| 10 | +) |
| 11 | + |
| 12 | +// InternalFuzzTarget is an internal type but exported because it is |
| 13 | +// cross-package; it is part of the implementation of the "go test" command. |
| 14 | +type InternalFuzzTarget struct { |
| 15 | + Name string |
| 16 | + Fn func(f *F) |
| 17 | +} |
| 18 | + |
| 19 | +// F is a type passed to fuzz tests. |
| 20 | +// |
| 21 | +// Fuzz tests run generated inputs against a provided fuzz target, which can |
| 22 | +// find and report potential bugs in the code being tested. |
| 23 | +// |
| 24 | +// A fuzz test runs the seed corpus by default, which includes entries provided |
| 25 | +// by (*F).Add and entries in the testdata/fuzz/<FuzzTestName> directory. After |
| 26 | +// any necessary setup and calls to (*F).Add, the fuzz test must then call |
| 27 | +// (*F).Fuzz to provide the fuzz target. See the testing package documentation |
| 28 | +// for an example, and see the F.Fuzz and F.Add method documentation for |
| 29 | +// details. |
| 30 | +// |
| 31 | +// *F methods can only be called before (*F).Fuzz. Once the test is |
| 32 | +// executing the fuzz target, only (*T) methods can be used. The only *F methods |
| 33 | +// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name. |
| 34 | +type F struct { |
| 35 | + common |
| 36 | + fuzzContext *fuzzContext |
| 37 | + testContext *testContext |
| 38 | + |
| 39 | + // inFuzzFn is true when the fuzz function is running. Most F methods cannot |
| 40 | + // be called when inFuzzFn is true. |
| 41 | + inFuzzFn bool |
| 42 | + |
| 43 | + // corpus is a set of seed corpus entries, added with F.Add and loaded |
| 44 | + // from testdata. |
| 45 | + corpus []corpusEntry |
| 46 | + |
| 47 | + result fuzzResult |
| 48 | + fuzzCalled bool |
| 49 | +} |
| 50 | + |
| 51 | +// corpusEntry is an alias to the same type as internal/fuzz.CorpusEntry. |
| 52 | +// We use a type alias because we don't want to export this type, and we can't |
| 53 | +// import internal/fuzz from testing. |
| 54 | +type corpusEntry = struct { |
| 55 | + Parent string |
| 56 | + Path string |
| 57 | + Data []byte |
| 58 | + Values []interface{} |
| 59 | + Generation int |
| 60 | + IsSeed bool |
| 61 | +} |
| 62 | + |
| 63 | +// Add will add the arguments to the seed corpus for the fuzz test. This will be |
| 64 | +// a no-op if called after or within the fuzz target, and args must match the |
| 65 | +// arguments for the fuzz target. |
| 66 | +func (f *F) Add(args ...interface{}) { |
| 67 | + var values []interface{} |
| 68 | + for i := range args { |
| 69 | + if t := reflect.TypeOf(args[i]); !supportedTypes[t] { |
| 70 | + panic(fmt.Sprintf("testing: unsupported type to Add %v", t)) |
| 71 | + } |
| 72 | + values = append(values, args[i]) |
| 73 | + } |
| 74 | + f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Path: fmt.Sprintf("seed#%d", len(f.corpus))}) |
| 75 | +} |
| 76 | + |
| 77 | +// supportedTypes represents all of the supported types which can be fuzzed. |
| 78 | +var supportedTypes = map[reflect.Type]bool{ |
| 79 | + reflect.TypeOf(([]byte)("")): true, |
| 80 | + reflect.TypeOf((string)("")): true, |
| 81 | + reflect.TypeOf((bool)(false)): true, |
| 82 | + reflect.TypeOf((byte)(0)): true, |
| 83 | + reflect.TypeOf((rune)(0)): true, |
| 84 | + reflect.TypeOf((float32)(0)): true, |
| 85 | + reflect.TypeOf((float64)(0)): true, |
| 86 | + reflect.TypeOf((int)(0)): true, |
| 87 | + reflect.TypeOf((int8)(0)): true, |
| 88 | + reflect.TypeOf((int16)(0)): true, |
| 89 | + reflect.TypeOf((int32)(0)): true, |
| 90 | + reflect.TypeOf((int64)(0)): true, |
| 91 | + reflect.TypeOf((uint)(0)): true, |
| 92 | + reflect.TypeOf((uint8)(0)): true, |
| 93 | + reflect.TypeOf((uint16)(0)): true, |
| 94 | + reflect.TypeOf((uint32)(0)): true, |
| 95 | + reflect.TypeOf((uint64)(0)): true, |
| 96 | +} |
| 97 | + |
| 98 | +// Fuzz runs the fuzz function, ff, for fuzz testing. If ff fails for a set of |
| 99 | +// arguments, those arguments will be added to the seed corpus. |
| 100 | +// |
| 101 | +// ff must be a function with no return value whose first argument is *T and |
| 102 | +// whose remaining arguments are the types to be fuzzed. |
| 103 | +// For example: |
| 104 | +// |
| 105 | +// f.Fuzz(func(t *testing.T, b []byte, i int) { ... }) |
| 106 | +// |
| 107 | +// The following types are allowed: []byte, string, bool, byte, rune, float32, |
| 108 | +// float64, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64. |
| 109 | +// More types may be supported in the future. |
| 110 | +// |
| 111 | +// ff must not call any *F methods, e.g. (*F).Log, (*F).Error, (*F).Skip. Use |
| 112 | +// the corresponding *T method instead. The only *F methods that are allowed in |
| 113 | +// the (*F).Fuzz function are (*F).Failed and (*F).Name. |
| 114 | +// |
| 115 | +// This function should be fast and deterministic, and its behavior should not |
| 116 | +// depend on shared state. No mutatable input arguments, or pointers to them, |
| 117 | +// should be retained between executions of the fuzz function, as the memory |
| 118 | +// backing them may be mutated during a subsequent invocation. ff must not |
| 119 | +// modify the underlying data of the arguments provided by the fuzzing engine. |
| 120 | +// |
| 121 | +// When fuzzing, F.Fuzz does not return until a problem is found, time runs out |
| 122 | +// (set with -fuzztime), or the test process is interrupted by a signal. F.Fuzz |
| 123 | +// should be called exactly once, unless F.Skip or F.Fail is called beforehand. |
| 124 | +func (f *F) Fuzz(ff interface{}) { |
| 125 | + f.failed = true |
| 126 | + f.result.N = 0 |
| 127 | + f.result.T = 0 |
| 128 | + f.result.Error = errors.New("operation not implemented") |
| 129 | + return |
| 130 | +} |
| 131 | + |
| 132 | +// fuzzContext holds fields common to all fuzz tests. |
| 133 | +type fuzzContext struct { |
| 134 | + deps testDeps |
| 135 | + mode fuzzMode |
| 136 | +} |
| 137 | + |
| 138 | +type fuzzMode uint8 |
| 139 | + |
| 140 | +// fuzzResult contains the results of a fuzz run. |
| 141 | +type fuzzResult struct { |
| 142 | + N int // The number of iterations. |
| 143 | + T time.Duration // The total time taken. |
| 144 | + Error error // Error is the error from the failing input |
| 145 | +} |
0 commit comments