Source file src/internal/testlog/log.go
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.Pointer 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.Pointer[Interface] 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.CompareAndSwap(nil, &impl) { 35 panic("testlog: SetLogger must be called only once") 36 } 37 } 38 39 // Logger returns the current test logger implementation. 40 // It returns nil if there is no logger. 41 func Logger() Interface { 42 impl := logger.Load() 43 if impl == nil { 44 return nil 45 } 46 return *impl 47 } 48 49 // Getenv calls Logger().Getenv, if a logger has been set. 50 func Getenv(name string) { 51 if log := Logger(); log != nil { 52 log.Getenv(name) 53 } 54 } 55 56 // Open calls Logger().Open, if a logger has been set. 57 func Open(name string) { 58 if log := Logger(); log != nil { 59 log.Open(name) 60 } 61 } 62 63 // Stat calls Logger().Stat, if a logger has been set. 64 func Stat(name string) { 65 if log := Logger(); log != nil { 66 log.Stat(name) 67 } 68 } 69