You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailscale/cmd/testwrapper/testwrapper.go

64 lines
1.4 KiB
Go

// Copyright (c) 2023 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// testwrapper is a wrapper for retrying flaky tests, using the -exec flag of
// 'go test'. Tests that are flaky can use the 'flakytest' subpackage to mark
// themselves as flaky and be retried on failure.
package main
import (
"context"
"errors"
"log"
"os"
"os/exec"
)
const (
retryStatus = 123
maxIterations = 3
)
func main() {
ctx := context.Background()
debug := os.Getenv("TS_TESTWRAPPER_DEBUG") != ""
log.SetPrefix("testwrapper: ")
if !debug {
log.SetFlags(0)
}
for i := 1; i <= maxIterations; i++ {
if i > 1 {
log.Printf("retrying flaky tests (%d of %d)", i, maxIterations)
}
cmd := exec.CommandContext(ctx, os.Args[1], os.Args[2:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), "TS_IN_TESTWRAPPER=1")
err := cmd.Run()
if err == nil {
return
}
var exitErr *exec.ExitError
if !errors.As(err, &exitErr) {
if debug {
log.Printf("error isn't an ExitError")
}
os.Exit(1)
}
if code := exitErr.ExitCode(); code != retryStatus {
if debug {
log.Printf("code (%d) != retryStatus (%d)", code, retryStatus)
}
os.Exit(code)
}
}
log.Printf("test did not pass in %d iterations", maxIterations)
os.Exit(1)
}