libgo: update to final Go1.14 release
authorIan Lance Taylor <iant@golang.org>
Wed, 26 Feb 2020 19:15:50 +0000 (11:15 -0800)
committerIan Lance Taylor <iant@golang.org>
Wed, 26 Feb 2020 20:19:13 +0000 (12:19 -0800)
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/221158

25 files changed:
gcc/go/gofrontend/MERGE
libgo/MERGE
libgo/VERSION
libgo/go/cmd/go/internal/modcmd/mod.go
libgo/go/cmd/go/internal/modload/import.go
libgo/go/cmd/go/internal/vet/vet.go
libgo/go/cmd/go/internal/web/api.go
libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt
libgo/go/cmd/go/testdata/script/mod_readonly.txt
libgo/go/cmd/go/testdata/script/vet_flags.txt
libgo/go/crypto/cipher/gcm.go
libgo/go/crypto/cipher/gcm_test.go
libgo/go/crypto/elliptic/elliptic.go
libgo/go/crypto/x509/pkcs8.go
libgo/go/go/build/build.go
libgo/go/go/doc/doc.go
libgo/go/hash/maphash/maphash.go
libgo/go/hash/maphash/maphash_test.go
libgo/go/math/big/int.go
libgo/go/runtime/malloc.go
libgo/go/runtime/mkpreempt.go
libgo/go/runtime/netpoll_stub.go
libgo/go/testing/benchmark.go
libgo/go/testing/sub_test.go
libgo/go/testing/testing.go

index 7dcb9ecb4fdebf7ad210d46e8a961ea807731beb..a62c8292e0a1827ca4b70fc2301a049e0a81d649 100644 (file)
@@ -1,4 +1,4 @@
-658fe4f48374167bf8688e8dbd5f85eee155749e
+5fc21bb0d91d916940c21e6d4a3e10ad3f45343d
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 2d01b8759bfc55148b3208ca0e2b4f9ffd1beed5..233492ada69ba877029691817b47cabb224ba24d 100644 (file)
@@ -1,4 +1,4 @@
-a068054af141c01df5a4519844f4b77273605f4e
+20a838ab94178c55bc4dc23ddc332fce8545a493
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
index 5304c505acda36a0e0aaaf96f35780e5f795c088..f000507a7fe7649efb56eaf39972338864860451 100644 (file)
@@ -1 +1 @@
-go1.14rc1
+go1.14
index 17505221587745bfc4cef0702f926403a96188b7..d72d0cacd68ddafdc2723c00ca3d7f04a7aa62bc 100644 (file)
@@ -7,7 +7,6 @@ package modcmd
 
 import (
        "cmd/go/internal/base"
-       "cmd/go/internal/cfg"
 )
 
 var CmdMod = &base.Command{
@@ -32,7 +31,3 @@ See 'go help modules' for an overview of module functionality.
                cmdWhy,
        },
 }
-
-func addModFlags(cmd *base.Command) {
-       cmd.Flag.StringVar(&cfg.ModFile, "modfile", "", "")
-}
index 5906d648b49afdb7065211eb9bec97cc7f1fbbbd..d7fca8fd2c5c9f15b3a348f2dea279ca9757fd50 100644 (file)
@@ -184,8 +184,9 @@ func Import(path string) (m module.Version, dir string, err error) {
                if !pathIsStd {
                        if cfg.BuildModReason == "" {
                                queryErr = fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
+                       } else {
+                               queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
                        }
-                       queryErr = fmt.Errorf("import lookup disabled by -mod=%s\n\t(%s)", cfg.BuildMod, cfg.BuildModReason)
                }
                return module.Version{}, "", &ImportMissingError{Path: path, QueryErr: queryErr}
        }
