]> Cypherpunks.ru repositories - gostls13.git/commitdiff
testing: add Testing function
authorIan Lance Taylor <iant@golang.org>
Thu, 9 Mar 2023 00:16:59 +0000 (16:16 -0800)
committerGopher Robot <gobot@golang.org>
Mon, 13 Mar 2023 21:58:46 +0000 (21:58 +0000)
The Testing function reports whether the program is a test created
by "go test".

Fixes #52600

Change-Id: Ie0fff7c7dfdfdf997c18b4b6112632600b327cc8
Reviewed-on: https://go-review.googlesource.com/c/go/+/475496
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>

api/next/52600.txt [new file with mode: 0644]
src/cmd/go/internal/load/test.go
src/testing/testing.go
src/testing/testing_test.go

diff --git a/api/next/52600.txt b/api/next/52600.txt
new file mode 100644 (file)
index 0000000..a9a34bb
--- /dev/null
@@ -0,0 +1 @@
+pkg testing, func Testing() bool #52600
index 64e5b74cc240155bd21b57f049f87b5db54a6393..7a40cc6b4544ea7a5ab176f8c802fce9e25f31a9 100644 (file)
@@ -253,6 +253,10 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
                pxtest.collectDeps()
        }
 
+       // Arrange for testing.Testing to report true.
+       ldflags := append(p.Internal.Ldflags, "-X", "testing.testBinary=1")
+       gccgoflags := append(p.Internal.Gccgoflags, "-Wl,--defsym,testing.gccgoTestBinary=1")
+
        // Build main package.
        pmain = &Package{
                PackagePublic: PackagePublic{
@@ -269,8 +273,8 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
                        BuildInfo:      p.Internal.BuildInfo,
                        Asmflags:       p.Internal.Asmflags,
                        Gcflags:        p.Internal.Gcflags,
-                       Ldflags:        p.Internal.Ldflags,
-                       Gccgoflags:     p.Internal.Gccgoflags,
+                       Ldflags:        ldflags,
+                       Gccgoflags:     gccgoflags,
                        OrigImportPath: p.Internal.OrigImportPath,
                        PGOProfile:     p.Internal.PGOProfile,
                },
index 2d0fd89137aba023956a6ce2c4254ee48ef6f77e..c970d05256ff2cb0f0dce88b504a0d74b57e4ed6 100644 (file)
@@ -644,6 +644,22 @@ func Short() bool {
        return *short
 }
 
+// testBinary is set by cmd/go to "1" if this is a binary built by "go test".
+// The value is set to "1" by a -X option to cmd/link. We assume that
+// because this is possible, the compiler will not optimize testBinary
+// into a constant on the basis that it is an unexported package-scope
+// variable that is never changed. If the compiler ever starts implementing
+// such an optimization, we will need some technique to mark this variable
+// as "changed by a cmd/link -X option".
+var testBinary = "0"
+
+// Testing reports whether the current code is being run in a test.
+// This will report true in programs created by "go test",
+// false in programs created by "go build".
+func Testing() bool {
+       return testBinary == "1"
+}
+
 // CoverMode reports what the test coverage mode is set to. The
 // values are "set", "count", or "atomic". The return value will be
 // empty if test coverage is not enabled.
index 3616f04d5fcc425f83bedef008ff08a381b8b55e..5e9268779fdac9b54e34903f6362bfa516960bf9 100644 (file)
@@ -5,6 +5,8 @@
 package testing_test
 
 import (
+       "bytes"
+       "internal/testenv"
        "os"
        "path/filepath"
        "testing"
@@ -232,3 +234,62 @@ func TestSetenvWithParallelGrandParentBeforeSetenv(t *testing.T) {
                })
        })
 }
+
+// testingTrueInInit is part of TestTesting.
+var testingTrueInInit = false
+
+// testingTrueInPackageVarInit is part of TestTesting.
+var testingTrueInPackageVarInit = testing.Testing()
+
+// init is part of TestTesting.
+func init() {
+       if testing.Testing() {
+               testingTrueInInit = true
+       }
+}
+
+var testingProg = `
+package main
+
+import (
+       "fmt"
+       "testing"
+)
+
+func main() {
+       fmt.Println(testing.Testing())
+}
+`
+
+func TestTesting(t *testing.T) {
+       if !testing.Testing() {
+               t.Errorf("testing.Testing() == %t, want %t", testing.Testing(), true)
+       }
+       if !testingTrueInInit {
+               t.Errorf("testing.Testing() called by init function == %t, want %t", testingTrueInInit, true)
+       }
+       if !testingTrueInPackageVarInit {
+               t.Errorf("testing.Testing() variable initialized as %t, want %t", testingTrueInPackageVarInit, true)
+       }
+
+       if testing.Short() {
+               t.Skip("skipping building a binary in short mode")
+       }
+       testenv.MustHaveGoRun(t)
+
+       fn := filepath.Join(t.TempDir(), "x.go")
+       if err := os.WriteFile(fn, []byte(testingProg), 0644); err != nil {
+               t.Fatal(err)
+       }
+
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "run", fn)
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%v failed: %v\n%s", cmd, err, out)
+       }
+
+       s := string(bytes.TrimSpace(out))
+       if s != "false" {
+               t.Errorf("in non-test testing.Test() returned %q, want %q", s, "false")
+       }
+}