map bazel's --test_runner_fail_fast to go's -failfast (#3058)

The following are now equivalent
```sh
> bazel test --test_runner_fail_fast //path/to/my/go/test
> bazel test --test_arg=-failfast //path/to/my/go/test
```
diff --git a/docs/go/core/rules.bzl b/docs/go/core/rules.bzl
index 359e97e..6a8423f 100644
--- a/docs/go/core/rules.bzl
+++ b/docs/go/core/rules.bzl
@@ -24,6 +24,7 @@
   [test_arg]: https://docs.bazel.build/versions/master/user-manual.html#flag--test_arg
   [test_filter]: https://docs.bazel.build/versions/master/user-manual.html#flag--test_filter
   [test_env]: https://docs.bazel.build/versions/master/user-manual.html#flag--test_env
+  [test_runner_fail_fast]: https://docs.bazel.build/versions/master/command-line-reference.html#flag--test_runner_fail_fast
   [write a CROSSTOOL file]: https://github.com/bazelbuild/bazel/wiki/Yet-Another-CROSSTOOL-Writing-Tutorial
   [bazel]: https://pkg.go.dev/github.com/bazelbuild/rules_go/go/tools/bazel?tab=doc
   [go_library]: #go_library
@@ -70,6 +71,7 @@
 - [test_arg]
 - [test_filter]
 - [test_env]
+- [test_runner_fail_fast]
 - [write a CROSSTOOL file]
 - [bazel]
 
diff --git a/docs/go/core/rules.md b/docs/go/core/rules.md
index 2baf52b..5adf76f 100644
--- a/docs/go/core/rules.md
+++ b/docs/go/core/rules.md
@@ -26,6 +26,7 @@
   [test_arg]: https://docs.bazel.build/versions/master/user-manual.html#flag--test_arg
   [test_filter]: https://docs.bazel.build/versions/master/user-manual.html#flag--test_filter
   [test_env]: https://docs.bazel.build/versions/master/user-manual.html#flag--test_env
+  [test_runner_fail_fast]: https://docs.bazel.build/versions/master/command-line-reference.html#flag--test_runner_fail_fast
   [write a CROSSTOOL file]: https://github.com/bazelbuild/bazel/wiki/Yet-Another-CROSSTOOL-Writing-Tutorial
   [bazel]: https://pkg.go.dev/github.com/bazelbuild/rules_go/go/tools/bazel?tab=doc
   [go_library]: #go_library
@@ -72,6 +73,7 @@
 - [test_arg]
 - [test_filter]
 - [test_env]
+- [test_runner_fail_fast]
 - [write a CROSSTOOL file]
 - [bazel]
 
@@ -306,7 +308,9 @@
     <test_filter_>` argument to Bazel. You can pass arguments to tests by passing
     `--test_arg=arg <test_arg_>` arguments to Bazel, and you can set environment
     variables in the test environment by passing
-    `--test_env=VAR=value <test_env_>`.<br><br>
+    `--test_env=VAR=value <test_env_>`. You can terminate test execution after the first
+    failure by passing the `--test_runner_fast_fast <test_runner_fail_fast_>` argument
+    to Bazel. This is equivalent to passing `--test_arg=-failfast <test_arg_>`.<br><br>
     To write structured testlog information to Bazel's `XML_OUTPUT_FILE`, tests
     ran with `bazel test` execute using a wrapper. This functionality can be
     disabled by setting `GO_TEST_WRAP=0` in the test environment. Additionally,
diff --git a/go/core.rst b/go/core.rst
index d9ec567..f694681 100644
--- a/go/core.rst
+++ b/go/core.rst
@@ -26,6 +26,7 @@
 .. _test_arg: https://docs.bazel.build/versions/master/user-manual.html#flag--test_arg
 .. _test_filter: https://docs.bazel.build/versions/master/user-manual.html#flag--test_filter
 .. _test_env: https://docs.bazel.build/versions/master/user-manual.html#flag--test_env
+.. _test_runner_fail_fast: https://docs.bazel.build/versions/master/command-line-reference.html#flag--test_runner_fail_fast
 .. _write a CROSSTOOL file: https://github.com/bazelbuild/bazel/wiki/Yet-Another-CROSSTOOL-Writing-Tutorial
 .. _bazel: https://pkg.go.dev/github.com/bazelbuild/rules_go/go/tools/bazel?tab=doc
 .. _introduction: /docs/go/core/rules.md#introduction
diff --git a/go/private/rules/test.bzl b/go/private/rules/test.bzl
index af42900..bc026a3 100644
--- a/go/private/rules/test.bzl
+++ b/go/private/rules/test.bzl
@@ -421,7 +421,9 @@
     <test_filter_>` argument to Bazel. You can pass arguments to tests by passing
     `--test_arg=arg <test_arg_>` arguments to Bazel, and you can set environment
     variables in the test environment by passing
-    `--test_env=VAR=value <test_env_>`.<br><br>
+    `--test_env=VAR=value <test_env_>`. You can terminate test execution after the first
+    failure by passing the `--test_runner_fast_fast <test_runner_fail_fast_>` argument
+    to Bazel. This is equivalent to passing `--test_arg=-failfast <test_arg_>`.<br><br>
     To write structured testlog information to Bazel's `XML_OUTPUT_FILE`, tests
     ran with `bazel test` execute using a wrapper. This functionality can be
     disabled by setting `GO_TEST_WRAP=0` in the test environment. Additionally,
diff --git a/go/tools/builders/generate_test_main.go b/go/tools/builders/generate_test_main.go
index bbb4c00..5ef740a 100644
--- a/go/tools/builders/generate_test_main.go
+++ b/go/tools/builders/generate_test_main.go
@@ -181,6 +181,10 @@
 		flag.Lookup("test.run").Value.Set(filter)
 	}
 
+	if failfast := os.Getenv("TESTBRIDGE_TEST_RUNNER_FAIL_FAST"); failfast != "" {
+		flag.Lookup("test.failfast").Value.Set("true")
+	}
+
 	{{if ne .CoverMode ""}}
 	if len(coverdata.Counters) > 0 {
 		testing.RegisterCover(testing.Cover{
diff --git a/tests/core/go_test/BUILD.bazel b/tests/core/go_test/BUILD.bazel
index 87a388f..32d8c79 100644
--- a/tests/core/go_test/BUILD.bazel
+++ b/tests/core/go_test/BUILD.bazel
@@ -140,6 +140,11 @@
 )
 
 go_bazel_test(
+    name = "test_fail_fast_test",
+    srcs = ["test_fail_fast_test.go"],
+)
+
+go_bazel_test(
     name = "test_filter_test",
     srcs = ["test_filter_test.go"],
 )
diff --git a/tests/core/go_test/README.rst b/tests/core/go_test/README.rst
index 714fa64..176cf19 100644
--- a/tests/core/go_test/README.rst
+++ b/tests/core/go_test/README.rst
@@ -75,6 +75,14 @@
 ``embed``, are visible to tests at run-time. Source files should not be
 visible at run-time.
 
+test_fail_fast_test
+----------------
+
+Checks that ``--test_runner_fail_fast`` actually enables stopping test execution after
+the first failure.
+
+Verifies #3055.
+
 test_filter_test
 ----------------
 
diff --git a/tests/core/go_test/test_fail_fast_test.go b/tests/core/go_test/test_fail_fast_test.go
new file mode 100644
index 0000000..b949b48
--- /dev/null
+++ b/tests/core/go_test/test_fail_fast_test.go
@@ -0,0 +1,75 @@
+// Copyright 2022 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 test_fail_fast_test
+
+import (
+	"bytes"
+	"io/ioutil"
+	"path/filepath"
+	"testing"
+
+	"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
+)
+
+func TestMain(m *testing.M) {
+	bazel_testing.TestMain(m, bazel_testing.Args{
+		Main: `
+-- BUILD.bazel --
+load("@io_bazel_rules_go//go:def.bzl", "go_test")
+
+go_test(
+    name = "fail_fast_test",
+    srcs = ["fail_fast_test.go"],
+)
+
+-- fail_fast_test.go --
+package test_fail_fast
+
+import "testing"
+
+func TestShouldFail(t *testing.T) {
+	t.Fail()
+}
+
+func TestShouldNotRun(t *testing.T) {
+	t.Fail()
+}
+`,
+	})
+}
+
+func Test(t *testing.T) {
+	if err := bazel_testing.RunBazel("test", "//:fail_fast_test", "--test_runner_fail_fast"); err == nil {
+		t.Fatal("got success; want failure")
+	} else if bErr, ok := err.(*bazel_testing.StderrExitError); !ok {
+		t.Fatalf("got %v; want StderrExitError", err)
+	} else if code := bErr.Err.ExitCode(); code != 3 {
+		t.Fatalf("got code %d; want code 3", code)
+	}
+
+	logPath := filepath.FromSlash("bazel-testlogs/fail_fast_test/test.log")
+	logData, err := ioutil.ReadFile(logPath)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !bytes.Contains(logData, []byte("TestShouldFail")) {
+		t.Fatalf("test log does not contain 'TestShouldFail': %q", logData)
+	}
+
+	if bytes.Contains(logData, []byte("TestShouldNotRun")) {
+		t.Fatalf("test log contains 'TestShouldNotRun' but should not: %q", logData)
+	}
+}