index 660a739fbbd4d3b9d17a0bd9ea2633971e102130..4e09c0fb9c92e3ceaa7132be04cde28bb680bae8 100644 (file)
@@ -51,7 +51,9 @@ func runVet(cmd *base.Command, args []string) {
 
        work.BuildInit()
        work.VetFlags = vetFlags
-       work.VetExplicit = true
+       if len(vetFlags) > 0 {
+               work.VetExplicit = true
+       }
        if vetTool != "" {
                var err error
                work.VetTool, err = filepath.Abs(vetTool)
index ad99eb2f8c392633eb9d41bc5f86b70df2e9a64f..209ed6861a154619cbd79d8f30fadba3a727e087 100644 (file)
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Package web defines minimal helper routines for accessing HTTP/HTTPS
-// resources without requiring external dependenicies on the net package.
+// resources without requiring external dependencies on the net package.
 //
 // If the cmd_go_bootstrap build tag is present, web avoids the use of the net
 // package and returns errors for all network operations.
index ae05250c5f695bfe80e914d0994cf319ad6dacc4..948496241e916911e752a12fe6a0b9f491d8dd6c 100644 (file)
@@ -2,49 +2,67 @@
 
 # go/build's Import should find modules by invoking the go command
 
-go build -o $WORK/testimport.exe ./testimport
+go build -o $WORK ./testimport ./testfindonly
 
 # GO111MODULE=off
 env GO111MODULE=off
-! exec $WORK/testimport.exe gobuild.example.com/x/y/z/w .
+! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
 
 # GO111MODULE=auto in GOPATH/src
 env GO111MODULE=auto
-exec $WORK/testimport.exe gobuild.example.com/x/y/z/w .
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
 
 # GO111MODULE=auto outside GOPATH/src
 cd $GOPATH/other
 env GO111MODULE=auto
-exec $WORK/testimport.exe other/x/y/z/w .
+exec $WORK/testimport$GOEXE other/x/y/z/w .
 stdout w2.go
 
-! exec $WORK/testimport.exe gobuild.example.com/x/y/z/w .
+! exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
 stderr 'cannot find module providing package gobuild.example.com/x/y/z/w'
 
 cd z
-exec $WORK/testimport.exe other/x/y/z/w .
+exec $WORK/testimport$GOEXE other/x/y/z/w .
 stdout w2.go
 
 # GO111MODULE=on outside GOPATH/src
 env GO111MODULE=
-exec $WORK/testimport.exe other/x/y/z/w .
+exec $WORK/testimport$GOEXE other/x/y/z/w .
 stdout w2.go
 env GO111MODULE=on
-exec $WORK/testimport.exe other/x/y/z/w .
+exec $WORK/testimport$GOEXE other/x/y/z/w .
 stdout w2.go
 
 # GO111MODULE=on in GOPATH/src
 cd $GOPATH/src
 env GO111MODULE=
-exec $WORK/testimport.exe gobuild.example.com/x/y/z/w .
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
 stdout w1.go
 env GO111MODULE=on
-exec $WORK/testimport.exe gobuild.example.com/x/y/z/w .
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w .
 stdout w1.go
 cd w
-exec $WORK/testimport.exe gobuild.example.com/x/y/z/w ..
+exec $WORK/testimport$GOEXE gobuild.example.com/x/y/z/w ..
 stdout w1.go
 
+# go/build's Import in FindOnly mode should find directories by invoking the go command
+#
+# Calling build.Import in build.FindOnly mode on an import path of a Go package
+# that produces errors when loading (e.g., due to build constraints not matching
+# the current build context) should return the package directory and nil error.
+
+# Issue 31603: Import with non-empty srcDir should work.
+env GO111MODULE=on
+exec $WORK/testfindonly$GOEXE gobuild.example.com/x/y/z/i $WORK
+! stdout 'build constraints'
+stdout '^dir=\$WORK.+i err=<nil>$'
+
+# Issue 37153: Import with empty srcDir should work.
+env GO111MODULE=on
+exec $WORK/testfindonly$GOEXE gobuild.example.com/x/y/z/i ''
+! stdout 'build constraints'
+stdout '^dir=\$WORK.+i err=<nil>$'
+
 -- go.mod --
 module gobuild.example.com/x/y/z
 
@@ -54,6 +72,11 @@ package z
 -- w/w1.go --
 package w
 
+-- i/i.go --
+// +build i
+
+package i
+
 -- testimport/x.go --
 package main
 
@@ -89,6 +112,20 @@ func main() {
        fmt.Printf("%s\n%s\n", p1.Dir, strings.Join(p1.GoFiles, " "))
 }
 
+-- testfindonly/x.go --
+package main
+
+import (
+       "fmt"
+       "go/build"
+       "os"
+)
+
+func main() {
+       p, err := build.Import(os.Args[1], os.Args[2], build.FindOnly)
+       fmt.Printf("dir=%s err=%v\n", p.Dir, err)
+}
+
 -- $GOPATH/other/go.mod --
 module other/x/y
 
index 77fc735d5729a5ca86f190159d466050f9455937..751f6e645e11de78cb2883327118ee047b7406ab 100644 (file)
@@ -7,6 +7,7 @@ go mod edit -fmt
 cp go.mod go.mod.empty
 ! go list all
 stderr '^can''t load package: x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly'
+! stderr '\(\)' # If we don't have a reason for -mod=readonly, don't log an empty one.
 cmp go.mod go.mod.empty
 
 # -mod=readonly should be set implicitly if the go.mod file is read-only
index 94bfd126c090992fe491bf2857cd391c309b8e39..2d790c1ac99a614262f19607d7e18ee49572babe 100644 (file)
@@ -9,6 +9,17 @@ go vet -n -unreachable=false encoding/binary
 stderr '-unreachable=false'
 ! stderr '-unsafeptr=false'
 
+# Issue 37030: "go vet <std package>" without other flags should disable the
+# unsafeptr check by default.
+go vet -n encoding/binary
+stderr '-unsafeptr=false'
+! stderr '-unreachable=false'
+
+# However, it should be enabled if requested explicitly.
+go vet -n -unsafeptr encoding/binary
+stderr '-unsafeptr'
+! stderr '-unsafeptr=false'
+
 [short] stop
 env GOCACHE=$WORK/gocache
 env GOTMPDIR=$WORK/tmp
index 73d78550f897b8a951e480210692646b9b952451..ba0af84a9d09d6c7966476796c83f6a6bd53928b 100644 (file)
@@ -86,7 +86,8 @@ func NewGCM(cipher Block) (AEAD, error) {
 }
 
 // NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois
-// Counter Mode, which accepts nonces of the given length.
+// Counter Mode, which accepts nonces of the given length. The length must not
+// be zero.
 //
 // Only use this function if you require compatibility with an existing
 // cryptosystem that uses non-standard nonce lengths. All other users should use
@@ -112,6 +113,10 @@ func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, erro
                return nil, errors.New("cipher: incorrect tag size given to GCM")
        }
 
+       if nonceSize <= 0 {
+               return nil, errors.New("cipher: the nonce can't have zero length, or the security of the key will be immediately compromised")
+       }
+
        if cipher, ok := cipher.(gcmAble); ok {
                return cipher.NewGCM(nonceSize, tagSize)
        }
index 64d5cc0db4fd9ff5d88054038a2cf610403f015b..0d53e471f95836467bf773e7d2fef0cee7c0af83 100644 (file)
@@ -217,6 +217,13 @@ var aesGCMTests = []struct {
                "2b9680b886b3efb7c6354b38c63b5373",
                "e2b7e5ed5ff27fc8664148f5a628a46dcbf2015184fffb82f2651c36",
        },
+       {
+               "11754cd72aec309bf52f7687212e8957",
+               "",
+               "",
+               "",
+               "250327c674aaf477aef2675748cf6971",
+       },
 }
 
 func TestAESGCM(t *testing.T) {
@@ -234,14 +241,22 @@ func TestAESGCM(t *testing.T) {
 
                var aesgcm cipher.AEAD
                switch {
-               // Handle non-standard nonce sizes
+               // Handle non-standard tag sizes
                case tagSize != 16:
                        aesgcm, err = cipher.NewGCMWithTagSize(aes, tagSize)
                        if err != nil {
                                t.Fatal(err)
                        }
 
-               // Handle non-standard tag sizes
+               // Handle 0 nonce size (expect error and continue)
+               case len(nonce) == 0:
+                       aesgcm, err = cipher.NewGCMWithNonceSize(aes, 0)
+                       if err == nil {
+                               t.Fatal("expected error for zero nonce size")
+                       }
+                       continue
+
+               // Handle non-standard nonce sizes
                case len(nonce) != 12:
                        aesgcm, err = cipher.NewGCMWithNonceSize(aes, len(nonce))
                        if err != nil {
index c84657c5e36777fcdf435b56ecf34d958f1b686f..e2f71cdb63babf2fcd72bacff4acafdcd5264b60 100644 (file)
@@ -372,7 +372,12 @@ func initP521() {
        p521.BitSize = 521
 }
 
-// P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
+// P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3),
+// also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is
+// "P-256".
+//
+// Multiple invocations of this function will return the same value, so it can
+// be used for equality checks and switch statements.
 //
 // The cryptographic operations are implemented using constant-time algorithms.
 func P256() Curve {
@@ -380,7 +385,11 @@ func P256() Curve {
        return p256
 }
 
-// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
+// P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4),
+// also known as secp384r1. The CurveParams.Name of this Curve is "P-384".
+//
+// Multiple invocations of this function will return the same value, so it can
+// be used for equality checks and switch statements.
 //
 // The cryptographic operations do not use constant-time algorithms.
 func P384() Curve {
@@ -388,7 +397,11 @@ func P384() Curve {
        return p384
 }
 
-// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+// P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5),
+// also known as secp521r1. The CurveParams.Name of this Curve is "P-521".
+//
+// Multiple invocations of this function will return the same value, so it can
+// be used for equality checks and switch statements.
 //
 // The cryptographic operations do not use constant-time algorithms.
 func P521() Curve {
index d37fc9e1b3fedf13caca4cb06b8a94a515ca9610..ec4ab10c5733f54d6608e87148a2455072d560d3 100644 (file)
@@ -79,7 +79,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
        }
 }
 
-// MarshalPKCS8PrivateKey converts an RSA private key to PKCS#8, ASN.1 DER form.
+// MarshalPKCS8PrivateKey converts a private key to PKCS#8, ASN.1 DER form.
 //
 // The following key types are currently supported: *rsa.PrivateKey, *ecdsa.PrivateKey
 // and ed25519.PrivateKey. Unsupported key types result in an error.
index e250ae7112586d802dd960b574fa832442167052..d5987dd861e06e13d41c06cd3091d821c858387f 100644 (file)
@@ -1017,8 +1017,6 @@ var errNoModules = errors.New("not using modules")
 // Then we reinvoke it for every dependency. But this is still better than not working at all.
 // See golang.org/issue/26504.
 func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) error {
-       const debugImportGo = false
-
        // To invoke the go command,
        // we must not being doing special things like AllowBinary or IgnoreVendor,
        // and all the file system callbacks must be nil (we're meant to use the local file system).
@@ -1137,15 +1135,15 @@ func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode)
        }
        dir := f[0]
        errStr := strings.TrimSpace(f[4])
-       if errStr != "" && p.Dir == "" {
-               // If 'go list' could not locate the package, return the same error that
-               // 'go list' reported.
-               // If 'go list' did locate the package (p.Dir is not empty), ignore the
-               // error. It was probably related to loading source files, and we'll
-               // encounter it ourselves shortly.
+       if errStr != "" && dir == "" {
+               // If 'go list' could not locate the package (dir is empty),
+               // return the same error that 'go list' reported.
                return errors.New(errStr)
        }
 
+       // If 'go list' did locate the package, ignore the error.
+       // It was probably related to loading source files, and we'll
+       // encounter it ourselves shortly if the FindOnly flag isn't set.
        p.Dir = dir
        p.ImportPath = f[1]
        p.Root = f[2]
index 0e50af04f624ab4ecf0e0d6de68e7a4e287065d2..79d38998e7b51164eb427dfa819049584947837f 100644 (file)
@@ -138,9 +138,12 @@ func New(pkg *ast.Package, importPath string, mode Mode) *Package {
 // NewFromFiles computes documentation for a package.
 //
 // The package is specified by a list of *ast.Files and corresponding
-// file set, which must not be nil. NewFromFiles does not skip files
-// based on build constraints, so it is the caller's responsibility to
-// provide only the files that are matched by the build context.
+// file set, which must not be nil.
+// NewFromFiles uses all provided files when computing documentation,
+// so it is the caller's responsibility to provide only the files that
+// match the desired build context. "go/build".Context.MatchFile can
+// be used for determining whether a file matches a build context with
+// the desired GOOS and GOARCH values, and other build constraints.
 // The import path of the package is specified by importPath.
 //
 // Examples found in _test.go files are associated with the corresponding
index 3f406e9db634e629d07e8e07f750140507a69931..071dc04b5489566720e0725ac631f541f4ff8a38 100644 (file)
@@ -5,10 +5,13 @@
 // Package maphash provides hash functions on byte sequences.
 // These hash functions are intended to be used to implement hash tables or
 // other data structures that need to map arbitrary strings or byte
-// sequences to a uniform distribution of integers.
+// sequences to a uniform distribution on unsigned 64-bit integers.
 //
 // The hash functions are collision-resistant but not cryptographically secure.
 // (See crypto/sha256 and crypto/sha512 for cryptographic use.)
+//
+// The hash value of a given byte sequence is consistent within a
+// single process, but will be different in different processes.
 package maphash
 
 import "unsafe"
@@ -66,7 +69,7 @@ type Hash struct {
 // which does call h.initSeed.)
 func (h *Hash) initSeed() {
        if h.seed.s == 0 {
-               h.SetSeed(MakeSeed())
+               h.setSeed(MakeSeed())
        }
 }
 
@@ -121,12 +124,17 @@ func (h *Hash) Seed() Seed {
 // Two Hash objects with different seeds will very likely behave differently.
 // Any bytes added to h before this call will be discarded.
 func (h *Hash) SetSeed(seed Seed) {
+       h.setSeed(seed)
+       h.n = 0
+}
+
+// setSeed sets seed without discarding accumulated data.
+func (h *Hash) setSeed(seed Seed) {
        if seed.s == 0 {
                panic("maphash: use of uninitialized Seed")
        }
        h.seed = seed
        h.state = seed
-       h.n = 0
 }
 
 // Reset discards all bytes added to h.
index 31d84a3b50a74fd0f4802a86d595be3279d0e29a..0164a9e20ae48212c553b93d00f9efed4fa7ade2 100644 (file)
@@ -83,6 +83,29 @@ func TestHashHighBytes(t *testing.T) {
        }
 }
 
+func TestRepeat(t *testing.T) {
+       h1 := new(Hash)
+       h1.WriteString("testing")
+       sum1 := h1.Sum64()
+
+       h1.Reset()
+       h1.WriteString("testing")
+       sum2 := h1.Sum64()
+
+       if sum1 != sum2 {
+               t.Errorf("different sum after reseting: %#x != %#x", sum1, sum2)
+       }
+
+       h2 := new(Hash)
+       h2.SetSeed(h1.Seed())
+       h2.WriteString("testing")
+       sum3 := h2.Sum64()
+
+       if sum1 != sum3 {
+               t.Errorf("different sum on the same seed: %#x != %#x", sum1, sum3)
+       }
+}
+
 // Make sure a Hash implements the hash.Hash and hash.Hash64 interfaces.
 var _ hash.Hash = &Hash{}
 var _ hash.Hash64 = &Hash{}
index bec0a81b20bd94eaf616472312b7514b88939182..18f122e953c45a5b314d95d6fff564db02d18fe4 100644 (file)
@@ -505,8 +505,8 @@ func (z *Int) Exp(x, y, m *Int) *Int {
 // GCD sets z to the greatest common divisor of a and b and returns z.
 // If x or y are not nil, GCD sets their value such that z = a*x + b*y.
 //
-// a and b may be positive, zero or negative.
-// Regardless of the signs of a and b, z is always >= 0.
+// a and b may be positive, zero or negative. (Before Go 1.14 both had
+// to be > 0.) Regardless of the signs of a and b, z is always >= 0.
 //
 // If a == b == 0, GCD sets z = x = y = 0.
 //
index 35ace7f073da87af6caaf7561493c500ba5087ac..266f5eba747ba09a7cee4e17526a774b47709b76 100644 (file)
 // Allocating and freeing a large object uses the mheap
 // directly, bypassing the mcache and mcentral.
 //
-// Free object slots in an mspan are zeroed only if mspan.needzero is
-// false. If needzero is true, objects are zeroed as they are
-// allocated. There are various benefits to delaying zeroing this way:
+// If mspan.needzero is false, then free object slots in the mspan are
+// already zeroed. Otherwise if needzero is true, objects are zeroed as
+// they are allocated. There are various benefits to delaying zeroing
+// this way:
 //
 //     1. Stack frame allocation can avoid zeroing altogether.
 //
index 64e220772e1ba2b229a40f10a478616c2b17ef6a..31b6f5cbac3ad1b9319dcb4fe1d3840dfcf12445 100644 (file)
@@ -244,6 +244,15 @@ func genAMD64() {
 
        // TODO: MXCSR register?
 
+       // Apparently, the signal handling code path in darwin kernel leaves
+       // the upper bits of Y registers in a dirty state, which causes
+       // many SSE operations (128-bit and narrower) become much slower.
+       // Clear the upper bits to get to a clean state. See issue #37174.
+       // It is safe here as Go code don't use the upper bits of Y registers.
+       p("#ifdef GOOS_darwin")
+       p("VZEROUPPER")
+       p("#endif")
+
        p("PUSHQ BP")
        p("MOVQ SP, BP")
        p("// Save flags before clobbering them")
index fe45cfbd400f2ba5275942a7d313acc053131fbd..f86f2f61748ed8c78fb8b647a191f14431915c00 100644 (file)
@@ -13,16 +13,23 @@ var netpollWaiters uint32
 
 var netpollStubLock mutex
 var netpollNote note
-var netpollBroken uint32
+
+// netpollBroken, protected by netpollBrokenLock, avoids a double notewakeup.
+var netpollBrokenLock mutex
+var netpollBroken bool
 
 func netpollGenericInit() {
        atomic.Store(&netpollInited, 1)
 }
 
 func netpollBreak() {
-       if atomic.Cas(&netpollBroken, 0, 1) {
+       lock(&netpollBrokenLock)
+       broken := netpollBroken
+       netpollBroken = true
+       if !broken {
                notewakeup(&netpollNote)
        }
+       unlock(&netpollBrokenLock)
 }
 
 // Polls for ready network connections.
@@ -34,8 +41,12 @@ func netpoll(delay int64) gList {
                // This lock ensures that only one goroutine tries to use
                // the note. It should normally be completely uncontended.
                lock(&netpollStubLock)
+
+               lock(&netpollBrokenLock)
                noteclear(&netpollNote)
-               atomic.Store(&netpollBroken, 0)
+               netpollBroken = false
+               unlock(&netpollBrokenLock)
+
                notetsleep(&netpollNote, delay)
                unlock(&netpollStubLock)
        }
index 93f461b07a22d32e3ea6ee15ad077885de0b2679..88ba0f024203fa70d9fb5f97f74b179b36bd5d6d 100644 (file)
@@ -179,6 +179,7 @@ func (b *B) ReportAllocs() {
 func (b *B) runN(n int) {
        benchmarkLock.Lock()
        defer benchmarkLock.Unlock()
+       defer b.runCleanup(normalPanic)
        // Try to get a comparable environment for each run
        // by clearing garbage from previous runs.
        runtime.GC()
index 3dc30ee72e2077ecd79f078ccf1395978a0d1a93..95f8220f815fe08834e566224f67a5caee93df20 100644 (file)
@@ -613,6 +613,46 @@ func TestBRun(t *T) {
                                t.Errorf("MemBytes was %v; want %v", got, 2*bufSize)
                        }
                },
+       }, {
+               desc: "cleanup is called",
+               f: func(b *B) {
+                       var calls, cleanups, innerCalls, innerCleanups int
+                       b.Run("", func(b *B) {
+                               calls++
+                               b.Cleanup(func() {
+                                       cleanups++
+                               })
+                               b.Run("", func(b *B) {
+                                       b.Cleanup(func() {
+                                               innerCleanups++
+                                       })
+                                       innerCalls++
+                               })
+                               work(b)
+                       })
+                       if calls == 0 || calls != cleanups {
+                               t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
+                       }
+                       if innerCalls == 0 || innerCalls != innerCleanups {
+                               t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
+                       }
+               },
+       }, {
+               desc:   "cleanup is called on failure",
+               failed: true,
+               f: func(b *B) {
+                       var calls, cleanups int
+                       b.Run("", func(b *B) {
+                               calls++
+                               b.Cleanup(func() {
+                                       cleanups++
+                               })
+                               b.Fatalf("failure")
+                       })
+                       if calls == 0 || calls != cleanups {
+                               t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
+                       }
+               },
        }}
        for _, tc := range testCases {
                var ok bool
index 67892d71fd07334aa2024a290f6d37aef53b4d7e..0891142d2c48ea7fe3d8b2e4aa044f714ab5f2f0 100644 (file)
@@ -571,7 +571,6 @@ var _ TB = (*T)(nil)
 var _ TB = (*B)(nil)
 
 // T is a type passed to Test functions to manage test state and support formatted test logs.
-// Logs are accumulated during execution and dumped to standard output when done.
 //
 // A test ends when its Test function returns or calls any of the methods
 // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as