Documentation
¶
Index ¶
- Variables
- func AbsPath(ctx context.Context, rel string) string
- func AtomicWriteFile(ctx context.Context, rel string, data []byte, perm os.FileMode) error
- func CreateTestStdio(content string) (*os.File, func())deprecated
- func DumpEnv(ctx context.Context) string
- func Edit(ctx context.Context, path string) error
- func EnsureInJail(jail, p string) string
- func EnsureInJailFor(jail, p string) string
- func ExpandEnv(ctx context.Context, s string) string
- func ExpandPath(ctx context.Context, p string) (string, error)
- func GetDefault(env Env, key, other string) string
- func GetTempDir(ctx context.Context) string
- func Glob(ctx context.Context, pattern string) ([]string, error)
- func IsInJail(jail, rel string) bool
- func IsInteractiveTerminal(f *os.File) bool
- func Mkdir(ctx context.Context, rel string, perm os.FileMode, all bool) error
- func ReadDir(ctx context.Context, rel string) ([]os.DirEntry, error)
- func ReadFile(ctx context.Context, rel string) ([]byte, error)
- func RelativePath(ctx context.Context, basepath, path string) string
- func Remove(ctx context.Context, rel string, all bool) error
- func RemoveJailPrefix(jail, path string) string
- func Rename(ctx context.Context, src, dst string) error
- func ResolvePath(ctx context.Context, rel string, follow bool) (string, error)
- func Stat(ctx context.Context, rel string, followSymlinks bool) (os.FileInfo, error)
- func StdinHasData(f *os.File) bool
- func Symlink(ctx context.Context, oldname, newname string) error
- func UserCachePath(ctx context.Context) (string, error)
- func UserConfigPath(ctx context.Context) (string, error)
- func UserDataPath(ctx context.Context) (string, error)
- func UserStatePath(ctx context.Context) (string, error)
- func WithEnv(ctx context.Context, env Env) context.Context
- func WithHasher(ctx context.Context, h Hasher) context.Context
- func WithStream(ctx context.Context, s *Stream) context.Context
- func WriteFile(ctx context.Context, rel string, data []byte, perm os.FileMode) error
- type Env
- type FileSystem
- type Hasher
- type MD5Hasher
- type OsEnv
- func (o *OsEnv) AtomicWriteFile(rel string, data []byte, perm os.FileMode) error
- func (o *OsEnv) Environ() []string
- func (o *OsEnv) ExpandPath(p string) string
- func (o *OsEnv) Get(key string) string
- func (o *OsEnv) GetHome() (string, error)
- func (o *OsEnv) GetTempDir() string
- func (o *OsEnv) GetUser() (string, error)
- func (o *OsEnv) Getwd() (string, error)
- func (o *OsEnv) Glob(pattern string) ([]string, error)
- func (o *OsEnv) Has(key string) bool
- func (o *OsEnv) Mkdir(path string, perm os.FileMode, all bool) error
- func (o *OsEnv) Name() string
- func (o *OsEnv) ReadDir(rel string) ([]os.DirEntry, error)
- func (o *OsEnv) ReadFile(name string) ([]byte, error)
- func (o *OsEnv) Remove(path string, all bool) error
- func (o *OsEnv) Rename(src, dst string) error
- func (o *OsEnv) ResolvePath(rel string, follow bool) (string, error)
- func (o *OsEnv) Set(key string, value string) error
- func (o *OsEnv) SetHome(home string) error
- func (o *OsEnv) SetUser(username string) error
- func (o *OsEnv) Setwd(dir string)
- func (o *OsEnv) Stat(name string, follow bool) (os.FileInfo, error)
- func (o *OsEnv) Symlink(oldname string, newname string) error
- func (o *OsEnv) Unset(key string)
- func (o *OsEnv) WriteFile(name string, data []byte, perm os.FileMode) error
- type Stream
- type TestEnv
- func (m *TestEnv) AtomicWriteFile(rel string, data []byte, perm os.FileMode) error
- func (m *TestEnv) Clone() *TestEnv
- func (m *TestEnv) Environ() []string
- func (m *TestEnv) ExpandPath(p string) string
- func (m TestEnv) Get(key string) string
- func (m *TestEnv) GetHome() (string, error)
- func (m *TestEnv) GetJail() string
- func (m *TestEnv) GetTempDir() string
- func (m *TestEnv) GetUser() (string, error)
- func (m *TestEnv) Getwd() (string, error)
- func (m *TestEnv) Glob(pattern string) ([]string, error)
- func (m *TestEnv) Has(key string) bool
- func (m *TestEnv) Mkdir(rel string, perm os.FileMode, all bool) error
- func (o *TestEnv) Name() string
- func (m *TestEnv) ReadDir(name string) ([]os.DirEntry, error)
- func (m *TestEnv) ReadFile(rel string) ([]byte, error)
- func (m *TestEnv) Remove(rel string, all bool) error
- func (m *TestEnv) Rename(src string, dst string) error
- func (m *TestEnv) ResolvePath(rel string, follow bool) (string, error)
- func (m *TestEnv) Set(key string, value string) error
- func (m *TestEnv) SetHome(rel string) error
- func (m *TestEnv) SetUser(username string) error
- func (m *TestEnv) Setwd(dir string)
- func (m *TestEnv) Stat(rel string, followSymlinks bool) (os.FileInfo, error)
- func (o *TestEnv) Symlink(oldname string, newname string) error
- func (m *TestEnv) Unset(key string)
- func (m *TestEnv) WriteFile(name string, data []byte, perm os.FileMode) error
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoEnvKey = errors.New("env key missing") ErrEscapeAttempt = errors.New("path escape attempt: operation would access path outside jail") )
var DefaultEditor = "nano"
Functions ¶
func AbsPath ¶
AbsPath returns a cleaned absolute path for the provided path. Behavior: - If path is empty, returns empty string. - Expands a leading tilde using ExpandPath with the Env from ctx. - Expands environment variables from the injected env in ctx. - If the path is not absolute, attempts to convert it to an absolute path. - Returns a cleaned path in all cases.
If ExpandPath fails (for example when HOME is not available) AbsPath falls back to the original input and proceeds with expansion of environment variables and cleaning.
func AtomicWriteFile ¶
func CreateTestStdio
deprecated
Deprecated: CreateTestStdio is unstable and may change in future releases.
CreateTestStdio creates a temporary file prefilled with the given content and seeks it to the beginning, making it suitable to pass as a stand-in for stdin, stdout, or stderr in tests.
It returns the open *os.File and a cleanup function. The cleanup function closes the file and removes it from disk. The function panics on any error while creating, writing, or seeking the temporary file; this makes test setup failures immediately visible.
Example usage in tests:
f, cleanup := CreateTestStdio("input text")
defer cleanup()
// pass f where a *os.File is needed
The returned file is created in the OS temporary directory using the pattern "test-stdio-*".
func DumpEnv ¶
DumpEnv returns a sorted, newline separated representation of the environment visible via the Env stored in ctx. Each line is formatted as "KEY=VALUE".
For TestEnv and OsEnv the function enumerates the known keys. For other Env implementations the function attempts to use common helper methods (Environ or Keys) if available. If enumeration is not possible a short message is returned indicating that limitation.
func Edit ¶
Edit launches the user's editor to edit the provided file path. It checks $VISUAL first, then $EDITOR. If neither is set, it falls back to "nano". The function attaches the current process's stdio to the editor so interactive editors work as expected.
func EnsureInJail ¶
EnsureInJail returns a path that resides inside jail when possible.
If the path is already inside jail, the cleaned absolute form is returned. Otherwise a path under jail is returned by appending the base name of the path.
func EnsureInJailFor ¶
EnsureInJailFor is a test-friendly helper that mirrors EnsureInJail but accepts paths written with forward slashes.
It converts both jail and p using filepath.FromSlash before applying the EnsureInJail logic. Use this from tests when expected values are easier to express using POSIX-style literals.
func ExpandEnv ¶
ExpandEnv expands $var or ${var} in s using the Env stored in ctx. If no Env is present in the context the real OS environment is used via OsEnv.
func ExpandPath ¶
ExpandPath expands a leading tilde in the provided path to the user's home directory obtained from the Env stored in ctx. Supported forms:
"~" "~/rest/of/path" "~\rest\of\path" (Windows)
If the home directory cannot be obtained from the environment an error is returned. If the path does not start with a tilde it is returned unchanged.
func GetDefault ¶
GetDefault returns the value of key from env when present and non-empty. Otherwise it returns the provided fallback value. Use this helper when a preference for an environment value is desired while still allowing a concrete default.
func GetTempDir ¶ added in v0.4.0
func Glob ¶ added in v0.3.0
Glob returns the names of all files matching the pattern using the Env stored in ctx. This enables glob patterns to work within sandboxed test environments. The pattern is expanded (handling ~) and then glob-matched. For TestEnv, results are restricted to within the jail boundary.
func IsInJail ¶
IsInJail reports whether the provided path resides within the jail boundary.
If jail is empty, the function returns true (no boundary). Relative paths always are in the jail
func IsInteractiveTerminal ¶
IsInteractiveTerminal reports whether the provided file is connected to an interactive terminal.
This delegates to golang.org/x/term.IsTerminal and returns true when the file descriptor refers to a terminal device (TTY). Pass os.Stdin to check the program's standard input.
Notes:
- The check uses the file descriptor (f.Fd()) and will return false for pipes, redirected files, and other non-terminal descriptors.
- It is a non-destructive check and does not change the file position.
func Mkdir ¶
Mkdir creates a directory using the Env stored in ctx. If all is true MkdirAll is used.
func ReadDir ¶
ReadDir reads the directory named by name and returns a list of entries. The path is expanded using ExpandPath with the Env from ctx before calling os.ReadDir.
func ReadFile ¶
ReadFile reads the named file using the Env stored in ctx. This ensures the filesystem view can be controlled by an injected TestEnv.
func RelativePath ¶
RelativePath returns a path relative to basepath. If path is empty an empty string is returned. If computing the relative path fails the absolute target path is returned.
func Remove ¶
Remove removes the named file or directory using the Env stored in ctx. If all is true RemoveAll is used.
func RemoveJailPrefix ¶
RemoveJailPrefix removes the jail prefix from a path and returns an absolute path.
func ResolvePath ¶
ResolvePath returns the absolute path with symlinks evaluated. If symlink evaluation fails the absolute path returned by AbsPath is returned instead.
func Stat ¶
Stat returns the os.FileInfo for the named file. The path is expanded using ExpandPath with the Env from ctx before calling os.Stat.
func StdinHasData ¶
StdinHasData reports whether the provided file appears to be receiving piped or redirected input (for example: `echo hi | myprog` or `myprog < file.txt`).
The implementation performs a lightweight metadata check: it returns true when the file is not a character device (that is, not a terminal). This is a common, portable heuristic used to detect piped input.
Notes and caveats:
- The check does not attempt to read from the file. It only inspects the file mode returned by Stat().
- For pipes this indicates stdin is coming from a pipe or redirect, but it does not strictly guarantee that bytes are immediately available to read. An open pipe may be empty until the writer writes to it.
- If f.Stat() returns an error the function conservatively returns false.
- Callers should pass os.Stdin to check the program's standard input, or a *os.File pointing to another stream for testing.
Example:
if StdinHasData(os.Stdin) {
// read from stdin
}
func Symlink ¶
Symlink creates a symbolic link pointing to oldname named newname. The oldname and newname are expanded using ExpandPath with the Env from ctx before creating the symlink. If symlink creation fails an error is returned.
func UserCachePath ¶
UserCachePath returns the directory that should be used to store per-user cache files.
Behavior:
- On Unix-like systems: prefers XDG_CACHE_HOME if set.
- On Windows: prefers LOCALAPPDATA if set.
- Falls back to $HOME/.cache when no appropriate environment variable is set.
The returned path is the base cache directory; append appName if you want an application-specific subdirectory.
func UserConfigPath ¶
UserConfigPath returns the directory that should be used to store per-user configuration files.
Behavior:
- On Unix-like systems: prefers XDG_CONFIG_HOME if set; otherwise falls back to $HOME/.config.
- On Windows: prefers APPDATA (via the provided env) if set.
The function returns the raw directory value as used by the platform. Callers should append an application-specific subdirectory if desired.
func UserDataPath ¶
UserDataPath returns the directory that should be used to store per-user application data.
Behavior:
- On Windows: uses LOCALAPPDATA and returns a "data" directory under it. If LOCALAPPDATA is not set, the function returns an error that wraps ErrNoEnvKey.
- On Unix-like systems: prefers XDG_DATA_HOME if set; otherwise falls back to ~/.local/share.
Callers should append an application-specific subdirectory if desired.
func UserStatePath ¶
UserStatePath returns the directory that should be used to store per-user state files for an application (transient runtime state).
Behavior:
- On Windows: uses LOCALAPPDATA and returns a "state" directory under it. If LOCALAPPDATA is not set, the function returns an error that wraps ErrNoEnvKey.
- On Unix-like systems: prefers XDG_STATE_HOME if set; otherwise falls back to ~/.local/state.
Callers should append an application-specific subdirectory if desired.
func WithEnv ¶
WithEnv returns a copy of ctx that carries env. Use this to inject a test environment into code under test.
func WithHasher ¶
WithHasher returns a copy of ctx that carries the provided Hasher. Use this to inject a custom hasher for tests or alternative hashing strategies.
func WithStream ¶
WithStream returns a copy of ctx that carries the provided Stream. Use this to inject custom I/O streams for testing or alternative stream configurations.
Types ¶
type Env ¶
type Env interface {
FileSystem
// Name of the environment
Name() string
// Get returns the raw environment value for key. The return value may be
// empty when the key is not present.
Get(key string) string
// Set assigns the environment key to value.
Set(key, value string) error
// Has reports whether the environment key is set.
Has(key string) bool
// Environ returns a copy of the environment as a slice of strings in the
// form "KEY=VALUE".
Environ() []string
// Unset removes the environment key.
Unset(key string)
// GetHome returns the user's home directory. Implementations should return
// an error if the value is not available.
GetHome() (string, error)
// SetHome sets the user's home directory in the environment.
SetHome(home string) error
// GetUser returns the current user's username. Implementations should
// return an error if the value is not available.
GetUser() (string, error)
// SetUser sets the current user's username in the environment.
SetUser(user string) error
// Getwd returns the working directory as seen by this Env. For OsEnv this
// is the process working directory; for TestEnv it is the stored PWD.
Getwd() (string, error)
// Setwd sets the working directory for this Env. For OsEnv this may change
// the process working directory; for TestEnv it updates the stored PWD.
Setwd(dir string)
// GetTempDir returns an appropriate temp directory for this Env. For OsEnv
// this delegates to os.TempDir(); TestEnv provides testable fallbacks.
GetTempDir() string
// ResolvePath resolves that path. Follows symlinks and returns the absolute
// path
ResolvePath(rel string, follow bool) (string, error)
}
Env is a compact interface for reading and modifying environment values. Implementations may reflect the real process environment (OsEnv) or provide an in-memory view suitable for tests (TestEnv).
The interface mirrors common environment operations so callers can inject a test implementation for unit tests without touching the real process env.
func EnvFromContext ¶
EnvFromContext returns the Env stored in ctx. If ctx is nil or does not contain an Env, the real OsEnv is returned.
type FileSystem ¶
type FileSystem interface {
// ReadFile reads the named file.
ReadFile(rel string) ([]byte, error)
// WriteFile writes data to a file with the given permissions.
WriteFile(rel string, data []byte, perm os.FileMode) error
// Mkdir creates a directory. If all is true, MkdirAll is used.
Mkdir(rel string, perm os.FileMode, all bool) error
// Remove removes the named file or directory. If all is true, RemoveAll is used.
Remove(rel string, all bool) error
// Rename renames (moves) a file or directory.
Rename(src, dst string) error
// Stat returns the os.FileInfo for the named file.
Stat(name string, followSymlinks bool) (os.FileInfo, error)
// ReadDir reads the directory and returns a list of entries.
ReadDir(rel string) ([]os.DirEntry, error)
Symlink(oldname, newname string) error
Glob(pattern string) ([]string, error)
AtomicWriteFile(rel string, data []byte, perm os.FileMode) error
}
FileSystem defines the contract for filesystem operations. Implementations may reflect the real filesystem (OsEnv) or provide an in-memory view suitable for tests (TestEnv).
type Hasher ¶
Hasher computes a deterministic short hash for a byte slice. Implementations should return a textual representation suitable for inclusion in meta fields.
DefaultHasher is the fallback hasher used when none is provided via context.
func HasherFromContext ¶
HasherFromContext returns the Hasher stored in ctx. If ctx is nil or does not contain a Hasher, DefaultHasher is returned.
type MD5Hasher ¶
type MD5Hasher struct{}
MD5Hasher is a simple Hasher implementation that returns an MD5 hex digest.
Note: MD5 is used here for deterministic, compact hashes only and is not intended for cryptographic integrity protection.
type OsEnv ¶
type OsEnv struct{}
OsEnv is an Env implementation that delegates to the real process environment and filesystem. Use this in production code where access to the actual OS environment is required.
func (*OsEnv) AtomicWriteFile ¶
func (*OsEnv) ExpandPath ¶
func (*OsEnv) GetHome ¶
GetHome returns the home directory reported by the OS. It delegates to os.UserHomeDir.
func (*OsEnv) GetTempDir ¶
GetTempDir returns the OS temporary directory.
func (*OsEnv) GetUser ¶
GetUser returns the current OS user username. If the Username field is empty it falls back to the user's Name field.
func (*OsEnv) Remove ¶
Remove removes the named file or directory. If all is true all items in the path are removed.
func (*OsEnv) ResolvePath ¶
ResolvePath implements FileSystem.
func (*OsEnv) SetHome ¶
SetHome sets environment values that represent the user's home directory.
On Windows it also sets USERPROFILE to satisfy common callers.
func (*OsEnv) SetUser ¶
SetUser sets environment values that represent the current user.
On Windows it also sets USERNAME in addition to USER.
type Stream ¶
type Stream struct {
// In is the input stream, typically os.Stdin.
In io.Reader
// Out is the output stream, typically os.Stdout.
Out io.Writer
// Err is the error stream, typically os.Stderr.
Err io.Writer
// IsPiped indicates whether stdin appears to be piped or redirected.
IsPiped bool
// IsTTY indicates whether stdout refers to a terminal.
IsTTY bool
}
Stream models the standard IO streams and common stream properties.
Struct field tags are included for clarity to external consumers that may wish to encode some stream metadata. The actual reader and writer fields are not suitable for encoding and therefore are tagged to be ignored.
func DefaultStream ¶
func DefaultStream() *Stream
DefaultStream returns a Stream configured with the real process standard input, output, and error streams. It detects whether stdin is piped and whether stdout is a terminal.
func StreamFromContext ¶
StreamFromContext returns the Stream stored in ctx. If ctx is nil or does not contain a Stream, DefaultStream() is returned.
type TestEnv ¶
type TestEnv struct {
// contains filtered or unexported fields
}
TestEnv is an in-memory Env implementation useful for tests. It does not touch the real process environment and therefore makes tests hermetic.
The home and user fields satisfy GetHome and GetUser. The data map stores other keys. For convenience, setting or unsetting the keys "HOME" and "USER" updates the corresponding home and user fields.
func NewTestEnv ¶
NewTestEnv constructs a TestEnv populated with sensible defaults for tests. It sets HOME and USER and also sets platform specific variables so functions that prefer XDG_* on Unix or APPDATA/LOCALAPPDATA on Windows will pick them up.
If home or username are empty, reasonable defaults are chosen:
- home defaults to EnsureInJailFor(jail, "/home/<username>")
- username defaults to "testuser"
The function does not create directories on disk. It only sets environment values in the returned TestEnv.
func (*TestEnv) AtomicWriteFile ¶
func (*TestEnv) Clone ¶
Clone returns a copy of the TestEnv so tests can modify the returned environment without mutating the original. It deep copies the internal map and makes a copy of the Stream struct.
func (*TestEnv) Environ ¶
Environ returns a slice of "KEY=VALUE" entries representing the environment stored in the TestEnv. It guarantees HOME and USER are present when set.
func (*TestEnv) ExpandPath ¶
ExpandPath expands a leading tilde in the provided path to the TestEnv home. Supported forms:
"~" "~/rest/of/path" "~\rest\of\path" (Windows)
If the path does not start with a tilde it is returned unchanged. This method uses the TestEnv GetHome value. If home is not set, expansion may produce an empty or unexpected result.
func (TestEnv) Get ¶
Get returns the stored value for key. Reading from a nil map returns the zero value, so this method is safe on a zero TestEnv. The special keys HOME and USER come from dedicated fields.
func (*TestEnv) GetHome ¶
GetHome returns the configured home directory or an error if it is not set.
For TestEnv the returned home is guaranteed to be located within the configured jail when possible. This helps keep tests hermetic by ensuring paths used for home are under the test temporary area.
func (*TestEnv) GetTempDir ¶
GetTempDir returns a temp directory appropriate for the TestEnv. If the receiver is nil this falls back to os.TempDir to avoid panics.
The method prefers explicit TMPDIR/TEMP/TMP values stored in the TestEnv. On Windows it applies a series of fallbacks: LOCALAPPDATA, APPDATA, USERPROFILE, then a home based default. On Unix like systems it falls back to /tmp.
The returned path will be adjusted to reside inside the configured jail when possible to keep test artifacts contained.
func (*TestEnv) ReadFile ¶
ReadFile reads the named file from the filesystem view held by this TestEnv. When the receiver is nil the real filesystem is used.
func (*TestEnv) Remove ¶
Remove removes the named file or directory. If all is true RemoveAll is used. When the receiver is nil the real filesystem is affected.
func (*TestEnv) Rename ¶
Rename renames (moves) a file or directory. When the receiver is nil the operation is performed on the real filesystem.
func (*TestEnv) ResolvePath ¶
func (*TestEnv) Set ¶
Set stores a key/value pair in the TestEnv. If key is "HOME" or "USER" the corresponding dedicated field is updated. Calling Set on a nil receiver returns an error rather than panicking.
func (*TestEnv) SetHome ¶
SetHome sets the TestEnv home directory and updates the "HOME" key in the underlying map for callers that read via Get.
func (*TestEnv) SetUser ¶
SetUser sets the TestEnv current user and updates the "USER" key in the underlying map for callers that use Get.