cmd/bench: add subrepo directories to run benchmarks on

For golang/go#53538

Change-Id: I0eb1d2f00ca1977bdd909e0a4bfe4367d388ba16
Reviewed-on: https://go-review.googlesource.com/c/benchmarks/+/453502
Reviewed-by: Michael Pratt <mpratt@google.com>
Run-TryBot: Dylan Le <dungtuanle@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/cmd/bench/gotest.go b/cmd/bench/gotest.go
index 4044b6b..25cfe65 100644
--- a/cmd/bench/gotest.go
+++ b/cmd/bench/gotest.go
@@ -13,10 +13,30 @@
 	for _, tc := range tcs {
 		log.Printf("Running Go test benchmarks for %s", tc.Name)
 		fmt.Printf("toolchain: %s\n", tc.Name)
-		err := tc.Do("test", "-v", "-run=none", "-bench=.", "-count=5", "golang.org/x/benchmarks/...")
+		err := tc.Do("", "test", "-v", "-run=none", "-bench=.", "-count=5", "golang.org/x/benchmarks/...")
 		if err != nil {
 			return fmt.Errorf("error running gotest with toolchain %s: %w", tc.Name, err)
 		}
 	}
 	return nil
 }
+
+func goTestSubrepo(tc *toolchain, subRepo string, dirs []string) error {
+	switch subRepo {
+	case "tools":
+		log.Printf("Running sub-repo benchmarks for %s", subRepo)
+		fmt.Printf("toolchain: %s\n", tc.Name)
+
+		for _, dir := range dirs {
+			err := tc.Do(dir, "test", "-v", "-bench=.", "./gopls/internal/regtest/bench/", "-count=5")
+			if err != nil {
+				log.Printf("Error: %v", err)
+				return fmt.Errorf("error running sub-repo %s benchmark with toolchain %s in dir %s: %w", subRepo, tc.Name, dir, err)
+			}
+		}
+	default:
+		return fmt.Errorf("unsupported subrepo %s", subRepo)
+	}
+
+	return nil
+}
diff --git a/cmd/bench/main.go b/cmd/bench/main.go
index 6469b57..ae634b0 100644
--- a/cmd/bench/main.go
+++ b/cmd/bench/main.go
@@ -23,11 +23,13 @@
 )
 
 var (
-	wait             = flag.Bool("wait", true, "wait for system idle before starting benchmarking")
-	gorootExperiment = flag.String("goroot", "", "GOROOT to test (default $GOROOT or 'go env GOROOT')")
-	gorootBaseline   = flag.String("goroot-baseline", "", "baseline GOROOT to test against (optional) (default $BENCH_BASELINE_GOROOT)")
-	branch           = flag.String("branch", "", "branch of the commits we're testing against (default $BENCH_BRANCH or unknown)")
-	repository       = flag.String("repository", "", "repository name of the commits we're testing against (default $BENCH_REPOSITORY or 'go')")
+	wait              = flag.Bool("wait", true, "wait for system idle before starting benchmarking")
+	gorootExperiment  = flag.String("goroot", "", "GOROOT to test (default $GOROOT or 'go env GOROOT')")
+	gorootBaseline    = flag.String("goroot-baseline", "", "baseline GOROOT to test against (optional) (default $BENCH_BASELINE_GOROOT)")
+	branch            = flag.String("branch", "", "branch of the commits we're testing against (default $BENCH_BRANCH or unknown)")
+	repository        = flag.String("repository", "", "repository name of the commits we're testing against (default $BENCH_REPOSITORY or 'go')")
+	subRepoExperiment = flag.String("subrepo", "", "Sub-repo dir to test (default $BENCH_SUBREPO_PATH)")
+	subRepoBaseline   = flag.String("subrepo-baseline", "", "Sub-repo baseline to test against (default $BENCH_SUBREPO_BASELINE_PATH)")
 )
 
 func determineGOROOT() (string, error) {
@@ -141,11 +143,24 @@
 	}
 	fmt.Printf("branch: %s\n", branch)
 
-	if repository != "go" {
-		// TODO(go.dev/issue/53538): Support other repositories.
-		log.Fatalf("Unknown repository %q", repository)
+	subRepoExperiment := *subRepoExperiment
+	if subRepoExperiment == "" {
+		subRepoExperiment = os.Getenv("BENCH_SUBREPO_PATH")
 	}
+	subRepoBaseline := *subRepoBaseline
+	if subRepoBaseline == "" {
+		subRepoBaseline = os.Getenv("BENCH_SUBREPO_BASELINE_PATH")
+	}
+	dirs := []string{subRepoExperiment, subRepoBaseline}
 
+	if repository != "go" {
+		toolchain := toolchainFromGOROOT("baseline", gorootBaseline)
+		if err := goTestSubrepo(toolchain, repository, dirs); err != nil {
+			log.Print("FAIL")
+			os.Exit(1)
+		}
+		return
+	}
 	// Run benchmarks against the toolchains.
 	if err := run(toolchains); err != nil {
 		log.Print("FAIL")
diff --git a/sweet/common/gotool.go b/sweet/common/gotool.go
index b86c6d0..14d3d58 100644
--- a/sweet/common/gotool.go
+++ b/sweet/common/gotool.go
@@ -30,8 +30,11 @@
 	}, nil
 }
 
-func (g *Go) Do(args ...string) error {
+func (g *Go) Do(dir string, args ...string) error {
 	cmd := exec.Command(g.Tool, args...)
+	if dir != "" {
+		cmd.Dir = dir
+	}
 	cmd.Env = g.Env.Collapse()
 	if g.PassOutput {
 		cmd.Stdout = os.Stdout
@@ -66,7 +69,7 @@
 	if pkg[0] == '/' || pkg[0] == '.' {
 		return fmt.Errorf("path used as package in go build")
 	}
-	return g.Do("build", "-o", out, pkg)
+	return g.Do("", "build", "-o", out, pkg)
 }
 
 func (g *Go) BuildPath(path, out string) error {
@@ -81,7 +84,7 @@
 	if err := chdir(path); err != nil {
 		return fmt.Errorf("failed to enter build directory: %w", err)
 	}
-	return g.Do("build", "-o", out)
+	return g.Do("", "build", "-o", out)
 }
 
 func chdir(path string) error {