Update
This commit is contained in:
1 parent
3530afb854
commit
6903fcff27
2146 files changed
+112256
-190703
No files matched your search
+48
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package testenv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// stackBufPool holds buffers for [InSynctestBubble]'s runtime.Stack calls,
|
||||
// which would otherwise allocate on every call: the compiler cannot prove
|
||||
// that a stack-allocated buffer does not escape into runtime.Stack. Plain
|
||||
// byte arrays, unlike the zstd coders that motivated InSynctestBubble, are
|
||||
// safe to share across synctest bubble boundaries.
|
||||
var stackBufPool = sync.Pool{New: func() any { return new([128]byte) }}
|
||||
|
||||
// InSynctestBubble reports whether the current goroutine is running within a
|
||||
// testing/synctest bubble.
|
||||
//
|
||||
// As of Go 1.26 there is no public API to query bubble membership
|
||||
// (internal/synctest.IsInBubble is runtime-internal), so this instead
|
||||
// looks for the "synctest bubble N" annotation that the runtime renders
|
||||
// in the current goroutine's [runtime.Stack] header. If a future Go
|
||||
// release changes that annotation, this reports false; tests that depend
|
||||
// on it for correctness (such as tailscale.com/util/zstdframe's) should
|
||||
// exercise the misdetection failure mode so the breakage is loud.
|
||||
func InSynctestBubble() bool {
|
||||
// Bubbles only exist within tests, so skip the (relatively) expensive
|
||||
// stack header check in non-test binaries. This deliberately does not
|
||||
// use InTest: InSynctestBubble may be reached from package init
|
||||
// functions (before the testing package has registered its flags),
|
||||
// and InTest would permanently latch a false result there. Bubbles
|
||||
// cannot exist during init, so returning false then is correct.
|
||||
if flag.Lookup("test.v") == nil {
|
||||
return false
|
||||
}
|
||||
// The current goroutine's header looks like:
|
||||
// goroutine 9 [running, synctest bubble 1]:
|
||||
// A 128-byte buffer always fits the header, and runtime.Stack
|
||||
// truncates the rest.
|
||||
buf := stackBufPool.Get().(*[128]byte)
|
||||
defer stackBufPool.Put(buf)
|
||||
n := runtime.Stack(buf[:], false)
|
||||
return bytes.Contains(buf[:n], []byte(" synctest bubble "))
|
||||
}
|
||||
+18
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// Copyright (c) Tailscale Inc & contributors
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
// Package testenv provides utility functions for tests. It does not depend on
|
||||
@@ -8,6 +8,7 @@ package testenv
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io"
|
||||
|
||||
"tailscale.com/types/lazy"
|
||||
)
|
||||
@@ -21,8 +22,23 @@ func InTest() bool {
|
||||
})
|
||||
}
|
||||
|
||||
// Verbose reports whether the test binary is running with verbose
|
||||
// output (the -test.v flag), like testing.Verbose but without
|
||||
// importing the testing package.
|
||||
func Verbose() bool {
|
||||
f := flag.Lookup("test.v")
|
||||
if f == nil {
|
||||
return false
|
||||
}
|
||||
// The flag's String value is "false" when off, and "true" or
|
||||
// "test2json" when on.
|
||||
return f.Value.String() != "false"
|
||||
}
|
||||
|
||||
// TB is testing.TB, to avoid importing "testing" in non-test code.
|
||||
type TB interface {
|
||||
ArtifactDir() string
|
||||
Attr(key, value string)
|
||||
Cleanup(func())
|
||||
Error(args ...any)
|
||||
Errorf(format string, args ...any)
|
||||
@@ -35,6 +51,7 @@ type TB interface {
|
||||
Log(args ...any)
|
||||
Logf(format string, args ...any)
|
||||
Name() string
|
||||
Output() io.Writer
|
||||
Setenv(key, value string)
|
||||
Chdir(dir string)
|
||||
Skip(args ...any)
|
||||
|
||||
Reference in new issue
Block a user