Files
.bencher
.github
appc
atomicfile
chirp
client
clientupdate
cmd
addlicense
build-webclient
checkmetrics
cloner
connector-gen
containerboot
derper
derpprobe
dist
get-authkey
gitops-pusher
hello
k8s-nameserver
k8s-operator
mkmanifest
mkpkg
mkversion
nardump
natc
netlogfmt
nginx-auth
pgproxy
printdep
proxy-to-grafana
sniproxy
speedtest
ssh-auth-none-demo
stunc
stund
stunstamp
sync-containers
systray
tailscale
tailscaled
testcontrol
testwrapper
flakytest
flakytest.go
flakytest_test.go
args.go
args_test.go
testwrapper.go
testwrapper_test.go
tl-longchain
tsconnect
tsidp
tsshd
tta
viewer
vnet
xdpderper
control
derp
disco
docs
doctor
drive
envknob
feature
gokrazy
health
hostinfo
internal
ipn
jsondb
k8s-operator
kube
licenses
log
logpolicy
logtail
maths
metrics
net
omit
packages
paths
portlist
posture
prober
proxymap
release
safesocket
safeweb
scripts
sessionrecording
smallzstd
ssh
syncs
tailcfg
taildrop
tempfork
tka
tool
tsconst
tsd
tsnet
tstest
tstime
tsweb
types
util
version
wf
wgengine
words
.gitattributes
.gitignore
.golangci.yml
ALPINE.txt
AUTHORS
CODEOWNERS
CODE_OF_CONDUCT.md
Dockerfile
Dockerfile.base
LICENSE
Makefile
PATENTS
README.md
SECURITY.md
VERSION.txt
api.md
assert_ts_toolchain_match.go
build_dist.sh
build_docker.sh
flake.lock
flake.nix
go.mod
go.mod.sri
go.sum
go.toolchain.branch
go.toolchain.rev
gomod_test.go
header.txt
pkgdoc_test.go
pull-toolchain.sh
shell.nix
staticcheck.conf
update-flake.sh
version-embed.go
version_tailscale_test.go
version_test.go
tailscale/cmd/testwrapper/flakytest/flakytest.go

74 lines
2.2 KiB
Go
Raw Normal View History

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Package flakytest contains test helpers for marking a test as flaky. For
// tests run using cmd/testwrapper, a failed flaky test will cause tests to be
// re-run a few time until they succeed or exceed our iteration limit.
package flakytest
import (
"fmt"
"os"
"path"
"regexp"
"sync"
"testing"
"tailscale.com/util/mak"
)
// FlakyTestLogMessage is a sentinel value that is printed to stderr when a
// flaky test is marked. This is used by cmd/testwrapper to detect flaky tests
// and retry them.
const FlakyTestLogMessage = "flakytest: this is a known flaky test"
// FlakeAttemptEnv is an environment variable that is set by cmd/testwrapper
// when a flaky test is being (re)tried. It contains the attempt number,
// starting at 1.
const FlakeAttemptEnv = "TS_TESTWRAPPER_ATTEMPT"
var issueRegexp = regexp.MustCompile(`\Ahttps://github\.com/tailscale/[a-zA-Z0-9_.-]+/issues/\d+\z`)
var (
rootFlakesMu sync.Mutex
rootFlakes map[string]bool
)
// Mark sets the current test as a flaky test, such that if it fails, it will
// be retried a few times on failure. issue must be a GitHub issue that tracks
// the status of the flaky test being marked, of the format:
//
// https://github.com/tailscale/myRepo-H3re/issues/12345
func Mark(t testing.TB, issue string) {
if !issueRegexp.MatchString(issue) {
t.Fatalf("bad issue format: %q", issue)
}
if _, ok := os.LookupEnv(FlakeAttemptEnv); ok {
// We're being run under cmd/testwrapper so send our sentinel message
// to stderr. (We avoid doing this when the env is absent to avoid
// spamming people running tests without the wrapper)
fmt.Fprintf(os.Stderr, "%s: %s\n", FlakyTestLogMessage, issue)
}
t.Logf("flakytest: issue tracking this flaky test: %s", issue)
// Record the root test name as flakey.
rootFlakesMu.Lock()
defer rootFlakesMu.Unlock()
mak.Set(&rootFlakes, t.Name(), true)
}
// Marked reports whether the current test or one of its parents was marked flaky.
func Marked(t testing.TB) bool {
n := t.Name()
for {
if rootFlakes[n] {
return true
}
n = path.Dir(n)
if n == "." || n == "/" {
break
}
}
return false
}