| // Copyright 2017 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 testlog provides a back-channel communication path | |
| // between tests and package os, so that cmd/go can see which | |
| // environment variables and files a test consults. | |
| package testlog | |
| import "sync/atomic" | |
| // Interface is the interface required of test loggers. | |
| // The os package will invoke the interface's methods to indicate that | |
| // it is inspecting the given environment variables or files. | |
| // Multiple goroutines may call these methods simultaneously. | |
| type Interface interface { | |
| Getenv(key string) | |
| Stat(file string) | |
| Open(file string) | |
| Chdir(dir string) | |
| } | |
| // logger is the current logger Interface. | |
| // We use an atomic.Pointer in case test startup | |
| // is racing with goroutines started during init. | |
| // That must not cause a race detector failure, | |
| // although it will still result in limited visibility | |
| // into exactly what those goroutines do. | |
| var logger atomic.Pointer[Interface] | |
| // SetLogger sets the test logger implementation for the current process. | |
| // It must be called only once, at process startup. | |
| func SetLogger(impl Interface) { | |
| if !logger.CompareAndSwap(nil, &impl) { | |
| panic("testlog: SetLogger must be called only once") | |
| } | |
| } | |
| // Logger returns the current test logger implementation. | |
| // It returns nil if there is no logger. | |
| func Logger() Interface { | |
| impl := logger.Load() | |
| if impl == nil { | |
| return nil | |
| } | |
| return *impl | |
| } | |
| // Getenv calls Logger().Getenv, if a logger has been set. | |
| func Getenv(name string) { | |
| if log := Logger(); log != nil { | |
| log.Getenv(name) | |
| } | |
| } | |
| // Open calls Logger().Open, if a logger has been set. | |
| func Open(name string) { | |
| if log := Logger(); log != nil { | |
| log.Open(name) | |
| } | |
| } | |
| // Stat calls Logger().Stat, if a logger has been set. | |
| func Stat(name string) { | |
| if log := Logger(); log != nil { | |
| log.Stat(name) | |
| } | |
| } |