diff --git a/hive.go b/hive.go index e5c982d71b..f06f38be92 100644 --- a/hive.go +++ b/hive.go @@ -26,6 +26,7 @@ func main() { dockerOutput = flag.Bool("docker.output", false, "Relay all docker output to stderr.") simPattern = flag.String("sim", "", "Regular `expression` selecting the simulators to run.") simTestPattern = flag.String("sim.limit", "", "Regular `expression` selecting tests/suites (interpreted by simulators).") + simTestExact = flag.String("sim.limit.exact", "", "Exact `expression` match for tests/suites (interpreted by simulators).") simParallelism = flag.Int("sim.parallelism", 1, "Max `number` of parallel clients/containers (interpreted by simulators).") simTestLimit = flag.Int("sim.testlimit", 0, "[DEPRECATED] Max `number` of tests to execute per client (interpreted by simulators).") simTimeLimit = flag.Duration("sim.timelimit", 0, "Simulation `timeout`. Hive aborts the simulator if it exceeds this time.") @@ -72,6 +73,9 @@ func main() { log15.Warn("--sim is ignored when using --dev mode") simList = nil } + if *simTestExact != "" && *simTestPattern != "" { + fatal("only one of --sim.limit and --sim.limit.exact can be provided") + } // Create the docker backends. dockerConfig := &libdocker.Config{ @@ -108,6 +112,7 @@ func main() { env := libhive.SimEnv{ LogDir: *testResultsRoot, SimLogLevel: *simLogLevel, + SimTestExact: *simTestExact, SimTestPattern: *simTestPattern, SimParallelism: *simParallelism, SimDurationLimit: *simTimeLimit, diff --git a/hivesim/hive.go b/hivesim/hive.go index c70c4d445b..6824a9f9e0 100644 --- a/hivesim/hive.go +++ b/hivesim/hive.go @@ -35,6 +35,13 @@ func New() *Simulation { panic("HIVE_SIMULATOR environment variable is empty") } sim := &Simulation{url: url} + if e := os.Getenv("HIVE_TEST_EXACT"); e != "" { + m, err := parseTestExact(e) + if err != nil { + fmt.Fprintln(os.Stderr, "Warning: invalid exact simulator/test match: "+err.Error()) + } + sim.m = m + } if p := os.Getenv("HIVE_TEST_PATTERN"); p != "" { m, err := parseTestPattern(p) if err != nil { diff --git a/hivesim/testapi.go b/hivesim/testapi.go index 9485f33c8d..03b6b86250 100644 --- a/hivesim/testapi.go +++ b/hivesim/testapi.go @@ -53,6 +53,9 @@ func RunSuite(host *Simulation, suite Suite) error { fmt.Fprintf(os.Stderr, "skipping suite %q because it doesn't match test pattern %s\n", suite.Name, host.m.pattern) return nil } + if host.m.isExact && host.m.exactSuite != suite.Name { + return nil + } suiteID, err := host.StartSuite(suite.Name, suite.Description, "") if err != nil { @@ -82,13 +85,12 @@ func MustRunSuite(host *Simulation, suite Suite) { // Using this test type doesn't launch any clients by default. To interact with clients, // you can launch them using the t.Client method: // -// c := t.Client() -// c.RPC().Call(...) +// c := t.Client() +// c.RPC().Call(...) // // or run a subtest using t.RunClientTest(): // -// t.RunClientTest(hivesim.ClientTestSpec{...}) -// +// t.RunClientTest(hivesim.ClientTestSpec{...}) type TestSpec struct { // These fields are displayed in the UI. Be sure to add // a meaningful description here. @@ -309,6 +311,9 @@ func runTest(host *Simulation, test testSpec, runit func(t *T)) error { fmt.Fprintf(os.Stderr, "skipping test %q because it doesn't match test pattern %s\n", test.name, host.m.pattern) return nil } + if !test.alwaysRun && host.m.isExact && host.m.exactTest != test.name { + return nil + } // Register test on simulation server and initialize the T. t := &T{ diff --git a/hivesim/testmatch.go b/hivesim/testmatch.go index 3cf2655f0f..173e4c034c 100644 --- a/hivesim/testmatch.go +++ b/hivesim/testmatch.go @@ -6,9 +6,24 @@ import ( ) type testMatcher struct { - suite *regexp.Regexp - test *regexp.Regexp - pattern string + suite *regexp.Regexp + test *regexp.Regexp + pattern string + exactSuite string + exactTest string + isExact bool +} + +func parseTestExact(e string) (m testMatcher, err error) { + parts := strings.Split(e, "/") + if len(parts) > 0 { + m.exactSuite = parts[0] + } + if len(parts) > 1 { + m.exactTest = parts[1] + } + m.isExact = true + return m, nil } func parseTestPattern(p string) (m testMatcher, err error) { diff --git a/internal/libhive/run.go b/internal/libhive/run.go index 42b985e834..cd28052069 100644 --- a/internal/libhive/run.go +++ b/internal/libhive/run.go @@ -205,6 +205,7 @@ func (r *Runner) run(ctx context.Context, sim string, env SimEnv) (SimResult, er "HIVE_PARALLELISM": strconv.Itoa(env.SimParallelism), "HIVE_LOGLEVEL": strconv.Itoa(env.SimLogLevel), "HIVE_TEST_PATTERN": env.SimTestPattern, + "HIVE_TEST_EXACT": env.SimTestExact, }, } containerID, err := r.container.CreateContainer(ctx, r.simImages[sim], opts) diff --git a/internal/libhive/testmanager.go b/internal/libhive/testmanager.go index 18d5ffedae..1a51eb0cbc 100644 --- a/internal/libhive/testmanager.go +++ b/internal/libhive/testmanager.go @@ -35,6 +35,7 @@ type SimEnv struct { SimLogLevel int SimParallelism int SimTestPattern string + SimTestExact string // This is the time limit for the simulation run. // There is no default limit.