GoPLS Viewer

Home|gopls/cmd/signature-fuzzer/fuzz-driver/driver.go
1// Copyright 2021 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// Stand-alone driver for emitting function-signature test code.  This
6// program is mainly just a wrapper around the code that lives in the
7// fuzz-generator package; it is useful for generating a specific bad
8// code scenario for a given seed, or for doing development on the
9// fuzzer, but for doing actual fuzz testing, better to use
10// fuzz-runner.
11
12package main
13
14import (
15    "flag"
16    "fmt"
17    "log"
18    "math/rand"
19    "os"
20    "time"
21
22    generator "golang.org/x/tools/cmd/signature-fuzzer/internal/fuzz-generator"
23)
24
25// Basic options
26var numfcnflag = flag.Int("numfcns"10"Number of test func pairs to emit in each package")
27var numpkgflag = flag.Int("numpkgs"1"Number of test packages to emit")
28var seedflag = flag.Int64("seed", -1"Random seed")
29var tagflag = flag.String("tag""gen""Prefix name of go files/pkgs to generate")
30var outdirflag = flag.String("outdir""""Output directory for generated files")
31var pkgpathflag = flag.String("pkgpath""gen""Base package path for generated files")
32
33// Options used for test case minimization.
34var fcnmaskflag = flag.String("fcnmask""""Mask containing list of fcn numbers to emit")
35var pkmaskflag = flag.String("pkgmask""""Mask containing list of pkg numbers to emit")
36
37// Options used to control which features are used in the generated code.
38var reflectflag = flag.Bool("reflect"true"Include testing of reflect.Call.")
39var deferflag = flag.Bool("defer"true"Include testing of defer stmts.")
40var recurflag = flag.Bool("recur"true"Include testing of recursive calls.")
41var takeaddrflag = flag.Bool("takeaddr"true"Include functions that take the address of their parameters and results.")
42var methodflag = flag.Bool("method"true"Include testing of method calls.")
43var inlimitflag = flag.Int("inmax", -1"Max number of input params.")
44var outlimitflag = flag.Int("outmax", -1"Max number of input params.")
45var pragmaflag = flag.String("pragma""""Tag generated test routines with pragma //go:<value>.")
46var maxfailflag = flag.Int("maxfail"10"Maximum runtime failures before test self-terminates")
47var stackforceflag = flag.Bool("forcestackgrowth"true"Use hooks to force stack growth.")
48
49// Debugging options
50var verbflag = flag.Int("v"0"Verbose trace output level")
51
52// Debugging/testing options. These tell the generator to emit "bad" code so as to
53// test the logic for detecting errors and/or minimization (in the fuzz runner).
54var emitbadflag = flag.Int("emitbad"0"[Testing only] force generator to emit 'bad' code.")
55var selbadpkgflag = flag.Int("badpkgidx"0"[Testing only] select index of bad package (used with -emitbad)")
56var selbadfcnflag = flag.Int("badfcnidx"0"[Testing only] select index of bad function (used with -emitbad)")
57
58// Misc options
59var goimpflag = flag.Bool("goimports"false"Run 'goimports' on generated code.")
60var randctlflag = flag.Int("randctl"generator.RandCtlChecks|generator.RandCtlPanic"Wraprand control flag")
61
62func verb(vlevel ints stringa ...interface{}) {
63    if *verbflag >= vlevel {
64        fmt.Printf(sa...)
65        fmt.Printf("\n")
66    }
67}
68
69func usage(msg string) {
70    if len(msg) > 0 {
71        fmt.Fprintf(os.Stderr"error: %s\n"msg)
72    }
73    fmt.Fprintf(os.Stderr"usage: fuzz-driver [flags]\n\n")
74    flag.PrintDefaults()
75    fmt.Fprintf(os.Stderr"Example:\n\n")
76    fmt.Fprintf(os.Stderr"  fuzz-driver -numpkgs=23 -numfcns=19 -seed 10101 -outdir gendir\n\n")
77    fmt.Fprintf(os.Stderr"  \tgenerates a Go program with 437 test cases (23 packages, each \n")
78    fmt.Fprintf(os.Stderr"  \twith 19 functions, for a total of 437 funcs total) into a set of\n")
79    fmt.Fprintf(os.Stderr"  \tsub-directories in 'gendir', using random see 10101\n")
80
81    os.Exit(2)
82}
83
84func setupTunables() {
85    tunables := generator.DefaultTunables()
86    if !*reflectflag {
87        tunables.DisableReflectionCalls()
88    }
89    if !*deferflag {
90        tunables.DisableDefer()
91    }
92    if !*recurflag {
93        tunables.DisableRecursiveCalls()
94    }
95    if !*takeaddrflag {
96        tunables.DisableTakeAddr()
97    }
98    if !*methodflag {
99        tunables.DisableMethodCalls()
100    }
101    if *inlimitflag != -1 {
102        tunables.LimitInputs(*inlimitflag)
103    }
104    if *outlimitflag != -1 {
105        tunables.LimitOutputs(*outlimitflag)
106    }
107    generator.SetTunables(tunables)
108}
109
110func main() {
111    log.SetFlags(0)
112    log.SetPrefix("fuzz-driver: ")
113    flag.Parse()
114    generator.Verbctl = *verbflag
115    if *outdirflag == "" {
116        usage("select an output directory with -o flag")
117    }
118    verb(1"in main verblevel=%d", *verbflag)
119    if *seedflag == -1 {
120        // user has not selected a specific seed -- pick one.
121        now := time.Now()
122        *seedflag = now.UnixNano() % 123456789
123        verb(0"selected seed: %d", *seedflag)
124    }
125    rand.Seed(*seedflag)
126    if flag.NArg() != 0 {
127        usage("unknown extra arguments")
128    }
129    verb(1"tag is %s", *tagflag)
130
131    fcnmaskerr := generator.ParseMaskString(*fcnmaskflag"fcn")
132    if err != nil {
133        usage(fmt.Sprintf("mangled fcn mask arg: %v"err))
134    }
135    pkmaskerr := generator.ParseMaskString(*pkmaskflag"pkg")
136    if err != nil {
137        usage(fmt.Sprintf("mangled pkg mask arg: %v"err))
138    }
139    verb(2"pkg mask is %v"pkmask)
140    verb(2"fn mask is %v"fcnmask)
141
142    verb(1"starting generation")
143    setupTunables()
144    config := generator.GenConfig{
145        PkgPath:          *pkgpathflag,
146        Tag:              *tagflag,
147        OutDir:           *outdirflag,
148        NumTestPackages:  *numpkgflag,
149        NumTestFunctions: *numfcnflag,
150        Seed:             *seedflag,
151        Pragma:           *pragmaflag,
152        FcnMask:          fcnmask,
153        PkgMask:          pkmask,
154        MaxFail:          *maxfailflag,
155        ForceStackGrowth: *stackforceflag,
156        RandCtl:          *randctlflag,
157        RunGoImports:     *goimpflag,
158        EmitBad:          *emitbadflag,
159        BadPackageIdx:    *selbadpkgflag,
160        BadFuncIdx:       *selbadfcnflag,
161    }
162    errs := generator.Generate(config)
163    if errs != 0 {
164        log.Fatal("errors during generation")
165    }
166    verb(1"... files written to directory %s", *outdirflag)
167    verb(1"leaving main")
168}
169
MembersX
flag
rand
usage.msg
setupTunables
setupTunables.tunables
fmt
time
generator
verb.s
main.pkmask
log
os
usage
main
main.BlockStmt.now
main.config
main.errs
verb
verb.vlevel
verb.a
main.fcnmask
main.err
Members
X