1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2015 Google Inc. All rights reserved. 2*1fa6dee9SAndroid Build Coastguard Worker// 3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*1fa6dee9SAndroid Build Coastguard Worker// 7*1fa6dee9SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*1fa6dee9SAndroid Build Coastguard Worker// 9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License. 14*1fa6dee9SAndroid Build Coastguard Worker 15*1fa6dee9SAndroid Build Coastguard Workerpackage main 16*1fa6dee9SAndroid Build Coastguard Worker 17*1fa6dee9SAndroid Build Coastguard Workerimport ( 18*1fa6dee9SAndroid Build Coastguard Worker "bytes" 19*1fa6dee9SAndroid Build Coastguard Worker "flag" 20*1fa6dee9SAndroid Build Coastguard Worker "fmt" 21*1fa6dee9SAndroid Build Coastguard Worker "go/ast" 22*1fa6dee9SAndroid Build Coastguard Worker "go/doc" 23*1fa6dee9SAndroid Build Coastguard Worker "go/parser" 24*1fa6dee9SAndroid Build Coastguard Worker "go/token" 25*1fa6dee9SAndroid Build Coastguard Worker "io/ioutil" 26*1fa6dee9SAndroid Build Coastguard Worker "os" 27*1fa6dee9SAndroid Build Coastguard Worker "reflect" 28*1fa6dee9SAndroid Build Coastguard Worker "sort" 29*1fa6dee9SAndroid Build Coastguard Worker "strings" 30*1fa6dee9SAndroid Build Coastguard Worker "testing" 31*1fa6dee9SAndroid Build Coastguard Worker "text/template" 32*1fa6dee9SAndroid Build Coastguard Worker) 33*1fa6dee9SAndroid Build Coastguard Worker 34*1fa6dee9SAndroid Build Coastguard Workervar ( 35*1fa6dee9SAndroid Build Coastguard Worker output = flag.String("o", "", "output filename") 36*1fa6dee9SAndroid Build Coastguard Worker pkg = flag.String("pkg", "", "test package") 37*1fa6dee9SAndroid Build Coastguard Worker exitCode = 0 38*1fa6dee9SAndroid Build Coastguard Worker) 39*1fa6dee9SAndroid Build Coastguard Worker 40*1fa6dee9SAndroid Build Coastguard Workertype data struct { 41*1fa6dee9SAndroid Build Coastguard Worker Package string 42*1fa6dee9SAndroid Build Coastguard Worker Tests []string 43*1fa6dee9SAndroid Build Coastguard Worker Examples []*doc.Example 44*1fa6dee9SAndroid Build Coastguard Worker HasMain bool 45*1fa6dee9SAndroid Build Coastguard Worker MainStartTakesFuzzers bool 46*1fa6dee9SAndroid Build Coastguard Worker} 47*1fa6dee9SAndroid Build Coastguard Worker 48*1fa6dee9SAndroid Build Coastguard Workerfunc findTests(srcs []string) (tests []string, examples []*doc.Example, hasMain bool) { 49*1fa6dee9SAndroid Build Coastguard Worker for _, src := range srcs { 50*1fa6dee9SAndroid Build Coastguard Worker f, err := parser.ParseFile(token.NewFileSet(), src, nil, parser.ParseComments) 51*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 52*1fa6dee9SAndroid Build Coastguard Worker panic(err) 53*1fa6dee9SAndroid Build Coastguard Worker } 54*1fa6dee9SAndroid Build Coastguard Worker for _, obj := range f.Scope.Objects { 55*1fa6dee9SAndroid Build Coastguard Worker if obj.Kind != ast.Fun || !strings.HasPrefix(obj.Name, "Test") { 56*1fa6dee9SAndroid Build Coastguard Worker continue 57*1fa6dee9SAndroid Build Coastguard Worker } 58*1fa6dee9SAndroid Build Coastguard Worker if obj.Name == "TestMain" { 59*1fa6dee9SAndroid Build Coastguard Worker hasMain = true 60*1fa6dee9SAndroid Build Coastguard Worker } else { 61*1fa6dee9SAndroid Build Coastguard Worker tests = append(tests, obj.Name) 62*1fa6dee9SAndroid Build Coastguard Worker } 63*1fa6dee9SAndroid Build Coastguard Worker } 64*1fa6dee9SAndroid Build Coastguard Worker 65*1fa6dee9SAndroid Build Coastguard Worker examples = append(examples, doc.Examples(f)...) 66*1fa6dee9SAndroid Build Coastguard Worker } 67*1fa6dee9SAndroid Build Coastguard Worker sort.Strings(tests) 68*1fa6dee9SAndroid Build Coastguard Worker return 69*1fa6dee9SAndroid Build Coastguard Worker} 70*1fa6dee9SAndroid Build Coastguard Worker 71*1fa6dee9SAndroid Build Coastguard Worker// Returns true for go1.18+, where testing.MainStart takes an extra slice of fuzzers. 72*1fa6dee9SAndroid Build Coastguard Workerfunc mainStartTakesFuzzers() bool { 73*1fa6dee9SAndroid Build Coastguard Worker return reflect.TypeOf(testing.MainStart).NumIn() > 4 74*1fa6dee9SAndroid Build Coastguard Worker} 75*1fa6dee9SAndroid Build Coastguard Worker 76*1fa6dee9SAndroid Build Coastguard Workerfunc main() { 77*1fa6dee9SAndroid Build Coastguard Worker flag.Parse() 78*1fa6dee9SAndroid Build Coastguard Worker 79*1fa6dee9SAndroid Build Coastguard Worker if flag.NArg() == 0 { 80*1fa6dee9SAndroid Build Coastguard Worker fmt.Fprintln(os.Stderr, "error: must pass at least one input") 81*1fa6dee9SAndroid Build Coastguard Worker exitCode = 1 82*1fa6dee9SAndroid Build Coastguard Worker return 83*1fa6dee9SAndroid Build Coastguard Worker } 84*1fa6dee9SAndroid Build Coastguard Worker 85*1fa6dee9SAndroid Build Coastguard Worker buf := &bytes.Buffer{} 86*1fa6dee9SAndroid Build Coastguard Worker 87*1fa6dee9SAndroid Build Coastguard Worker tests, examples, hasMain := findTests(flag.Args()) 88*1fa6dee9SAndroid Build Coastguard Worker 89*1fa6dee9SAndroid Build Coastguard Worker d := data{ 90*1fa6dee9SAndroid Build Coastguard Worker Package: *pkg, 91*1fa6dee9SAndroid Build Coastguard Worker Tests: tests, 92*1fa6dee9SAndroid Build Coastguard Worker Examples: examples, 93*1fa6dee9SAndroid Build Coastguard Worker HasMain: hasMain, 94*1fa6dee9SAndroid Build Coastguard Worker MainStartTakesFuzzers: mainStartTakesFuzzers(), 95*1fa6dee9SAndroid Build Coastguard Worker } 96*1fa6dee9SAndroid Build Coastguard Worker 97*1fa6dee9SAndroid Build Coastguard Worker err := testMainTmpl.Execute(buf, d) 98*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 99*1fa6dee9SAndroid Build Coastguard Worker panic(err) 100*1fa6dee9SAndroid Build Coastguard Worker } 101*1fa6dee9SAndroid Build Coastguard Worker 102*1fa6dee9SAndroid Build Coastguard Worker err = ioutil.WriteFile(*output, buf.Bytes(), 0666) 103*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 104*1fa6dee9SAndroid Build Coastguard Worker panic(err) 105*1fa6dee9SAndroid Build Coastguard Worker } 106*1fa6dee9SAndroid Build Coastguard Worker} 107*1fa6dee9SAndroid Build Coastguard Worker 108*1fa6dee9SAndroid Build Coastguard Workervar testMainTmpl = template.Must(template.New("testMain").Parse(` 109*1fa6dee9SAndroid Build Coastguard Workerpackage main 110*1fa6dee9SAndroid Build Coastguard Worker 111*1fa6dee9SAndroid Build Coastguard Workerimport ( 112*1fa6dee9SAndroid Build Coastguard Worker "io" 113*1fa6dee9SAndroid Build Coastguard Worker{{if not .HasMain}} 114*1fa6dee9SAndroid Build Coastguard Worker "os" 115*1fa6dee9SAndroid Build Coastguard Worker{{end}} 116*1fa6dee9SAndroid Build Coastguard Worker "reflect" 117*1fa6dee9SAndroid Build Coastguard Worker "regexp" 118*1fa6dee9SAndroid Build Coastguard Worker "testing" 119*1fa6dee9SAndroid Build Coastguard Worker "time" 120*1fa6dee9SAndroid Build Coastguard Worker 121*1fa6dee9SAndroid Build Coastguard Worker pkg "{{.Package}}" 122*1fa6dee9SAndroid Build Coastguard Worker) 123*1fa6dee9SAndroid Build Coastguard Worker 124*1fa6dee9SAndroid Build Coastguard Workervar t = []testing.InternalTest{ 125*1fa6dee9SAndroid Build Coastguard Worker{{range .Tests}} 126*1fa6dee9SAndroid Build Coastguard Worker {"{{.}}", pkg.{{.}}}, 127*1fa6dee9SAndroid Build Coastguard Worker{{end}} 128*1fa6dee9SAndroid Build Coastguard Worker} 129*1fa6dee9SAndroid Build Coastguard Worker 130*1fa6dee9SAndroid Build Coastguard Workervar e = []testing.InternalExample{ 131*1fa6dee9SAndroid Build Coastguard Worker{{range .Examples}} 132*1fa6dee9SAndroid Build Coastguard Worker {{if or .Output .EmptyOutput}} 133*1fa6dee9SAndroid Build Coastguard Worker {"{{.Name}}", pkg.Example{{.Name}}, {{.Output | printf "%q" }}, {{.Unordered}}}, 134*1fa6dee9SAndroid Build Coastguard Worker {{end}} 135*1fa6dee9SAndroid Build Coastguard Worker{{end}} 136*1fa6dee9SAndroid Build Coastguard Worker} 137*1fa6dee9SAndroid Build Coastguard Worker 138*1fa6dee9SAndroid Build Coastguard Workervar matchPat string 139*1fa6dee9SAndroid Build Coastguard Workervar matchRe *regexp.Regexp 140*1fa6dee9SAndroid Build Coastguard Worker 141*1fa6dee9SAndroid Build Coastguard Workertype matchString struct{} 142*1fa6dee9SAndroid Build Coastguard Worker 143*1fa6dee9SAndroid Build Coastguard Workerfunc MatchString(pat, str string) (result bool, err error) { 144*1fa6dee9SAndroid Build Coastguard Worker if matchRe == nil || matchPat != pat { 145*1fa6dee9SAndroid Build Coastguard Worker matchPat = pat 146*1fa6dee9SAndroid Build Coastguard Worker matchRe, err = regexp.Compile(matchPat) 147*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 148*1fa6dee9SAndroid Build Coastguard Worker return 149*1fa6dee9SAndroid Build Coastguard Worker } 150*1fa6dee9SAndroid Build Coastguard Worker } 151*1fa6dee9SAndroid Build Coastguard Worker return matchRe.MatchString(str), nil 152*1fa6dee9SAndroid Build Coastguard Worker} 153*1fa6dee9SAndroid Build Coastguard Worker 154*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) MatchString(pat, str string) (bool, error) { 155*1fa6dee9SAndroid Build Coastguard Worker return MatchString(pat, str) 156*1fa6dee9SAndroid Build Coastguard Worker} 157*1fa6dee9SAndroid Build Coastguard Worker 158*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) StartCPUProfile(w io.Writer) error { 159*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 160*1fa6dee9SAndroid Build Coastguard Worker} 161*1fa6dee9SAndroid Build Coastguard Worker 162*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) StopCPUProfile() { 163*1fa6dee9SAndroid Build Coastguard Worker} 164*1fa6dee9SAndroid Build Coastguard Worker 165*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) WriteHeapProfile(w io.Writer) error { 166*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 167*1fa6dee9SAndroid Build Coastguard Worker} 168*1fa6dee9SAndroid Build Coastguard Worker 169*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) WriteProfileTo(string, io.Writer, int) error { 170*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 171*1fa6dee9SAndroid Build Coastguard Worker} 172*1fa6dee9SAndroid Build Coastguard Worker 173*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) ImportPath() string { 174*1fa6dee9SAndroid Build Coastguard Worker return "{{.Package}}" 175*1fa6dee9SAndroid Build Coastguard Worker} 176*1fa6dee9SAndroid Build Coastguard Worker 177*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) StartTestLog(io.Writer) { 178*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 179*1fa6dee9SAndroid Build Coastguard Worker} 180*1fa6dee9SAndroid Build Coastguard Worker 181*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) StopTestLog() error { 182*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 183*1fa6dee9SAndroid Build Coastguard Worker} 184*1fa6dee9SAndroid Build Coastguard Worker 185*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) SetPanicOnExit0(bool) { 186*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 187*1fa6dee9SAndroid Build Coastguard Worker} 188*1fa6dee9SAndroid Build Coastguard Worker 189*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) CoordinateFuzzing(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error { 190*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 191*1fa6dee9SAndroid Build Coastguard Worker} 192*1fa6dee9SAndroid Build Coastguard Worker 193*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) RunFuzzWorker(func(corpusEntry) error) error { 194*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 195*1fa6dee9SAndroid Build Coastguard Worker} 196*1fa6dee9SAndroid Build Coastguard Worker 197*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) ReadCorpus(string, []reflect.Type) ([]corpusEntry, error) { 198*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 199*1fa6dee9SAndroid Build Coastguard Worker} 200*1fa6dee9SAndroid Build Coastguard Worker 201*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) CheckCorpus([]interface{}, []reflect.Type) error { 202*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 203*1fa6dee9SAndroid Build Coastguard Worker} 204*1fa6dee9SAndroid Build Coastguard Worker 205*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) ResetCoverage() { 206*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 207*1fa6dee9SAndroid Build Coastguard Worker} 208*1fa6dee9SAndroid Build Coastguard Worker 209*1fa6dee9SAndroid Build Coastguard Workerfunc (matchString) SnapshotCoverage() { 210*1fa6dee9SAndroid Build Coastguard Worker panic("shouldn't get here") 211*1fa6dee9SAndroid Build Coastguard Worker} 212*1fa6dee9SAndroid Build Coastguard Worker 213*1fa6dee9SAndroid Build Coastguard Workerfunc (f matchString) InitRuntimeCoverage() (mode string, tearDown func(string, string) (string, error), snapcov func() float64) { 214*1fa6dee9SAndroid Build Coastguard Worker return 215*1fa6dee9SAndroid Build Coastguard Worker} 216*1fa6dee9SAndroid Build Coastguard Worker 217*1fa6dee9SAndroid Build Coastguard Workertype corpusEntry = struct { 218*1fa6dee9SAndroid Build Coastguard Worker Parent string 219*1fa6dee9SAndroid Build Coastguard Worker Path string 220*1fa6dee9SAndroid Build Coastguard Worker Data []byte 221*1fa6dee9SAndroid Build Coastguard Worker Values []interface{} 222*1fa6dee9SAndroid Build Coastguard Worker Generation int 223*1fa6dee9SAndroid Build Coastguard Worker IsSeed bool 224*1fa6dee9SAndroid Build Coastguard Worker} 225*1fa6dee9SAndroid Build Coastguard Worker 226*1fa6dee9SAndroid Build Coastguard Workerfunc main() { 227*1fa6dee9SAndroid Build Coastguard Worker{{if .MainStartTakesFuzzers }} 228*1fa6dee9SAndroid Build Coastguard Worker m := testing.MainStart(matchString{}, t, nil, nil, e) 229*1fa6dee9SAndroid Build Coastguard Worker{{else}} 230*1fa6dee9SAndroid Build Coastguard Worker m := testing.MainStart(matchString{}, t, nil, e) 231*1fa6dee9SAndroid Build Coastguard Worker{{end}} 232*1fa6dee9SAndroid Build Coastguard Worker{{if .HasMain}} 233*1fa6dee9SAndroid Build Coastguard Worker pkg.TestMain(m) 234*1fa6dee9SAndroid Build Coastguard Worker{{else}} 235*1fa6dee9SAndroid Build Coastguard Worker os.Exit(m.Run()) 236*1fa6dee9SAndroid Build Coastguard Worker{{end}} 237*1fa6dee9SAndroid Build Coastguard Worker} 238*1fa6dee9SAndroid Build Coastguard Worker`)) 239