// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package testdeps provides access to dependencies needed by test execution. // // This package is imported by the generated main package, which passes // TestDeps into testing.Main. This allows tests to use packages at run time // without making those packages direct dependencies of package testing. // Direct dependencies of package testing are harder to write tests for.
package testdeps import ( ) // TestDeps is an implementation of the testing.testDeps interface, // suitable for passing to [testing.MainStart]. type TestDeps struct{} var matchPat string var matchRe *regexp.Regexp func (TestDeps) (, string) ( bool, error) { if matchRe == nil || matchPat != { matchPat = matchRe, = regexp.Compile(matchPat) if != nil { return } } return matchRe.MatchString(), nil } func (TestDeps) ( io.Writer) error { return pprof.StartCPUProfile() } func (TestDeps) () { pprof.StopCPUProfile() } func (TestDeps) ( string, io.Writer, int) error { return pprof.Lookup().WriteTo(, ) } // ImportPath is the import path of the testing binary, set by the generated main function. var ImportPath string func (TestDeps) () string { return ImportPath } // testLog implements testlog.Interface, logging actions by package os. type testLog struct { mu sync.Mutex w *bufio.Writer set bool } func ( *testLog) ( string) { .add("getenv", ) } func ( *testLog) ( string) { .add("open", ) } func ( *testLog) ( string) { .add("stat", ) } func ( *testLog) ( string) { .add("chdir", ) } // add adds the (op, name) pair to the test log. func ( *testLog) (, string) { if strings.Contains(, "\n") || == "" { return } .mu.Lock() defer .mu.Unlock() if .w == nil { return } .w.WriteString() .w.WriteByte(' ') .w.WriteString() .w.WriteByte('\n') } var log testLog func (TestDeps) ( io.Writer) { log.mu.Lock() log.w = bufio.NewWriter() if !log.set { // Tests that define TestMain and then run m.Run multiple times // will call StartTestLog/StopTestLog multiple times. // Checking log.set avoids calling testlog.SetLogger multiple times // (which will panic) and also avoids writing the header multiple times. log.set = true testlog.SetLogger(&log) log.w.WriteString("# test log\n") // known to cmd/go/internal/test/test.go } log.mu.Unlock() } func (TestDeps) () error { log.mu.Lock() defer log.mu.Unlock() := log.w.Flush() log.w = nil return } // SetPanicOnExit0 tells the os package whether to panic on os.Exit(0). func (TestDeps) ( bool) { testlog.SetPanicOnExit0() } func (TestDeps) ( time.Duration, int64, time.Duration, int64, int, []fuzz.CorpusEntry, []reflect.Type, , string) ( error) { // Fuzzing may be interrupted with a timeout or if the user presses ^C. // In either case, we'll stop worker processes gracefully and save // crashers and interesting values. , := signal.NotifyContext(context.Background(), os.Interrupt) defer () = fuzz.CoordinateFuzzing(, fuzz.CoordinateFuzzingOpts{ Log: os.Stderr, Timeout: , Limit: , MinimizeTimeout: , MinimizeLimit: , Parallel: , Seed: , Types: , CorpusDir: , CacheDir: , }) if == .Err() { return nil } return } func (TestDeps) ( func(fuzz.CorpusEntry) error) error { // Worker processes may or may not receive a signal when the user presses ^C // On POSIX operating systems, a signal sent to a process group is delivered // to all processes in that group. This is not the case on Windows. // If the worker is interrupted, return quickly and without error. // If only the coordinator process is interrupted, it tells each worker // process to stop by closing its "fuzz_in" pipe. , := signal.NotifyContext(context.Background(), os.Interrupt) defer () := fuzz.RunFuzzWorker(, ) if == .Err() { return nil } return } func (TestDeps) ( string, []reflect.Type) ([]fuzz.CorpusEntry, error) { return fuzz.ReadCorpus(, ) } func (TestDeps) ( []any, []reflect.Type) error { return fuzz.CheckCorpus(, ) } func (TestDeps) () { fuzz.ResetCoverage() } func (TestDeps) () { fuzz.SnapshotCoverage() }