1 // Copyright 2017 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 testlog provides a back-channel communication path 6 // between tests and package os, so that cmd/go can see which 7 // environment variables and files a test consults. 8 package testlog 9 10 import "sync/atomic" 11 12 // Interface is the interface required of test loggers. 13 // The os package will invoke the interface's methods to indicate that 14 // it is inspecting the given environment variables or files. 15 // Multiple goroutines may call these methods simultaneously. 16 type Interface interface { 17 Getenv(key string) 18 Stat(file string) 19 Open(file string) 20 Chdir(dir string) 21 } 22 23 // logger is the current logger Interface. 24 // We use an atomic.Value in case test startup 25 // is racing with goroutines started during init. 26 // That must not cause a race detector failure, 27 // although it will still result in limited visibility 28 // into exactly what those goroutines do. 29 var logger atomic.Value 30 31 // SetLogger sets the test logger implementation for the current process. 32 // It must be called only once, at process startup. 33 func SetLogger(impl Interface) { 34 if logger.Load() != nil { 35 panic("testlog: SetLogger must be called only once") 36 } 37 logger.Store(&impl) 38 } 39 40 // Logger returns the current test logger implementation. 41 // It returns nil if there is no logger. 42 func Logger() Interface { 43 impl := logger.Load() 44 if impl == nil { 45 return nil 46 } 47 return *impl.(*Interface) 48 } 49 50 // Getenv calls Logger().Getenv, if a logger has been set. 51 func Getenv(name string) { 52 if log := Logger(); log != nil { 53 log.Getenv(name) 54 } 55 } 56 57 // Open calls Logger().Open, if a logger has been set. 58 func Open(name string) { 59 if log := Logger(); log != nil { 60 log.Open(name) 61 } 62 } 63 64 // Stat calls Logger().Stat, if a logger has been set. 65 func Stat(name string) { 66 if log := Logger(); log != nil { 67 log.Stat(name) 68 } 69 } 70