internal: add build tags guarding code that doesn't build on plan9

This is intended to get the misc-compile-plan9 builder passing.
internal/static adds a stub for plan9 that panics since the esbuild
module it uses doesn't build on plan9. A bunch of tests that use
miniredis are build tagged since miniredis doesn't build on plan9 The
setup of testDB in server_test.go is moved to its own file
frontend_test so it can be used by other test files in the package
while allowing us to disable server_test which uses miniredis.

For #61209

Change-Id: Iacb39180459e31c946d02b62e8c03e91368c087a
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/508448
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Michael Matloob <matloob@google.com>
diff --git a/internal/cache/cache_test.go b/internal/cache/cache_test.go
index 6ac0a4c..8f1735e 100644
--- a/internal/cache/cache_test.go
+++ b/internal/cache/cache_test.go
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/alicebob/miniredis/v2 pulls in
+// github.com/yuin/gopher-lua which uses a non
+// build-tag-guarded use of the syscall package.
+//go:build !plan9
+
 package cache
 
 import (
diff --git a/internal/frontend/frontend_test.go b/internal/frontend/frontend_test.go
new file mode 100644
index 0000000..8b51c3e
--- /dev/null
+++ b/internal/frontend/frontend_test.go
@@ -0,0 +1,134 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package frontend
+
+import (
+	"context"
+	"net/http"
+	"testing"
+	"time"
+
+	"github.com/go-redis/redis/v8"
+	"github.com/google/safehtml/template"
+	"golang.org/x/pkgsite/internal"
+	"golang.org/x/pkgsite/internal/middleware"
+	"golang.org/x/pkgsite/internal/postgres"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
+	"golang.org/x/pkgsite/internal/queue"
+	"golang.org/x/pkgsite/internal/source"
+	"golang.org/x/pkgsite/internal/testing/sample"
+	"golang.org/x/pkgsite/static"
+	thirdparty "golang.org/x/pkgsite/third_party"
+)
+
+const testTimeout = 5 * time.Second
+
+var testDB *postgres.DB
+
+func TestMain(m *testing.M) {
+	postgres.RunDBTests("discovery_frontend_test", m, &testDB)
+}
+
+type testModule struct {
+	path            string
+	redistributable bool
+	versions        []string
+	packages        []testPackage
+}
+
+type testPackage struct {
+	name           string
+	suffix         string
+	readmeContents string
+	readmeFilePath string
+	docs           []*internal.Documentation
+}
+
+func newTestServer(t *testing.T, proxyModules []*proxytest.Module, redisClient *redis.Client, experimentNames ...string) (*Server, http.Handler, func()) {
+	t.Helper()
+	proxyClient, teardown := proxytest.SetupTestClient(t, proxyModules)
+	sourceClient := source.NewClient(sourceTimeout)
+	ctx := context.Background()
+
+	q := queue.NewInMemory(ctx, 1, experimentNames,
+		func(ctx context.Context, mpath, version string) (int, error) {
+			return FetchAndUpdateState(ctx, mpath, version, proxyClient, sourceClient, testDB)
+		})
+
+	s, err := NewServer(ServerConfig{
+		DataSourceGetter:     func(context.Context) internal.DataSource { return testDB },
+		Queue:                q,
+		TaskIDChangeInterval: 10 * time.Minute,
+		TemplateFS:           template.TrustedFSFromEmbed(static.FS),
+		// Use the embedded FSs here to make sure they're tested.
+		// Integration tests will use the actual directories.
+		StaticFS:     static.FS,
+		ThirdPartyFS: thirdparty.FS,
+		StaticPath:   "../../static",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	mux := http.NewServeMux()
+	s.Install(mux.Handle, redisClient, nil)
+
+	var exps []*internal.Experiment
+	for _, n := range experimentNames {
+		exps = append(exps, &internal.Experiment{Name: n, Rollout: 100})
+	}
+	exp, err := middleware.NewExperimenter(ctx, time.Hour, func(context.Context) ([]*internal.Experiment, error) { return exps, nil }, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	mw := middleware.Experiment(exp)
+	return s, mw(mux), func() {
+		teardown()
+		postgres.ResetTestDB(testDB, t)
+	}
+}
+
+func insertTestModules(ctx context.Context, t *testing.T, mods []testModule) {
+	for _, mod := range mods {
+		var (
+			suffixes []string
+			pkgs     = make(map[string]testPackage)
+		)
+		for _, pkg := range mod.packages {
+			suffixes = append(suffixes, pkg.suffix)
+			pkgs[pkg.suffix] = pkg
+		}
+		for _, ver := range mod.versions {
+			m := sample.Module(mod.path, ver, suffixes...)
+			m.SourceInfo = source.NewGitHubInfo(sample.RepositoryURL, "", ver)
+			m.IsRedistributable = mod.redistributable
+			if !m.IsRedistributable {
+				m.Licenses = nil
+			}
+			for _, u := range m.Units {
+				if pkg, ok := pkgs[internal.Suffix(u.Path, m.ModulePath)]; ok {
+					if pkg.name != "" {
+						u.Name = pkg.name
+					}
+					if pkg.readmeContents != "" {
+						u.Readme = &internal.Readme{
+							Contents: pkg.readmeContents,
+							Filepath: pkg.readmeFilePath,
+						}
+					}
+					if pkg.docs != nil {
+						u.Documentation = pkg.docs
+					}
+				}
+				if !mod.redistributable {
+					u.IsRedistributable = false
+					u.Licenses = nil
+					u.Documentation = nil
+					u.Readme = nil
+				}
+			}
+			postgres.MustInsertModule(ctx, t, testDB, m)
+		}
+	}
+}
diff --git a/internal/frontend/server_test.go b/internal/frontend/server_test.go
index 125f1be..1d9e7be 100644
--- a/internal/frontend/server_test.go
+++ b/internal/frontend/server_test.go
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/alicebob/miniredis/v2 pulls in
+// github.com/yuin/gopher-lua which uses a non
+// build-tag-guarded use of the syscall package.
+//go:build !plan9
+
 package frontend
 
 import (
@@ -26,27 +31,14 @@
 	"golang.org/x/pkgsite/internal/cookie"
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/experiment"
-	"golang.org/x/pkgsite/internal/middleware"
 	"golang.org/x/pkgsite/internal/postgres"
-	"golang.org/x/pkgsite/internal/proxy/proxytest"
-	"golang.org/x/pkgsite/internal/queue"
-	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/testing/htmlcheck"
 	"golang.org/x/pkgsite/internal/testing/pagecheck"
 	"golang.org/x/pkgsite/internal/testing/sample"
 	"golang.org/x/pkgsite/internal/version"
 	"golang.org/x/pkgsite/static"
-	thirdparty "golang.org/x/pkgsite/third_party"
 )
 
-const testTimeout = 5 * time.Second
-
-var testDB *postgres.DB
-
-func TestMain(m *testing.M) {
-	postgres.RunDBTests("discovery_frontend_test", m, &testDB)
-}
-
 func TestHTMLInjection(t *testing.T) {
 	_, handler, _ := newTestServer(t, nil, nil)
 	w := httptest.NewRecorder()
@@ -58,21 +50,6 @@
 
 const pseudoVersion = "v0.0.0-20140414041502-123456789012"
 
-type testModule struct {
-	path            string
-	redistributable bool
-	versions        []string
-	packages        []testPackage
-}
-
-type testPackage struct {
-	name           string
-	suffix         string
-	readmeContents string
-	readmeFilePath string
-	docs           []*internal.Documentation
-}
-
 type serverTestCase struct {
 	// name of the test
 	name string
@@ -308,50 +285,6 @@
 	},
 }
 
-func insertTestModules(ctx context.Context, t *testing.T, mods []testModule) {
-	for _, mod := range mods {
-		var (
-			suffixes []string
-			pkgs     = make(map[string]testPackage)
-		)
-		for _, pkg := range mod.packages {
-			suffixes = append(suffixes, pkg.suffix)
-			pkgs[pkg.suffix] = pkg
-		}
-		for _, ver := range mod.versions {
-			m := sample.Module(mod.path, ver, suffixes...)
-			m.SourceInfo = source.NewGitHubInfo(sample.RepositoryURL, "", ver)
-			m.IsRedistributable = mod.redistributable
-			if !m.IsRedistributable {
-				m.Licenses = nil
-			}
-			for _, u := range m.Units {
-				if pkg, ok := pkgs[internal.Suffix(u.Path, m.ModulePath)]; ok {
-					if pkg.name != "" {
-						u.Name = pkg.name
-					}
-					if pkg.readmeContents != "" {
-						u.Readme = &internal.Readme{
-							Contents: pkg.readmeContents,
-							Filepath: pkg.readmeFilePath,
-						}
-					}
-					if pkg.docs != nil {
-						u.Documentation = pkg.docs
-					}
-				}
-				if !mod.redistributable {
-					u.IsRedistributable = false
-					u.Licenses = nil
-					u.Documentation = nil
-					u.Readme = nil
-				}
-			}
-			postgres.MustInsertModule(ctx, t, testDB, m)
-		}
-	}
-}
-
 var (
 	in      = htmlcheck.In
 	notIn   = htmlcheck.NotIn
@@ -1515,49 +1448,6 @@
 	}
 }
 
-func newTestServer(t *testing.T, proxyModules []*proxytest.Module, redisClient *redis.Client, experimentNames ...string) (*Server, http.Handler, func()) {
-	t.Helper()
-	proxyClient, teardown := proxytest.SetupTestClient(t, proxyModules)
-	sourceClient := source.NewClient(sourceTimeout)
-	ctx := context.Background()
-
-	q := queue.NewInMemory(ctx, 1, experimentNames,
-		func(ctx context.Context, mpath, version string) (int, error) {
-			return FetchAndUpdateState(ctx, mpath, version, proxyClient, sourceClient, testDB)
-		})
-
-	s, err := NewServer(ServerConfig{
-		DataSourceGetter:     func(context.Context) internal.DataSource { return testDB },
-		Queue:                q,
-		TaskIDChangeInterval: 10 * time.Minute,
-		TemplateFS:           template.TrustedFSFromEmbed(static.FS),
-		// Use the embedded FSs here to make sure they're tested.
-		// Integration tests will use the actual directories.
-		StaticFS:     static.FS,
-		ThirdPartyFS: thirdparty.FS,
-		StaticPath:   "../../static",
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-	mux := http.NewServeMux()
-	s.Install(mux.Handle, redisClient, nil)
-
-	var exps []*internal.Experiment
-	for _, n := range experimentNames {
-		exps = append(exps, &internal.Experiment{Name: n, Rollout: 100})
-	}
-	exp, err := middleware.NewExperimenter(ctx, time.Hour, func(context.Context) ([]*internal.Experiment, error) { return exps, nil }, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	mw := middleware.Experiment(exp)
-	return s, mw(mux), func() {
-		teardown()
-		postgres.ResetTestDB(testDB, t)
-	}
-}
-
 func TestCheckTemplates(t *testing.T) {
 	// Perform additional checks on parsed templates.
 	staticFS := template.TrustedFSFromEmbed(static.FS)
diff --git a/internal/middleware/caching_test.go b/internal/middleware/caching_test.go
index 385a6b0..2f46b93 100644
--- a/internal/middleware/caching_test.go
+++ b/internal/middleware/caching_test.go
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/alicebob/miniredis/v2 pulls in
+// github.com/yuin/gopher-lua which uses a non
+// build-tag-guarded use of the syscall package.
+//go:build !plan9
+
 package middleware
 
 import (
diff --git a/internal/middleware/quota_test.go b/internal/middleware/quota_test.go
index f2b03a8..bc8ab1b 100644
--- a/internal/middleware/quota_test.go
+++ b/internal/middleware/quota_test.go
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/alicebob/miniredis/v2 pulls in
+// github.com/yuin/gopher-lua which uses a non
+// build-tag-guarded use of the syscall package.
+//go:build !plan9
+
 package middleware
 
 import (
diff --git a/internal/static/config.go b/internal/static/config.go
new file mode 100644
index 0000000..369a043
--- /dev/null
+++ b/internal/static/config.go
@@ -0,0 +1,20 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package static
+
+type Config struct {
+	// Entrypoint is a directory in which to to build TypeScript
+	// sources.
+	EntryPoint string
+
+	// Bundle is true if files imported by an entry file
+	// should be joined together in a single output file.
+	Bundle bool
+
+	// Watch is true in development. Sourcemaps are placed inline,
+	// the output is unminified, and changes to any TypeScript
+	// files will force a rebuild of the JavaScript output.
+	Watch bool
+}
diff --git a/internal/static/static.go b/internal/static/static.go
index bb6fff2..25b3614 100644
--- a/internal/static/static.go
+++ b/internal/static/static.go
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/evanw/esbuild doesn't compile on plan9
+//go:build !plan9
+
 // Package static builds static assets for the frontend and the worker.
 package static
 
@@ -14,21 +17,6 @@
 	"github.com/evanw/esbuild/pkg/api"
 )
 
-type Config struct {
-	// Entrypoint is a directory in which to to build TypeScript
-	// sources.
-	EntryPoint string
-
-	// Bundle is true if files imported by an entry file
-	// should be joined together in a single output file.
-	Bundle bool
-
-	// Watch is true in development. Sourcemaps are placed inline,
-	// the output is unminified, and changes to any TypeScript
-	// files will force a rebuild of the JavaScript output.
-	Watch bool
-}
-
 // Build compiles TypeScript files into minified JavaScript
 // files using github.com/evanw/esbuild.
 //
diff --git a/internal/static/stub_plan9.go b/internal/static/stub_plan9.go
new file mode 100644
index 0000000..a519ba0
--- /dev/null
+++ b/internal/static/stub_plan9.go
@@ -0,0 +1,15 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Since github.com/evanw/esbuild doesn't build on plan9
+// this function stubs out the build function with a function
+// that panics.
+
+//go:build plan9
+
+package static
+
+func Build(config Config) error {
+	panic("This functionality is not supported on plan9")
+}
diff --git a/internal/testing/integration/common_test.go b/internal/testing/integration/common_test.go
new file mode 100644
index 0000000..474227a
--- /dev/null
+++ b/internal/testing/integration/common_test.go
@@ -0,0 +1,15 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package integration
+
+import (
+	"golang.org/x/pkgsite/internal/postgres"
+	"golang.org/x/pkgsite/internal/proxy/proxytest"
+)
+
+var (
+	testDB      *postgres.DB
+	testModules []*proxytest.Module
+)
diff --git a/internal/testing/integration/integration_test.go b/internal/testing/integration/integration_test.go
index e4f78d6..6ac8a5f 100644
--- a/internal/testing/integration/integration_test.go
+++ b/internal/testing/integration/integration_test.go
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/alicebob/miniredis/v2 pulls in
+// github.com/yuin/gopher-lua which uses a non
+// build-tag-guarded use of the syscall package.
+//go:build !plan9
+
 package integration
 
 import (
@@ -26,11 +31,6 @@
 	"golang.org/x/pkgsite/internal/proxy/proxytest"
 )
 
-var (
-	testDB      *postgres.DB
-	testModules []*proxytest.Module
-)
-
 func TestMain(m *testing.M) {
 	dochtml.LoadTemplates(template.TrustedFSFromTrustedSource(template.TrustedSourceFromConstant("../../../static")))
 	testModules = proxytest.LoadTestModules("../../proxy/testdata")
diff --git a/internal/testing/integration/worker_test.go b/internal/testing/integration/worker_test.go
index 6afd5fe..110a21b 100644
--- a/internal/testing/integration/worker_test.go
+++ b/internal/testing/integration/worker_test.go
@@ -2,6 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// github.com/alicebob/miniredis/v2 pulls in
+// github.com/yuin/gopher-lua which uses a non
+// build-tag-guarded use of the syscall package.
+//go:build !plan9
+
 package integration
 
 import (