mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-11-03 16:31:20 +00:00 
			
		
		
		
	And enable U1000 check in staticcheck. Updates #cleanup Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
		
			
				
	
	
		
			115 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright (c) Tailscale Inc & AUTHORS
 | 
						|
// SPDX-License-Identifier: BSD-3-Clause
 | 
						|
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"flag"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"slices"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
// registerTestFlags registers all flags from the testing package with the
 | 
						|
// provided flag set. It does so by calling testing.Init() and then iterating
 | 
						|
// over all flags registered on flag.CommandLine.
 | 
						|
func registerTestFlags(fs *flag.FlagSet) {
 | 
						|
	testing.Init()
 | 
						|
	type bv interface {
 | 
						|
		IsBoolFlag() bool
 | 
						|
	}
 | 
						|
 | 
						|
	flag.CommandLine.VisitAll(func(f *flag.Flag) {
 | 
						|
		if b, ok := f.Value.(bv); ok && b.IsBoolFlag() {
 | 
						|
			fs.Bool(f.Name, f.DefValue == "true", f.Usage)
 | 
						|
			if name, ok := strings.CutPrefix(f.Name, "test."); ok {
 | 
						|
				fs.Bool(name, f.DefValue == "true", f.Usage)
 | 
						|
			}
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		// We don't actually care about the value of the flag, so we just
 | 
						|
		// register it as a string. The values will be passed to `go test` which
 | 
						|
		// will parse and validate them anyway.
 | 
						|
		fs.String(f.Name, f.DefValue, f.Usage)
 | 
						|
		if name, ok := strings.CutPrefix(f.Name, "test."); ok {
 | 
						|
			fs.String(name, f.DefValue, f.Usage)
 | 
						|
		}
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// splitArgs splits args into three parts as consumed by go test.
 | 
						|
//
 | 
						|
//	go test [build/test flags] [packages] [build/test flags & test binary flags]
 | 
						|
//
 | 
						|
// We return these as three slices of strings [pre] [pkgs] [post].
 | 
						|
//
 | 
						|
// It is used to split the arguments passed to testwrapper into the arguments
 | 
						|
// passed to go test and the arguments passed to the tests.
 | 
						|
func splitArgs(args []string) (pre, pkgs, post []string, _ error) {
 | 
						|
	if len(args) == 0 {
 | 
						|
		return nil, nil, nil, nil
 | 
						|
	}
 | 
						|
 | 
						|
	fs := newTestFlagSet()
 | 
						|
	// Parse stops at the first non-flag argument, so this allows us
 | 
						|
	// to parse those as values and then reconstruct them as args.
 | 
						|
	if err := fs.Parse(args); err != nil {
 | 
						|
		return nil, nil, nil, err
 | 
						|
	}
 | 
						|
	fs.Visit(func(f *flag.Flag) {
 | 
						|
		if f.Value.String() != f.DefValue && f.DefValue != "false" {
 | 
						|
			pre = append(pre, "-"+f.Name, f.Value.String())
 | 
						|
		} else {
 | 
						|
			pre = append(pre, "-"+f.Name)
 | 
						|
		}
 | 
						|
	})
 | 
						|
 | 
						|
	// fs.Args() now contains [packages]+[build/test flags & test binary flags],
 | 
						|
	// to split it we need to find the first non-flag argument.
 | 
						|
	rem := fs.Args()
 | 
						|
	ix := slices.IndexFunc(rem, func(s string) bool { return strings.HasPrefix(s, "-") })
 | 
						|
	if ix == -1 {
 | 
						|
		return pre, rem, nil, nil
 | 
						|
	}
 | 
						|
	pkgs = rem[:ix]
 | 
						|
	post = rem[ix:]
 | 
						|
	return pre, pkgs, post, nil
 | 
						|
}
 | 
						|
 | 
						|
func newTestFlagSet() *flag.FlagSet {
 | 
						|
	fs := flag.NewFlagSet("testwrapper", flag.ContinueOnError)
 | 
						|
	fs.SetOutput(io.Discard)
 | 
						|
 | 
						|
	// Register all flags from the testing package.
 | 
						|
	registerTestFlags(fs)
 | 
						|
	// Also register the -exec flag, which is not part of the testing package.
 | 
						|
	// TODO(maisem): figure out what other flags we need to register explicitly.
 | 
						|
	fs.String("exec", "", "Command to run tests with")
 | 
						|
	fs.Bool("race", false, "build with race detector")
 | 
						|
	return fs
 | 
						|
}
 | 
						|
 | 
						|
// testingVerbose reports whether the test is being run with verbose logging.
 | 
						|
var testingVerbose = func() bool {
 | 
						|
	verbose := false
 | 
						|
 | 
						|
	// Likely doesn't matter, but to be correct follow the go flag parsing logic
 | 
						|
	// of overriding previous values.
 | 
						|
	for _, arg := range os.Args[1:] {
 | 
						|
		switch arg {
 | 
						|
		case "-test.v", "--test.v",
 | 
						|
			"-test.v=true", "--test.v=true",
 | 
						|
			"-v", "--v",
 | 
						|
			"-v=true", "--v=true":
 | 
						|
			verbose = true
 | 
						|
		case "-test.v=false", "--test.v=false",
 | 
						|
			"-v=false", "--v=false":
 | 
						|
			verbose = false
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return verbose
 | 
						|
}()
 |