Update to latest rules_go

Closes #465

PiperOrigin-RevId: 263216442
diff --git a/WORKSPACE b/WORKSPACE
index 00fe502..f4157f2 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -35,6 +35,10 @@
 load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
 install_bazel_dependencies()
 
+load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
+
+protobuf_deps()
+
 # Setup rules_go toolchain
 load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
 
diff --git a/package.bzl b/package.bzl
index 8052239..0f4ad48 100644
--- a/package.bzl
+++ b/package.bzl
@@ -47,11 +47,23 @@
     _maybe(
         http_archive,
         name = "io_bazel_rules_go",
+        patch_args = ["-p1"],
+        # Patch out a breaking change to runfiles support library
+        # See discussion on https://github.com/bazelbuild/rules_go/pull/2076
+        patches = ["@build_bazel_rules_typescript//:revert_rules_go_commit_4442d82a001f378d0605cbbca3fb529979a1c3a6.patch"],
+        sha256 = "8df59f11fb697743cbb3f26cfb8750395f30471e9eabde0d174c3aebc7a1cd39",
         urls = [
-            "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz",
-            "https://github.com/bazelbuild/rules_go/releases/download/0.18.5/rules_go-0.18.5.tar.gz",
+            "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/0.19.1/rules_go-0.19.1.tar.gz",
+            "https://github.com/bazelbuild/rules_go/releases/download/0.19.1/rules_go-0.19.1.tar.gz",
         ],
-        sha256 = "a82a352bffae6bee4e95f68a8d80a70e87f42c4741e6a448bec11998fcc82329",
+    )
+
+    _maybe(
+        http_archive,
+        name = "com_google_protobuf",
+        sha256 = "98e615d592d237f94db8bf033fba78cd404d979b0b70351a9e5aaff725398357",
+        strip_prefix = "protobuf-3.9.1",
+        urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.9.1.tar.gz"],
     )
 
     # go_repository is defined in bazel_gazelle
