1// Copyright 2016 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// Package testdeps provides access to dependencies needed by test execution. 6// 7// This package is imported by the generated main package, which passes 8// TestDeps into testing.Main. This allows tests to use packages at run time 9// without making those packages direct dependencies of package testing. 10// Direct dependencies of package testing are harder to write tests for. 11package testdeps 12 13import ( 14 "bufio" 15 "internal/testlog" 16 "io" 17 "regexp" 18 "runtime/pprof" 19 "strings" 20 "sync" 21) 22 23// TestDeps is an implementation of the testing.testDeps interface, 24// suitable for passing to testing.MainStart. 25type TestDeps struct{} 26 27var matchPat string 28var matchRe *regexp.Regexp 29 30func (TestDeps) MatchString(pat, str string) (result bool, err error) { 31 if matchRe == nil || matchPat != pat { 32 matchPat = pat 33 matchRe, err = regexp.Compile(matchPat) 34 if err != nil { 35 return 36 } 37 } 38 return matchRe.MatchString(str), nil 39} 40 41func (TestDeps) StartCPUProfile(w io.Writer) error { 42 return pprof.StartCPUProfile(w) 43} 44 45func (TestDeps) StopCPUProfile() { 46 pprof.StopCPUProfile() 47} 48 49func (TestDeps) WriteProfileTo(name string, w io.Writer, debug int) error { 50 return pprof.Lookup(name).WriteTo(w, debug) 51} 52 53// ImportPath is the import path of the testing binary, set by the generated main function. 54var ImportPath string 55 56func (TestDeps) ImportPath() string { 57 return ImportPath 58} 59 60// testLog implements testlog.Interface, logging actions by package os. 61type testLog struct { 62 mu sync.Mutex 63 w *bufio.Writer 64 set bool 65} 66 67func (l *testLog) Getenv(key string) { 68 l.add("getenv", key) 69} 70 71func (l *testLog) Open(name string) { 72 l.add("open", name) 73} 74 75func (l *testLog) Stat(name string) { 76 l.add("stat", name) 77} 78 79func (l *testLog) Chdir(name string) { 80 l.add("chdir", name) 81} 82 83// add adds the (op, name) pair to the test log. 84func (l *testLog) add(op, name string) { 85 if strings.Contains(name, "\n") || name == "" { 86 return 87 } 88 89 l.mu.Lock() 90 defer l.mu.Unlock() 91 if l.w == nil { 92 return 93 } 94 l.w.WriteString(op) 95 l.w.WriteByte(' ') 96 l.w.WriteString(name) 97 l.w.WriteByte('\n') 98} 99 100var log testLog 101 102func (TestDeps) StartTestLog(w io.Writer) { 103 log.mu.Lock() 104 log.w = bufio.NewWriter(w) 105 if !log.set { 106 // Tests that define TestMain and then run m.Run multiple times 107 // will call StartTestLog/StopTestLog multiple times. 108 // Checking log.set avoids calling testlog.SetLogger multiple times 109 // (which will panic) and also avoids writing the header multiple times. 110 log.set = true 111 testlog.SetLogger(&log) 112 log.w.WriteString("# test log\n") // known to cmd/go/internal/test/test.go 113 } 114 log.mu.Unlock() 115} 116 117func (TestDeps) StopTestLog() error { 118 log.mu.Lock() 119 defer log.mu.Unlock() 120 err := log.w.Flush() 121 log.w = nil 122 return err 123} 124