testutil

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package testutil centralises deterministic test helpers used across the repository: fake clock, fake random source, goleak integration, and shared fixture loaders. It is imported only from `_test.go` files.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BinaryCommandContext

func BinaryCommandContext(
	ctx context.Context,
	t *testing.T,
	name string,
	args ...string,
) *exec.Cmd

BinaryCommandContext returns a command for the requested project binary. Bazel coverage instruments data-dependency binaries as well as the test executable, so subprocesses need their own GOCOVERDIR. Without it, the Go runtime writes a coverage warning to stderr and breaks tests that assert a clean command invocation.

func BuildBinary

func BuildBinary(ctx context.Context, t *testing.T, name string) string

BuildBinary returns an absolute path to the requested command binary. Bazel tests consume the already-built binary supplied through bazelTestBinaryEnv; direct `go test` runs fall back to compiling ./cmd/<name>/ in a temporary directory. Caller passes the leaf command directory name (today only "usbip-go" — the project ships one binary per OpenSpec, but the helper stays generic in case a future cmd/ leaf needs the same fallback behavior).

Centralised here so binary-smoke tests across `cmd/.../`_test.go packages share one helper. Two prior duplicates in cmd/usbip-go/binary_smoke_test.go and cmd/usbip-go/binary_missing_parent_dir_test.go drifted on TMPDIR handling; this is the canonical version.

Notes on the absolute-path dance: `t.TempDir()` may return a relative path when TMPDIR resolves relative under a sandbox; an `exec.Command(out)` with a relative `out` cannot be resolved by fork/exec once the daemon under test changes cwd. `filepath.Abs` the temp dir before composing the binary path, and pass the same absolute TMPDIR to the build subprocess so go's workdir creation does not chase a relative `.go-build-XYZ` either.

func RepoRoot

func RepoRoot(t *testing.T) string

RepoRoot walks up from PWD looking for go.mod and returns the directory holding it. Fatal-fails the test if the walk reaches the filesystem root without finding go.mod.

Types

type FakeClock

type FakeClock struct {
	// contains filtered or unexported fields
}

FakeClock is a deterministic app.Clock implementation for tests. All internal state is guarded by a mutex so concurrent Sleep, After, and Advance calls are race-free under the Go race detector.

Use NewFakeClockAt to construct. The zero value is intentionally not useful because every deterministic test wants an explicit epoch.

FakeClock satisfies app.Clock. The assertion lives here rather than in internal/app to avoid a circular dependency: internal/testutil consumes the Clock contract, and internal/app must not import testutil in production code.

func NewFakeClockAt

func NewFakeClockAt(t time.Time) *FakeClock

NewFakeClockAt returns a FakeClock whose Now() starts at t.

func (*FakeClock) Advance

func (f *FakeClock) Advance(d time.Duration)

Advance moves the clock forward by d. Any After channel whose deadline is at or before the new Now is fired with the new Now value and removed from the pending list.

func (*FakeClock) After

func (f *FakeClock) After(d time.Duration) <-chan time.Time

After returns a buffered channel that receives the clock's time once the deadline (now+d) has been reached via Advance or Sleep. d <= 0 fires immediately.

func (*FakeClock) Now

func (f *FakeClock) Now() time.Time

Now returns the clock's current time.

func (*FakeClock) Pending

func (f *FakeClock) Pending() int

Pending reports the number of After-channels currently awaiting their deadline. Exposed so tests asserting the "register-before-return" contract of a watcher goroutine can verify registration synchronously without falling back to polling or wall-clock sleeps. The count is taken under the FakeClock mutex so concurrent After/Advance callers cannot observe a torn value.

func (*FakeClock) Sleep

func (f *FakeClock) Sleep(d time.Duration)

Sleep advances the clock by d, firing any pending After channels whose deadline has been reached.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL