tstest, util/testenv: drop tstest's dependency on the testing package

Change tstest's exported functions (AssertNotParallel, Replace,
Parallel, RequireRoot, SkipOnKernelVersions, MinAllocsPerRun, FixLogs,
UnfixLogs, CheckIsZero, ResourceCheck) to take testenv.TB instead of
testing.TB or *testing.T, so importing tstest from non-test code no
longer links the testing package and its flag registration side
effects into the binary. Add testenv.Verbose to replace the one use of
testing.Verbose, and a deptest check to keep testing out of tstest's
dependency graph.

Callers are unaffected: *testing.T and testing.TB both satisfy
testenv.TB.

Updates tailscale/corp#45223

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: Ib373ff66ceff638d071582baf8367245987e9155
This commit is contained in:
Brad Fitzpatrick
2026-07-21 13:03:23 -07:00
committed by Brad Fitzpatrick
parent d11757863d
commit 3ccc7725a3
7 changed files with 47 additions and 17 deletions
+11 -6
View File
@@ -2,18 +2,23 @@
// SPDX-License-Identifier: BSD-3-Clause
// Package tstest provides utilities for use in unit tests.
//
// It intentionally does not depend on the "testing" package (using
// [testenv.TB] instead of testing.TB) so that importing it from
// non-test code doesn't link the testing package and its flag
// registration side effects into the binary.
package tstest
import (
"context"
"fmt"
"os"
"testing"
"time"
"tailscale.com/envknob"
"tailscale.com/types/logger"
"tailscale.com/util/backoff"
"tailscale.com/util/testenv"
)
// AssertNotParallel asserts that t has not been marked as parallel.
@@ -21,7 +26,7 @@ import (
//
// Use this when a test modifies package-level globals or other shared
// state that would be unsafe to modify concurrently with other tests.
func AssertNotParallel(t testing.TB) {
func AssertNotParallel(t testenv.TB) {
t.Helper()
t.Setenv("ASSERT_NOT_PARALLEL_TEST", "1") // panics if t.Parallel was called
}
@@ -32,7 +37,7 @@ func AssertNotParallel(t testing.TB) {
// When target is a package-level variable, the caller should also call
// [AssertNotParallel] to ensure the test is not running in parallel with
// other tests that may access the same variable.
func Replace[T any](t testing.TB, target *T, val T) {
func Replace[T any](t testenv.TB, target *T, val T) {
t.Helper()
if target == nil {
t.Fatalf("Replace: nil pointer")
@@ -66,14 +71,14 @@ func WaitFor(maxWait time.Duration, try func() error) error {
var serializeParallel = envknob.RegisterBool("TS_SERIAL_TESTS")
// Parallel calls t.Parallel, unless TS_SERIAL_TESTS is set true.
func Parallel(t *testing.T) {
func Parallel(t interface{ Parallel() }) {
if !serializeParallel() {
t.Parallel()
}
}
// RequireRoot skips the test if the current user is not root.
func RequireRoot(tb testing.TB) {
func RequireRoot(tb testenv.TB) {
tb.Helper()
if os.Getuid() != 0 {
tb.Skip("skipping test; requires root")
@@ -82,7 +87,7 @@ func RequireRoot(tb testing.TB) {
// SkipOnKernelVersions skips the test if the current
// kernel version is in the specified list.
func SkipOnKernelVersions(t testing.TB, issue string, versions ...string) {
func SkipOnKernelVersions(t testenv.TB, issue string, versions ...string) {
major, minor, patch := KernelVersion()
if major == 0 && minor == 0 && patch == 0 {
t.Logf("could not determine kernel version")