1package main
2
3import (
4	"flag"
5	"runtime"
6
7	"time"
8
9	"github.com/onsi/ginkgo/config"
10)
11
12type RunWatchAndBuildCommandFlags struct {
13	Recurse     bool
14	SkipPackage string
15	GoOpts      map[string]interface{}
16
17	//for run and watch commands
18	NumCPU         int
19	NumCompilers   int
20	ParallelStream bool
21	Notify         bool
22	AfterSuiteHook string
23	AutoNodes      bool
24	Timeout        time.Duration
25
26	//only for run command
27	KeepGoing       bool
28	UntilItFails    bool
29	RandomizeSuites bool
30
31	//only for watch command
32	Depth       int
33	WatchRegExp string
34
35	FlagSet *flag.FlagSet
36}
37
38const runMode = 1
39const watchMode = 2
40const buildMode = 3
41
42func NewRunCommandFlags(flagSet *flag.FlagSet) *RunWatchAndBuildCommandFlags {
43	c := &RunWatchAndBuildCommandFlags{
44		FlagSet: flagSet,
45	}
46	c.flags(runMode)
47	return c
48}
49
50func NewWatchCommandFlags(flagSet *flag.FlagSet) *RunWatchAndBuildCommandFlags {
51	c := &RunWatchAndBuildCommandFlags{
52		FlagSet: flagSet,
53	}
54	c.flags(watchMode)
55	return c
56}
57
58func NewBuildCommandFlags(flagSet *flag.FlagSet) *RunWatchAndBuildCommandFlags {
59	c := &RunWatchAndBuildCommandFlags{
60		FlagSet: flagSet,
61	}
62	c.flags(buildMode)
63	return c
64}
65
66func (c *RunWatchAndBuildCommandFlags) wasSet(flagName string) bool {
67	wasSet := false
68	c.FlagSet.Visit(func(f *flag.Flag) {
69		if f.Name == flagName {
70			wasSet = true
71		}
72	})
73
74	return wasSet
75}
76
77func (c *RunWatchAndBuildCommandFlags) computeNodes() {
78	if c.wasSet("nodes") {
79		return
80	}
81	if c.AutoNodes {
82		switch n := runtime.NumCPU(); {
83		case n <= 4:
84			c.NumCPU = n
85		default:
86			c.NumCPU = n - 1
87		}
88	}
89}
90
91func (c *RunWatchAndBuildCommandFlags) stringSlot(slot string) *string {
92	var opt string
93	c.GoOpts[slot] = &opt
94	return &opt
95}
96
97func (c *RunWatchAndBuildCommandFlags) boolSlot(slot string) *bool {
98	var opt bool
99	c.GoOpts[slot] = &opt
100	return &opt
101}
102
103func (c *RunWatchAndBuildCommandFlags) intSlot(slot string) *int {
104	var opt int
105	c.GoOpts[slot] = &opt
106	return &opt
107}
108
109func (c *RunWatchAndBuildCommandFlags) flags(mode int) {
110	c.GoOpts = make(map[string]interface{})
111
112	onWindows := (runtime.GOOS == "windows")
113
114	c.FlagSet.BoolVar(&(c.Recurse), "r", false, "Find and run test suites under the current directory recursively.")
115	c.FlagSet.BoolVar(c.boolSlot("race"), "race", false, "Run tests with race detection enabled.")
116	c.FlagSet.BoolVar(c.boolSlot("cover"), "cover", false, "Run tests with coverage analysis, will generate coverage profiles with the package name in the current directory.")
117	c.FlagSet.StringVar(c.stringSlot("coverpkg"), "coverpkg", "", "Run tests with coverage on the given external modules.")
118	c.FlagSet.StringVar(&(c.SkipPackage), "skipPackage", "", "A comma-separated list of package names to be skipped.  If any part of the package's path matches, that package is ignored.")
119	c.FlagSet.StringVar(c.stringSlot("tags"), "tags", "", "A list of build tags to consider satisfied during the build.")
120	c.FlagSet.StringVar(c.stringSlot("gcflags"), "gcflags", "", "Arguments to pass on each go tool compile invocation.")
121	c.FlagSet.StringVar(c.stringSlot("covermode"), "covermode", "", "Set the mode for coverage analysis.")
122	c.FlagSet.BoolVar(c.boolSlot("a"), "a", false, "Force rebuilding of packages that are already up-to-date.")
123	c.FlagSet.BoolVar(c.boolSlot("n"), "n", false, "Have `go test` print the commands but do not run them.")
124	c.FlagSet.BoolVar(c.boolSlot("msan"), "msan", false, "Enable interoperation with memory sanitizer.")
125	c.FlagSet.BoolVar(c.boolSlot("x"), "x", false, "Have `go test` print the commands.")
126	c.FlagSet.BoolVar(c.boolSlot("work"), "work", false, "Print the name of the temporary work directory and do not delete it when exiting.")
127	c.FlagSet.StringVar(c.stringSlot("asmflags"), "asmflags", "", "Arguments to pass on each go tool asm invocation.")
128	c.FlagSet.StringVar(c.stringSlot("buildmode"), "buildmode", "", "Build mode to use. See 'go help buildmode' for more.")
129	c.FlagSet.StringVar(c.stringSlot("mod"), "mod", "", "Go module control. See 'go help modules' for more.")
130	c.FlagSet.StringVar(c.stringSlot("compiler"), "compiler", "", "Name of compiler to use, as in runtime.Compiler (gccgo or gc).")
131	c.FlagSet.StringVar(c.stringSlot("gccgoflags"), "gccgoflags", "", "Arguments to pass on each gccgo compiler/linker invocation.")
132	c.FlagSet.StringVar(c.stringSlot("installsuffix"), "installsuffix", "", "A suffix to use in the name of the package installation directory.")
133	c.FlagSet.StringVar(c.stringSlot("ldflags"), "ldflags", "", "Arguments to pass on each go tool link invocation.")
134	c.FlagSet.BoolVar(c.boolSlot("linkshared"), "linkshared", false, "Link against shared libraries previously created with -buildmode=shared.")
135	c.FlagSet.StringVar(c.stringSlot("pkgdir"), "pkgdir", "", "install and load all packages from the given dir instead of the usual locations.")
136	c.FlagSet.StringVar(c.stringSlot("toolexec"), "toolexec", "", "a program to use to invoke toolchain programs like vet and asm.")
137	c.FlagSet.IntVar(c.intSlot("blockprofilerate"), "blockprofilerate", 1, "Control the detail provided in goroutine blocking profiles by calling runtime.SetBlockProfileRate with the given value.")
138	c.FlagSet.StringVar(c.stringSlot("coverprofile"), "coverprofile", "", "Write a coverage profile to the specified file after all tests have passed.")
139	c.FlagSet.StringVar(c.stringSlot("cpuprofile"), "cpuprofile", "", "Write a CPU profile to the specified file before exiting.")
140	c.FlagSet.StringVar(c.stringSlot("memprofile"), "memprofile", "", "Write a memory profile to the specified file after all tests have passed.")
141	c.FlagSet.IntVar(c.intSlot("memprofilerate"), "memprofilerate", 0, "Enable more precise (and expensive) memory profiles by setting runtime.MemProfileRate.")
142	c.FlagSet.StringVar(c.stringSlot("outputdir"), "outputdir", "", "Place output files from profiling in the specified directory.")
143	c.FlagSet.BoolVar(c.boolSlot("requireSuite"), "requireSuite", false, "Fail if there are ginkgo tests in a directory but no test suite (missing RunSpecs)")
144	c.FlagSet.StringVar(c.stringSlot("vet"), "vet", "", "Configure the invocation of 'go vet' to use the comma-separated list of vet checks. If list is 'off', 'go test' does not run 'go vet' at all.")
145
146	if mode == runMode || mode == watchMode {
147		config.Flags(c.FlagSet, "", false)
148		c.FlagSet.IntVar(&(c.NumCPU), "nodes", 1, "The number of parallel test nodes to run")
149		c.FlagSet.IntVar(&(c.NumCompilers), "compilers", 0, "The number of concurrent compilations to run (0 will autodetect)")
150		c.FlagSet.BoolVar(&(c.AutoNodes), "p", false, "Run in parallel with auto-detected number of nodes")
151		c.FlagSet.BoolVar(&(c.ParallelStream), "stream", onWindows, "stream parallel test output in real time: less coherent, but useful for debugging")
152		if !onWindows {
153			c.FlagSet.BoolVar(&(c.Notify), "notify", false, "Send desktop notifications when a test run completes")
154		}
155		c.FlagSet.StringVar(&(c.AfterSuiteHook), "afterSuiteHook", "", "Run a command when a suite test run completes")
156		c.FlagSet.DurationVar(&(c.Timeout), "timeout", 24*time.Hour, "Suite fails if it does not complete within the specified timeout")
157	}
158
159	if mode == runMode {
160		c.FlagSet.BoolVar(&(c.KeepGoing), "keepGoing", false, "When true, failures from earlier test suites do not prevent later test suites from running")
161		c.FlagSet.BoolVar(&(c.UntilItFails), "untilItFails", false, "When true, Ginkgo will keep rerunning tests until a failure occurs")
162		c.FlagSet.BoolVar(&(c.RandomizeSuites), "randomizeSuites", false, "When true, Ginkgo will randomize the order in which test suites run")
163	}
164
165	if mode == watchMode {
166		c.FlagSet.IntVar(&(c.Depth), "depth", 1, "Ginkgo will watch dependencies down to this depth in the dependency tree")
167		c.FlagSet.StringVar(&(c.WatchRegExp), "watchRegExp", `\.go$`, "Files matching this regular expression will be watched for changes")
168	}
169}
170