diff --git a/revert_rules_go_commit_4442d82a001f378d0605cbbca3fb529979a1c3a6.patch b/revert_rules_go_commit_4442d82a001f378d0605cbbca3fb529979a1c3a6.patch
new file mode 100644
index 0000000..e923592
--- /dev/null
+++ b/revert_rules_go_commit_4442d82a001f378d0605cbbca3fb529979a1c3a6.patch
@@ -0,0 +1,1365 @@
+diff --git a/go/tools/bazel/BUILD.bazel b/go/tools/bazel/BUILD.bazel
+index 6fbd4086..66656084 100644
+--- a/go/tools/bazel/BUILD.bazel
++++ b/go/tools/bazel/BUILD.bazel
+@@ -4,6 +4,8 @@ go_library(
+     name = "go_default_library",
+     srcs = [
+         "bazel.go",
++        "runfiledir.go",
++        "runfilemanifest.go",
+         "runfiles.go",
+     ],
+     importpath = "github.com/bazelbuild/rules_go/go/tools/bazel",
+@@ -13,8 +15,13 @@ go_library(
+ go_test(
+     name = "go_default_test",
+     size = "small",
+-    srcs = ["bazel_test.go"],
+-    data = ["README.md"],
++    srcs = [
++        "bazel_test.go",
++        "runfiles_test.go",
++    ],
++    data = [
++        "README.md",
++    ],
+     embed = [":go_default_library"],
+ )
+ 
+diff --git a/go/tools/bazel/bazel.go b/go/tools/bazel/bazel.go
+index 08bf3496..37f1b8d1 100644
+--- a/go/tools/bazel/bazel.go
++++ b/go/tools/bazel/bazel.go
+@@ -16,14 +16,76 @@
+ package bazel
+ 
+ import (
++	"fmt"
+ 	"io/ioutil"
+ 	"os"
++	"path/filepath"
++	"sync"
+ )
+ 
+ const TEST_SRCDIR = "TEST_SRCDIR"
+ const TEST_TMPDIR = "TEST_TMPDIR"
+ const TEST_WORKSPACE = "TEST_WORKSPACE"
+ 
++var (
++	defaultTestWorkspace = ""
++
++	runfileResolver     runfilesResolver
++	runfileResolverErr  error
++	runfileResolverOnce sync.Once
++)
++
++func getRunfilesResolver() (runfilesResolver, error) {
++	runfileResolverOnce.Do(func() {
++		runfileResolver, runfileResolverErr = newRunfilesResolver()
++	})
++	return runfileResolver, runfileResolverErr
++}
++
++// Runfile returns an absolute path to the specified file in the runfiles directory of the running target.
++// It searches the current working directory, the runfiles path, and the workspace subdirectory of runfiles.
++// If a runfiles manifest is present, it will be used to resolve files not present in the working directory.
++// Returns an error if the file could not be found, or if an error occurs trying to find the runfiles env.
++func Runfile(path string) (string, error) {
++	// Search in working directory
++	if _, err := os.Stat(path); err == nil {
++		return path, nil
++	}
++
++	resolver, err := getRunfilesResolver()
++	if err != nil {
++		return "", err
++	}
++
++	// Search in runfiles.
++	searchPath := []string{path}
++	if workspace, err := TestWorkspace(); err == nil {
++		searchPath = append(searchPath, filepath.Join(workspace, path))
++	}
++
++	for _, path := range searchPath {
++		filename, ok := resolver.Resolve(path)
++		if !ok {
++			continue
++		}
++
++		if _, err := os.Stat(filename); err == nil {
++			return filename, nil
++		}
++	}
++
++	return "", fmt.Errorf("unable to find file %q", path)
++}
++
++// RunfilesPath return the path to the run files tree for this test.
++// It returns an error if TEST_SRCDIR does not exist.
++func RunfilesPath() (string, error) {
++	if src, ok := os.LookupEnv(TEST_SRCDIR); ok {
++		return src, nil
++	}
++	return "", fmt.Errorf("environment variable %q is not defined, are you running with bazel test", TEST_SRCDIR)
++}
++
+ // NewTmpDir creates a new temporary directory in TestTmpDir().
+ func NewTmpDir(prefix string) (string, error) {
+ 	return ioutil.TempDir(TestTmpDir(), prefix)
+@@ -37,3 +99,90 @@ func TestTmpDir() string {
+ 	}
+ 	return os.TempDir()
+ }
++
++// TestWorkspace returns the name of the Bazel workspace for this test.
++// If TEST_WORKSPACE is not defined, it returns an error.
++func TestWorkspace() (string, error) {
++	if ws, ok := os.LookupEnv(TEST_WORKSPACE); ok {
++		return ws, nil
++	}
++	if defaultTestWorkspace != "" {
++		return defaultTestWorkspace, nil
++	}
++	return "", fmt.Errorf("Unable to find environment variable TEST_WORKSPACE")
++}
++
++// SetDefaultTestWorkspace allows you to set a fake value for the
++// environment variable TEST_WORKSPACE if it is not defined. This is useful
++// when running tests on the command line and not through Bazel.
++func SetDefaultTestWorkspace(w string) {
++	defaultTestWorkspace = w
++}
++
++// getCandidates returns the list of all possible "prefix/suffix" paths where there might be an
++// optional component in-between the two pieces.
++//
++// This function exists to cope with issues #1239 because we cannot tell where the built Go
++// binaries are located upfront.
++func getCandidates(prefix string, suffix string) []string {
++	candidates := []string{filepath.Join(prefix, suffix)}
++	if entries, err := ioutil.ReadDir(prefix); err == nil {
++		for _, entry := range entries {
++			candidate := filepath.Join(prefix, entry.Name(), suffix)
++			candidates = append(candidates, candidate)
++		}
++	}
++	return candidates
++}
++
++// FindBinary locates the given executable within bazel-bin or the current directory.
++//
++// "pkg" indicates the relative path to the build package that contains the binary target, and
++// "binary" indicates the basename of the binary searched for.
++func FindBinary(pkg string, binary string) (string, bool) {
++	candidates := getCandidates(filepath.Join("bazel-bin", pkg), binary)
++	candidates = append(candidates, getCandidates(pkg, binary)...)
++
++	for _, candidate := range candidates {
++		// Following symlinks here is intentional because Bazel generates symlinks in
++		// general and we don't care about that.
++		if fileInfo, err := os.Stat(candidate); err == nil {
++			if fileInfo.Mode()&os.ModeType == 0 && fileInfo.Mode()&0100 != 0 {
++				return candidate, true
++			}
++		}
++	}
++	return "", false
++}
++
++// findRunfiles locates the directory under which a built binary can find its data dependencies
++// using relative paths.
++func findRunfiles(workspace string, pkg string, binary string, cookie string) (string, bool) {
++	candidates := getCandidates(filepath.Join("bazel-bin", pkg), filepath.Join(binary+".runfiles", workspace))
++	candidates = append(candidates, ".")
++
++	for _, candidate := range candidates {
++		if _, err := os.Stat(filepath.Join(candidate, cookie)); err == nil {
++			return candidate, true
++		}
++	}
++	return "", false
++}
++
++// EnterRunfiles locates the directory under which a built binary can find its data dependencies
++// using relative paths, and enters that directory.
++//
++// "workspace" indicates the name of the current project, "pkg" indicates the relative path to the
++// build package that contains the binary target, "binary" indicates the basename of the binary
++// searched for, and "cookie" indicates an arbitrary data file that we expect to find within the
++// runfiles tree.
++func EnterRunfiles(workspace string, pkg string, binary string, cookie string) error {
++	runfiles, ok := findRunfiles(workspace, pkg, binary, cookie)
++	if !ok {
++		return fmt.Errorf("cannot find runfiles tree")
++	}
++	if err := os.Chdir(runfiles); err != nil {
++		return fmt.Errorf("cannot enter runfiles tree: %v", err)
++	}
++	return nil
++}
+diff --git a/go/tools/bazel/bazel_test.go b/go/tools/bazel/bazel_test.go
+index 66aa5876..41c9eed2 100644
+--- a/go/tools/bazel/bazel_test.go
++++ b/go/tools/bazel/bazel_test.go
+@@ -126,6 +126,137 @@ func TestTestWorkspace(t *testing.T) {
+ 	}
+ }
+ 
++func TestTestWorkspaceWithoutDefaultSet(t *testing.T) {
++	if oldVal, ok := os.LookupEnv(TEST_WORKSPACE); ok {
++		defer os.Setenv(TEST_WORKSPACE, oldVal)
++	} else {
++		t.Errorf("Terrible things are happening. You can't read env variables")
++	}
++	os.Unsetenv(TEST_WORKSPACE)
++
++	workspace, err := TestWorkspace()
++
++	if workspace != "" {
++		t.Errorf("Workspace should be left empty but was: %s", workspace)
++	}
++
++	if err == nil {
++		t.Errorf("Expected error but instead passed")
++	}
++}
++
++func TestTestWorkspaceWithDefaultSet(t *testing.T) {
++	if oldVal, ok := os.LookupEnv(TEST_WORKSPACE); ok {
++		defer os.Setenv(TEST_WORKSPACE, oldVal)
++	} else {
++		t.Errorf("Terrible things are happening. You can't read env variables")
++	}
++	os.Unsetenv(TEST_WORKSPACE)
++
++	SetDefaultTestWorkspace("default_value")
++	workspace, err := TestWorkspace()
++
++	if workspace == "" {
++		t.Errorf("Workspace is left empty")
++	}
++
++	if err != nil {
++		t.Errorf("Unable to get workspace with error %s", err)
++	}
++}
++
++func TestFindBinary(t *testing.T) {
++	testData := []struct {
++		name string
++
++		pathsToCreate []string
++		wantBinary    string
++		wantOk        bool
++	}{
++		{
++			"NoFiles",
++			[]string{},
++			"",
++			false,
++		},
++		{
++			"CurrentDirectoryNoConfigurationInPath",
++			[]string{
++				"some/package/",
++				"some/package/bin*",
++			},
++			"some/package/bin",
++			true,
++		},
++		{
++			"CurrentDirectoryConfigurationInPath",
++			[]string{
++				"some/package/amd64/",
++				"some/package/arm64/",
++				"some/package/arm64/bin*",
++				"some/package/powerpc/",
++			},
++			"some/package/arm64/bin",
++			true,
++		},
++		{
++			"BazelBinNoConfigurationInPath",
++			[]string{
++				"bazel-bin/some/package/",
++				"bazel-bin/some/package/bin*",
++				"bin", // bazel-bin should be preferred.
++			},
++			"bazel-bin/some/package/bin",
++			true,
++		},
++		{
++			"BazelBinConfigurationInPath",
++			[]string{
++				"bazel-bin/some/package/amd64/",
++				"bazel-bin/some/package/arm64/",
++				"bazel-bin/some/package/arm64/bin*",
++				"bazel-bin/some/package/powerpc/",
++				"bin", // bazel-bin should be preferred.
++				"some/package/amd64/",
++				"some/package/amd64/bin", // bazel-bin should be preferred.
++			},
++			"bazel-bin/some/package/arm64/bin",
++			true,
++		},
++		{
++			"IgnoreNonExecutable",
++			[]string{
++				"bazel-bin/some/package/amd64/",
++				"bazel-bin/some/package/amd64/bin",
++				"bazel-bin/some/package/arm64/",
++				"bazel-bin/some/package/arm64/bin*",
++				"bazel-bin/some/package/powerpc/",
++				"bazel-bin/some/package/powerpc/bin",
++			},
++			"bazel-bin/some/package/arm64/bin",
++			true,
++		},
++	}
++	for _, d := range testData {
++		t.Run(d.name, func(t *testing.T) {
++			cleanup, err := makeAndEnterTempdir()
++			if err != nil {
++				t.Fatal(err)
++			}
++			defer cleanup()
++
++			if err := createPaths(d.pathsToCreate); err != nil {
++				t.Fatal(err)
++			}
++
++			binary, ok := FindBinary("some/package", "bin")
++			if binary != d.wantBinary || ok != d.wantOk {
++				t.Errorf("Got %s, %v; want %s, %v", binary, ok, d.wantBinary, d.wantOk)
++			}
++		})
++	}
++}
++
+ func TestFindRunfiles(t *testing.T) {
+ 	testData := []struct {
+ 		name string
+diff --git a/go/tools/bazel/runfiledir.go b/go/tools/bazel/runfiledir.go
+new file mode 100644
+index 00000000..255d1452
+--- /dev/null
++++ b/go/tools/bazel/runfiledir.go
+@@ -0,0 +1,32 @@
++// Copyright 2018 The Bazel Authors.
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++//      http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++
++package bazel
++
++import (
++	"path/filepath"
++)
++
++type directoryResolver string
++
++// newDirectoryRunfilesResolver creates a new runfiles resolver that uses a runfiles directory to derive
++// filenames.
++func newDirectoryRunfilesResolver(directory string) (runfilesResolver, error) {
++	return directoryResolver(directory), nil
++}
++
++// Resolve implements the Resolver interface.
++func (r directoryResolver) Resolve(n string) (string, bool) {
++	return filepath.Join(string(r), n), true
++}
+diff --git a/go/tools/bazel/runfilemanifest.go b/go/tools/bazel/runfilemanifest.go
+new file mode 100644
+index 00000000..8392a4b0
+--- /dev/null
++++ b/go/tools/bazel/runfilemanifest.go
+@@ -0,0 +1,53 @@
++// Copyright 2018 The Bazel Authors.
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++//      http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++
++package bazel
++
++import (
++	"bufio"
++	"errors"
++	"io"
++	"path/filepath"
++	"strings"
++)
++
++var errManifestInvalid = errors.New("runfiles manifest syntax error")
++
++type manifestResolver map[string]string
++
++// newManifestRunfilesResolver creates a new runfiles resolver that uses a manifest file to resolve
++// filenames.
++func newManifestRunfilesResolver(manifest io.Reader) (runfilesResolver, error) {
++	resolver := manifestResolver{}
++	scanner := bufio.NewScanner(manifest)
++
++	for scanner.Scan() {
++		a := strings.SplitN(scanner.Text(), " ", 2)
++		if len(a) != 2 {
++			return nil, errManifestInvalid
++		}
++		resolver[filepath.Clean(a[0])] = a[1]
++	}
++
++	return resolver, nil
++}
++
++// Resolve implements the Resolver interface.
++func (r manifestResolver) Resolve(n string) (string, bool) {
++	if fn, ok := r[filepath.Clean(n)]; ok {
++		return fn, true
++	}
++
++	return "", false
++}
+diff --git a/go/tools/bazel/runfiles.go b/go/tools/bazel/runfiles.go
+index ed053e90..16ca3e16 100644
+--- a/go/tools/bazel/runfiles.go
++++ b/go/tools/bazel/runfiles.go
+@@ -15,17 +15,8 @@
+ package bazel
+ 
+ import (
+-	"bytes"
+ 	"errors"
+-	"fmt"
+-	"io/ioutil"
+ 	"os"
+-	"path"
+-	"path/filepath"
+-	"runtime"
+-	"sort"
+-	"strings"
+-	"sync"
+ )
+ 
+ const (
+@@ -33,393 +24,31 @@ const (
+ 	RUNFILES_DIR           = "RUNFILES_DIR"
+ )
+ 
+-// Runfile returns an absolute path to the file named by "path", which
+-// should be a relative path from the workspace root to the file within
+-// the bazel workspace.
+-//
+-// Runfile may be called from tests invoked with 'bazel test' and
+-// binaries invoked with 'bazel run'. On Windows,
+-// only tests invoked with 'bazel test' are supported.
+-func Runfile(path string) (string, error) {
+-	// Search in working directory
+-	if _, err := os.Stat(path); err == nil {
+-		return filepath.Abs(path)
+-	}
+-
+-	if err := ensureRunfiles(); err != nil {
+-		return "", err
+-	}
+-
+-	// Search manifest if we have one.
+-	if entry, ok := runfiles.index[path]; ok {
+-		return entry.Path, nil
+-	}
+-
+-	// Search the main workspace.
+-	if runfiles.workspace != "" {
+-		mainPath := filepath.Join(runfiles.dir, runfiles.workspace, path)
+-		if _, err := os.Stat(mainPath); err == nil {
+-			return mainPath, nil
+-		}
+-	}
+-
+-	// Search other workspaces.
+-	for _, w := range runfiles.workspaces {
+-		workPath := filepath.Join(runfiles.dir, w, path)
+-		if _, err := os.Stat(workPath); err == nil {
+-			return workPath, nil
+-		}
+-	}
+-
+-	return "", fmt.Errorf("Runfile %s: could not locate file", path)
+-}
+-
+-// FindBinary returns an absolute path to the binary built from a go_binary
+-// rule in the given package with the given name. FindBinary is similar to
+-// Runfile, but it accounts for varying configurations and file extensions,
+-// which may cause the binary to have different paths on different platforms.
+-//
+-// FindBinary may be called from tests invoked with 'bazel test' and
+-// binaries invoked with 'bazel run'. On Windows,
+-// only tests invoked with 'bazel test' are supported.
+-func FindBinary(pkg, name string) (string, bool) {
+-	if err := ensureRunfiles(); err != nil {
+-		return "", false
+-	}
+-
+-	// If we've gathered a list of runfiles, either by calling ListRunfiles or
+-	// parsing the manifest on Windows, just use that instead of searching
+-	// directories. Return the first match. The manifest on Windows may contain
+-	// multiple entries for the same file.
+-	if runfiles.list != nil {
+-		if runtime.GOOS == "windows" {
+-			name += ".exe"
+-		}
+-		for _, entry := range runfiles.list {
+-			if path.Base(entry.ShortPath) != name {
+-				continue
+-			}
+-			pkgDir := path.Dir(path.Dir(entry.ShortPath))
+-			if pkgDir == "." {
+-				pkgDir = ""
+-			}
+-			if pkgDir != pkg {
+-				continue
+-			}
+-			return entry.Path, true
+-		}
+-		return "", false
+-	}
+-
+-	dir, err := Runfile(pkg)
+-	if err != nil {
+-		return "", false
+-	}
+-	var found string
+-	stopErr := errors.New("stop")
+-	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+-		if err != nil {
+-			return err
+-		}
+-		base := filepath.Base(path)
+-		stem := strings.TrimSuffix(base, ".exe")
+-		if stem != name {
+-			return nil
+-		}
+-		if runtime.GOOS != "windows" {
+-			if st, err := os.Stat(path); err != nil {
+-				return err
+-			} else if st.Mode()&0111 == 0 {
+-				return nil
+-			}
+-		}
+-		if stem == name {
+-			found = path
+-			return stopErr
+-		}
+-		return nil
+-	})
+-	if err == stopErr {
+-		return found, true
+-	} else {
+-		return "", false
+-	}
+-}
+-
+-// A RunfileEntry describes a runfile.
+-type RunfileEntry struct {
+-	// Workspace is the bazel workspace the file came from. For example,
+-	// this would be "io_bazel_rules_go" for a file in rules_go.
+-	Workspace string
+-
+-	// ShortPath is a relative, slash-separated path from the workspace root
+-	// to the file. For non-binary files, this may be passed to Runfile
+-	// to locate a file.
+-	ShortPath string
+-
+-	// Path is an absolute path to the file.
+-	Path string
+-}
+-
+-// ListRunfiles returns a list of available runfiles.
+-func ListRunfiles() ([]RunfileEntry, error) {
+-	if err := ensureRunfiles(); err != nil {
+-		return nil, err
+-	}
+-
+-	if runfiles.list == nil && runfiles.dir != "" {
+-		runfiles.listOnce.Do(func() {
+-			var list []RunfileEntry
+-			haveWorkspaces := strings.HasSuffix(runfiles.dir, ".runfiles") && runfiles.workspace != ""
+-
+-			err := filepath.Walk(runfiles.dir, func(path string, info os.FileInfo, err error) error {
+-				if err != nil {
+-					return err
+-				}
+-				rel, _ := filepath.Rel(runfiles.dir, path)
+-				rel = filepath.ToSlash(rel)
+-				if rel == "." {
+-					return nil
+-				}
+-
+-				var workspace, shortPath string
+-				if haveWorkspaces {
+-					if i := strings.IndexByte(rel, '/'); i < 0 {
+-						return nil
+-					} else {
+-						workspace, shortPath = rel[:i], rel[i+1:]
+-					}
+-				} else {
+-					workspace, shortPath = "", rel
+-				}
+-
+-				list = append(list, RunfileEntry{Workspace: workspace, ShortPath: shortPath, Path: path})
+-				return nil
+-			})
+-			if err != nil {
+-				runfiles.err = err
+-				return
+-			}
+-			runfiles.list = list
+-		})
+-	}
+-	return runfiles.list, runfiles.err
+-}
+-
+-// TestWorkspace returns the name of the Bazel workspace for this test.
+-// TestWorkspace returns an error if the TEST_WORKSPACE environment variable
+-// was not set or SetDefaultTestWorkspace was not called.
+-func TestWorkspace() (string, error) {
+-	if err := ensureRunfiles(); err != nil {
+-		return "", err
+-	}
+-	if runfiles.workspace != "" {
+-		return runfiles.workspace, nil
+-	}
+-	return "", errors.New("TEST_WORKSPACE not set and SetDefaultTestWorkspace not called")
+-}
++var errNoRunfilesEnv = errors.New("runfiles environment missing")
+ 
+-// SetDefaultTestWorkspace allows you to set a fake value for the
+-// environment variable TEST_WORKSPACE if it is not defined. This is useful
+-// when running tests on the command line and not through Bazel.
+-func SetDefaultTestWorkspace(w string) {
+-	ensureRunfiles()
+-	runfiles.workspace = w
++// runfilesResolver is an interface for a resolver that can take a runfiles path and resolve it to a path on
++// disk.
++type runfilesResolver interface {
++	Resolve(string) (string, bool)
+ }
+ 
+-// RunfilesPath return the path to the runfiles tree.
+-// It will return an error if there is no runfiles tree, for example because
+-// the executable is run on Windows or was not invoked with 'bazel test'
+-// or 'bazel run'.
+-func RunfilesPath() (string, error) {
+-	if err := ensureRunfiles(); err != nil {
+-		return "", err
+-	}
+-	if runfiles.dir == "" {
+-		if runtime.GOOS == "windows" {
+-			return "", errors.New("RunfilesPath: no runfiles directory on windows")
+-		} else {
+-			return "", errors.New("could not locate runfiles directory")
+-		}
+-	}
+-	if runfiles.workspace == "" {
+-		return "", errors.New("could not locate runfiles workspace")
+-	}
+-	return filepath.Join(runfiles.dir, runfiles.workspace), nil
+-}
+-
+-// EnterRunfiles locates the directory under which a built binary can find its data dependencies
+-// using relative paths, and enters that directory.
+-//
+-// "workspace" indicates the name of the current project, "pkg" indicates the relative path to the
+-// build package that contains the binary target, "binary" indicates the basename of the binary
+-// searched for, and "cookie" indicates an arbitrary data file that we expect to find within the
+-// runfiles tree.
+-//
+-// DEPRECATED: use RunfilesPath instead.
+-func EnterRunfiles(workspace string, pkg string, binary string, cookie string) error {
+-	runfiles, ok := findRunfiles(workspace, pkg, binary, cookie)
+-	if !ok {
+-		return fmt.Errorf("cannot find runfiles tree")
+-	}
+-	if err := os.Chdir(runfiles); err != nil {
+-		return fmt.Errorf("cannot enter runfiles tree: %v", err)
+-	}
+-	return nil
+-}
+-
+-var runfiles = struct {
+-	once, listOnce sync.Once
+-
+-	// list is a list of known runfiles, either loaded from the manifest
+-	// or discovered by walking the runfile directory.
+-	list []RunfileEntry
+-
+-	// index maps runfile short paths to absolute paths.
+-	index map[string]RunfileEntry
+-
+-	// dir is a path to the runfile directory. Typically this is a directory
+-	// named <target>.runfiles, with a subdirectory for each workspace.
+-	dir string
+-
+-	// workspace is workspace where the binary or test was built.
+-	workspace string
+-
+-	// workspaces is a list of other workspace names.
+-	workspaces []string
+-
+-	// err is set when there is an error loading runfiles, for example,
+-	// parsing the manifest.
+-	err error
+-}{}
+-
+-func ensureRunfiles() error {
+-	runfiles.once.Do(initRunfiles)
+-	return runfiles.err
+-}
+-
+-func initRunfiles() {
+-	manifest := os.Getenv("RUNFILES_MANIFEST_FILE")
++// newRunfilesResolver creates a new runfiles resolver. The type of resolver and its parameters are derived
++// from the environment.
++func newRunfilesResolver() (runfilesResolver, error) {
++	manifest := os.Getenv(RUNFILES_MANIFEST_FILE)
+ 	if manifest != "" {
+-		// On Windows, Bazel doesn't create a symlink tree of runfiles because
+-		// Windows doesn't support symbolic links by default. Instead, runfile
+-		// locations are written to a manifest file.
+-		runfiles.index = make(map[string]RunfileEntry)
+-		data, err := ioutil.ReadFile(manifest)
++		f, err := os.Open(manifest)
+ 		if err != nil {
+-			runfiles.err = err
+-			return
++			return nil, err
+ 		}
+-		lineno := 0
+-		for len(data) > 0 {
+-			i := bytes.IndexByte(data, '\n')
+-			var line []byte
+-			if i < 0 {
+-				line = data
+-				data = nil
+-			} else {
+-				line = data[:i]
+-				data = data[i+1:]
+-			}
+-			lineno++
+-			line = bytes.TrimSpace(line)
+-			if len(line) == 0 {
+-				continue
+-			}
+-			e := bytes.SplitN(line, []byte(" "), 2)
+-			if len(e) < 2 {
+-				runfiles.err = fmt.Errorf("error parsing runfiles manifest: %s:%d: no space", manifest, lineno)
+-				return
+-			}
+-
+-			entry := RunfileEntry{ShortPath: string(e[0]), Path: string(e[1])}
+-			if i := strings.IndexByte(entry.ShortPath, '/'); i >= 0 {
+-				entry.Workspace = entry.ShortPath[:i]
+-				entry.ShortPath = entry.ShortPath[i+1:]
+-			}
+-			if strings.HasPrefix(entry.ShortPath, "external/") {
+-				entry.ShortPath = entry.ShortPath[len("external/"):]
+-				if i := strings.IndexByte(entry.ShortPath, '/'); i >= 0 {
+-					entry.Workspace = entry.ShortPath[:i]
+-					entry.ShortPath = entry.ShortPath[i+1:]
+-				}
+-			}
+-
+-			runfiles.list = append(runfiles.list, entry)
+-			runfiles.index[entry.ShortPath] = entry
+-		}
+-	}
+-
+-	runfiles.workspace = os.Getenv("TEST_WORKSPACE")
+-
+-	if dir := os.Getenv("RUNFILES_DIR"); dir != "" {
+-		runfiles.dir = dir
+-	} else if dir = os.Getenv("TEST_SRCDIR"); dir != "" {
+-		runfiles.dir = dir
+-	} else if runtime.GOOS != "windows" {
+-		dir, err := os.Getwd()
+-		if err != nil {
+-			runfiles.err = fmt.Errorf("error localting runfiles dir: %v", err)
+-			return
+-		}
+-
+-		parent := filepath.Dir(dir)
+-		if strings.HasSuffix(parent, ".runfiles") {
+-			runfiles.dir = parent
+-			if runfiles.workspace == "" {
+-				runfiles.workspace = filepath.Base(dir)
+-			}
+-		} else {
+-			runfiles.err = errors.New("could not locate runfiles directory")
+-			return
+-		}
+-	}
+-
+-	if runfiles.dir != "" {
+-		fis, err := ioutil.ReadDir(runfiles.dir)
+-		if err != nil {
+-			runfiles.err = fmt.Errorf("could not open runfiles directory: %v", err)
+-			return
+-		}
+-		for _, fi := range fis {
+-			if fi.IsDir() {
+-				runfiles.workspaces = append(runfiles.workspaces, fi.Name())
+-			}
+-		}
+-		sort.Strings(runfiles.workspaces)
++		defer f.Close()
++		return newManifestRunfilesResolver(f)
+ 	}
+-}
+ 
+-// getCandidates returns the list of all possible "prefix/suffix" paths where there might be an
+-// optional component in-between the two pieces.
+-//
+-// This function exists to cope with issues #1239 because we cannot tell where the built Go
+-// binaries are located upfront.
+-//
+-// DEPRECATED: only used by EnterRunfiles.
+-func getCandidates(prefix string, suffix string) []string {
+-	candidates := []string{filepath.Join(prefix, suffix)}
+-	if entries, err := ioutil.ReadDir(prefix); err == nil {
+-		for _, entry := range entries {
+-			candidate := filepath.Join(prefix, entry.Name(), suffix)
+-			candidates = append(candidates, candidate)
+-		}
++	directory := os.Getenv(RUNFILES_DIR)
++	if directory != "" {
++		return newDirectoryRunfilesResolver(directory)
+ 	}
+-	return candidates
+-}
+-
+-// findRunfiles locates the directory under which a built binary can find its data dependencies
+-// using relative paths.
+-//
+-// DEPRECATED: only used by EnterRunfiles.
+-func findRunfiles(workspace string, pkg string, binary string, cookie string) (string, bool) {
+-	candidates := getCandidates(filepath.Join("bazel-bin", pkg), filepath.Join(binary+".runfiles", workspace))
+-	candidates = append(candidates, ".")
+ 
+-	for _, candidate := range candidates {
+-		if _, err := os.Stat(filepath.Join(candidate, cookie)); err == nil {
+-			return candidate, true
+-		}
+-	}
+-	return "", false
++	return nil, errNoRunfilesEnv
+ }
+diff --git a/go/tools/bazel/runfiles_test.go b/go/tools/bazel/runfiles_test.go
+new file mode 100644
+index 00000000..b7bd44f0
+--- /dev/null
++++ b/go/tools/bazel/runfiles_test.go
+@@ -0,0 +1,125 @@
++// Copyright 2018 The Bazel Authors.
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++//      http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++
++package bazel
++
++import (
++	"io/ioutil"
++	"os"
++	"path/filepath"
++	"testing"
++)
++
++func setenvForTest(key, value string) (cleanup func()) {
++	if old, ok := os.LookupEnv(key); ok {
++		cleanup = func() { os.Setenv(key, old) }
++	} else {
++		cleanup = func() { os.Unsetenv(key) }
++	}
++	os.Setenv(key, value)
++	return cleanup
++}
++
++func setupResolverForTest() {
++	// Prevent initialization code from running.
++	runfileResolverOnce.Do(func() {})
++	runfileResolver, runfileResolverErr = newRunfilesResolver()
++}
++
++func TestManifestRunfiles(t *testing.T) {
++	dir, err := NewTmpDir("test")
++	if err != nil {
++		t.Fatal(err)
++	}
++	defer os.RemoveAll(dir)
++
++	testStr := "This is a test"
++	mappedFilename := filepath.Join(dir, "mapped_file.txt")
++	if err := ioutil.WriteFile(mappedFilename, []byte(testStr), 0600); err != nil {
++		t.Fatal(err)
++	}
++
++	manifestFilename := filepath.Join(dir, "MANIFEST")
++	if err := ioutil.WriteFile(manifestFilename, []byte("runfiles/test.txt "+mappedFilename), 0600); err != nil {
++		t.Fatal(err)
++	}
++
++	cleanupManifestEnv := setenvForTest(RUNFILES_MANIFEST_FILE, manifestFilename)
++	defer cleanupManifestEnv()
++	cleanupDirEnv := setenvForTest(RUNFILES_DIR, "")
++	defer cleanupDirEnv()
++
++	setupResolverForTest()
++	if runfileResolverErr != nil {
++		t.Fatal(runfileResolverErr)
++	}
++	if _, ok := runfileResolver.(manifestResolver); !ok {
++		t.Error("resolver should be manifest resolver")
++	}
++
++	filename, err := Runfile("runfiles/test.txt")
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	d, err := ioutil.ReadFile(filename)
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	if string(d) != testStr {
++		t.Errorf("expected %s, got %s", testStr, string(d))
++	}
++}
++
++func TestDirectoryRunfiles(t *testing.T) {
++	dir, err := NewTmpDir("test")
++	if err != nil {
++		t.Fatal(err)
++	}
++	defer os.RemoveAll(dir)
++
++	testStr := "This is a test"
++	mappedfn := filepath.Join(dir, "runfile.txt")
++	if err := ioutil.WriteFile(mappedfn, []byte(testStr), 0600); err != nil {
++		t.Fatal(err)
++	}
++
++	cleanupManifestEnv := setenvForTest(RUNFILES_MANIFEST_FILE, "")
++	defer cleanupManifestEnv()
++	cleanupDirEnv := setenvForTest(RUNFILES_DIR, dir)
++	defer cleanupDirEnv()
++
++	setupResolverForTest()
++	if runfileResolverErr != nil {
++		t.Fatal(runfileResolverErr)
++	}
++	if _, ok := runfileResolver.(directoryResolver); !ok {
++		t.Error("resolver should be directory resolver")
++	}
++
++	filename, err := Runfile("runfile.txt")
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	d, err := ioutil.ReadFile(filename)
++	if err != nil {
++		t.Fatal(err)
++	}
++
++	if string(d) != testStr {
++		t.Errorf("expected %s, got %s", testStr, string(d))
++	}
++}
+diff --git a/tests/core/runfiles/BUILD.bazel b/tests/core/runfiles/BUILD.bazel
+deleted file mode 100644
+index c7db6d3d..00000000
+--- a/tests/core/runfiles/BUILD.bazel
++++ /dev/null
+@@ -1,48 +0,0 @@
+-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
+-
+-package(default_visibility = ["//visibility:public"])
+-
+-test_suite(
+-    name = "runfiles_tests",
+-    tests = [
+-        ":local_test",
+-        "@runfiles_remote_test//:remote_test",
+-    ],
+-)
+-
+-go_test(
+-    name = "local_test",
+-    srcs = ["runfiles_test.go"],
+-    deps = [":check_runfiles"],
+-)
+-
+-go_binary(
+-    name = "local_cmd",
+-    srcs = ["runfiles_cmd.go"],
+-    deps = [":check_runfiles"],
+-)
+-
+-go_binary(
+-    name = "local_bin",
+-    srcs = ["empty_bin.go"],
+-)
+-
+-go_library(
+-    name = "check_runfiles",
+-    srcs = ["check_runfiles.go"],
+-    data = [
+-        "local_file.txt",
+-        ":local_bin",
+-        ":local_group",
+-        "@runfiles_remote_test//:remote_bin",
+-        "@runfiles_remote_test//:remote_file.txt",
+-        "@runfiles_remote_test//:remote_group",
+-    ],
+-    importpath = "github.com/bazelbuild/rules_go/tests/core/runfiles/check",
+-    deps = ["//go/tools/bazel:go_default_library"],
+-)
+-
+-filegroup(
+-    name = "local_group",
+-    srcs = ["local_group.txt"],
+-)
+diff --git a/tests/core/runfiles/README.rst b/tests/core/runfiles/README.rst
+deleted file mode 100644
+index ec357826..00000000
+--- a/tests/core/runfiles/README.rst
++++ /dev/null
+@@ -1,23 +0,0 @@
+-Runfiles functionality
+-=====================
+-
+-runfiles_tests
+---------------
+-
+-Checks that functions in ``//go/tools/bazel:go_default_library`` that
+-provide access to runfiles behave correctly. In particular, this checks:
+-
+-* ``Runfile`` works for regular files.
+-* ``FindBinary`` works for binaries.
+-* ``ListRunfiles`` lists all expected files.
+-* These functions work for runfiles in the local workspace and for files in
+-  external repositories (``@runfiles_remote_test`` is a ``local_repository``
+-  that points to a subdirectory here).
+-* These functions work in tests invoked with ``bazel test`` and
+-  binaries invoked with ``bazel run``.
+-* These functions work on Windows and other platforms. Bazel doesn't
+-  create a symlink tree for runfiles on Windows since symbolic links
+-  can't be created without administrative privilege by default.
+-
+-TODO: Verify binary behavior in CI. The ``local_bin`` and ``remote_bin``
+-targets verify behavior for binaries, but they are not tests.
+diff --git a/tests/core/runfiles/bin.go b/tests/core/runfiles/bin.go
+deleted file mode 100644
+index 0ced7a9e..00000000
+--- a/tests/core/runfiles/bin.go
++++ /dev/null
+@@ -1,17 +0,0 @@
+-// Copyright 2019 The Bazel Authors. All rights reserved.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-//    http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-package main
+-
+-func main() {}
+diff --git a/tests/core/runfiles/check_runfiles.go b/tests/core/runfiles/check_runfiles.go
+deleted file mode 100644
+index 8858a573..00000000
+--- a/tests/core/runfiles/check_runfiles.go
++++ /dev/null
+@@ -1,121 +0,0 @@
+-// Copyright 2019 The Bazel Authors. All rights reserved.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-//    http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-package check
+-
+-import (
+-	"fmt"
+-	"os"
+-	"path/filepath"
+-	"runtime"
+-	"sort"
+-	"strings"
+-
+-	"github.com/bazelbuild/rules_go/go/tools/bazel"
+-)
+-
+-type TestFile struct {
+-	Workspace, ShortPath, Path string
+-	Binary                     bool
+-}
+-
+-var DefaultTestFiles = []TestFile{
+-	{Workspace: "io_bazel_rules_go", Path: "tests/core/runfiles/local_file.txt"},
+-	{Workspace: "io_bazel_rules_go", Path: "tests/core/runfiles/local_group.txt"},
+-	{Workspace: "io_bazel_rules_go", Path: "tests/core/runfiles/local_bin", Binary: true},
+-	{Workspace: "runfiles_remote_test", Path: "remote_file.txt"},
+-	{Workspace: "runfiles_remote_test", Path: "remote_group.txt"},
+-	{Workspace: "runfiles_remote_test", Path: "remote_bin", Binary: true},
+-}
+-
+-func CheckRunfiles(files []TestFile) error {
+-	// Check that the runfiles directory matches the current workspace.
+-	// There is no runfiles directory on Windows.
+-	if runtime.GOOS != "windows" {
+-		dir, err := bazel.RunfilesPath()
+-		if err != nil {
+-			return err
+-		}
+-		root, base := filepath.Dir(dir), filepath.Base(dir)
+-		if !strings.HasSuffix(root, ".runfiles") {
+-			return fmt.Errorf("RunfilesPath: %q is not a .runfiles directory", dir)
+-		}
+-		workspace := os.Getenv("TEST_WORKSPACE")
+-		if workspace != "" && workspace != base {
+-			return fmt.Errorf("RunfilesPath: %q does not match test workspace %s", dir, workspace)
+-		}
+-		if srcDir := os.Getenv("TEST_SRCDIR"); srcDir != "" && filepath.Join(srcDir, workspace) != dir {
+-			return fmt.Errorf("RunfilesPath: %q does not match TEST_SRCDIR %q", dir, srcDir)
+-		}
+-	}
+-
+-	// Check that files can be found with Runfile or FindBinary.
+-	// Make sure the paths returned are absolute paths to actual files.
+-	seen := make(map[string]string)
+-	for _, f := range files {
+-		var got string
+-		var err error
+-		if !f.Binary {
+-			if got, err = bazel.Runfile(f.Path); err != nil {
+-				return err
+-			}
+-			if !filepath.IsAbs(got) {
+-				return fmt.Errorf("Runfile %s: got a relative path %q; want absolute", f.Path, got)
+-			}
+-			seen[f.Path] = got
+-		} else {
+-			var pkg, name string
+-			if i := strings.LastIndex(f.Path, "/"); i < 0 {
+-				name = f.Path
+-			} else {
+-				pkg = f.Path[:i]
+-				name = f.Path[i+1:]
+-			}
+-			var ok bool
+-			if got, ok = bazel.FindBinary(pkg, name); !ok {
+-				return fmt.Errorf("FindBinary %s %s: could not find binary", pkg, name)
+-			}
+-			if !filepath.IsAbs(got) {
+-				return fmt.Errorf("FindBinary %s %s: got a relative path %q; want absolute", pkg, name, got)
+-			}
+-		}
+-
+-		if _, err := os.Stat(got); err != nil {
+-			return fmt.Errorf("%s: could not stat: %v", f.Path, err)
+-		}
+-	}
+-
+-	// Check that the files can be listed.
+-	entries, err := bazel.ListRunfiles()
+-	if err != nil {
+-		return err
+-	}
+-	for _, e := range entries {
+-		if want, ok := seen[e.ShortPath]; ok && want != e.Path {
+-			return err
+-		}
+-		delete(seen, e.ShortPath)
+-	}
+-
+-	if len(seen) > 0 {
+-		unseen := make([]string, 0, len(seen))
+-		for short := range seen {
+-			unseen = append(unseen, short)
+-		}
+-		sort.Strings(unseen)
+-		return fmt.Errorf("ListRunfiles did not include files:\n\t%s", strings.Join(unseen, "\n\t"))
+-	}
+-
+-	return nil
+-}
+diff --git a/tests/core/runfiles/empty_bin.go b/tests/core/runfiles/empty_bin.go
+deleted file mode 100644
+index 38dd16da..00000000
+--- a/tests/core/runfiles/empty_bin.go
++++ /dev/null
+@@ -1,3 +0,0 @@
+-package main
+-
+-func main() {}
+diff --git a/tests/core/runfiles/local_file.txt b/tests/core/runfiles/local_file.txt
+deleted file mode 100644
+index e69de29b..00000000
+diff --git a/tests/core/runfiles/local_group.txt b/tests/core/runfiles/local_group.txt
+deleted file mode 100644
+index e69de29b..00000000
+diff --git a/tests/core/runfiles/runfiles_cmd.go b/tests/core/runfiles/runfiles_cmd.go
+deleted file mode 100644
+index 0ab124b5..00000000
+--- a/tests/core/runfiles/runfiles_cmd.go
++++ /dev/null
+@@ -1,28 +0,0 @@
+-// Copyright 2019 The Bazel Authors. All rights reserved.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-//    http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-package main
+-
+-import (
+-	"fmt"
+-	"os"
+-
+-	"github.com/bazelbuild/rules_go/tests/core/runfiles/check"
+-)
+-
+-func main() {
+-	if err := check.CheckRunfiles(check.DefaultTestFiles); err != nil {
+-		fmt.Fprintln(os.Stderr, err.Error())
+-	}
+-}
+diff --git a/tests/core/runfiles/runfiles_remote_test/BUILD.bazel b/tests/core/runfiles/runfiles_remote_test/BUILD.bazel
+deleted file mode 100644
+index 112dcd35..00000000
+--- a/tests/core/runfiles/runfiles_remote_test/BUILD.bazel
++++ /dev/null
+@@ -1,27 +0,0 @@
+-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_test")
+-
+-package(default_visibility = ["//visibility:public"])
+-
+-go_test(
+-    name = "remote_test",
+-    srcs = ["@io_bazel_rules_go//tests/core/runfiles:runfiles_test.go"],
+-    deps = ["@io_bazel_rules_go//tests/core/runfiles:check_runfiles"],
+-)
+-
+-go_binary(
+-    name = "remote_cmd",
+-    srcs = ["@io_bazel_rules_go//tests/core/runfiles:runfiles_cmd.go"],
+-    deps = ["@io_bazel_rules_go//tests/core/runfiles:check_runfiles"],
+-)
+-
+-go_binary(
+-    name = "remote_bin",
+-    srcs = ["@io_bazel_rules_go//tests/core/runfiles:empty_bin.go"],
+-)
+-
+-filegroup(
+-    name = "remote_group",
+-    srcs = ["remote_group.txt"],
+-)
+-
+-exports_files(["remote_file.txt"])
+diff --git a/tests/core/runfiles/runfiles_remote_test/WORKSPACE b/tests/core/runfiles/runfiles_remote_test/WORKSPACE
+deleted file mode 100644
+index c9af3f85..00000000
+--- a/tests/core/runfiles/runfiles_remote_test/WORKSPACE
++++ /dev/null
+@@ -1 +0,0 @@
+-workspace(name = "runfiles_remote_test")
+diff --git a/tests/core/runfiles/runfiles_remote_test/remote_file.txt b/tests/core/runfiles/runfiles_remote_test/remote_file.txt
+deleted file mode 100644
+index e69de29b..00000000
+diff --git a/tests/core/runfiles/runfiles_remote_test/remote_group.txt b/tests/core/runfiles/runfiles_remote_test/remote_group.txt
+deleted file mode 100644
+index e69de29b..00000000
+diff --git a/tests/core/runfiles/runfiles_test.go b/tests/core/runfiles/runfiles_test.go
+deleted file mode 100644
+index 62aab3af..00000000
+--- a/tests/core/runfiles/runfiles_test.go
++++ /dev/null
+@@ -1,27 +0,0 @@
+-// Copyright 2019 The Bazel Authors. All rights reserved.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-//    http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-package main
+-
+-import (
+-	"testing"
+-
+-	"github.com/bazelbuild/rules_go/tests/core/runfiles/check"
+-)
+-
+-func Test(t *testing.T) {
+-	if err := check.CheckRunfiles(check.DefaultTestFiles); err != nil {
+-		t.Fatal(err)
+-	}
+-}