diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 7dcb9ecb4fd..a62c8292e0a 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/libgo/MERGE b/libgo/MERGE index 2d01b8759bf..233492ada69 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -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. diff --git a/libgo/VERSION b/libgo/VERSION index 5304c505acd..f000507a7fe 100644 --- a/libgo/VERSION +++ b/libgo/VERSION @@ -1 +1 @@ -go1.14rc1 +go1.14 diff --git a/libgo/go/cmd/go/internal/modcmd/mod.go b/libgo/go/cmd/go/internal/modcmd/mod.go index 17505221587..d72d0cacd68 100644 --- a/libgo/go/cmd/go/internal/modcmd/mod.go +++ b/libgo/go/cmd/go/internal/modcmd/mod.go @@ -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", "", "") -} diff --git a/libgo/go/cmd/go/internal/modload/import.go b/libgo/go/cmd/go/internal/modload/import.go index 5906d648b49..d7fca8fd2c5 100644 --- a/libgo/go/cmd/go/internal/modload/import.go +++ b/libgo/go/cmd/go/internal/modload/import.go @@ -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} } diff --git a/libgo/go/cmd/go/internal/vet/vet.go b/libgo/go/cmd/go/internal/vet/vet.go index 660a739fbbd..4e09c0fb9c9 100644 --- a/libgo/go/cmd/go/internal/vet/vet.go +++ b/libgo/go/cmd/go/internal/vet/vet.go @@ -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) diff --git a/libgo/go/cmd/go/internal/web/api.go b/libgo/go/cmd/go/internal/web/api.go index ad99eb2f8c3..209ed6861a1 100644 --- a/libgo/go/cmd/go/internal/web/api.go +++ b/libgo/go/cmd/go/internal/web/api.go @@ -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. diff --git a/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt b/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt index ae05250c5f6..948496241e9 100644 --- a/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt +++ b/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt @@ -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=$' + +# 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=$' + -- 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 diff --git a/libgo/go/cmd/go/testdata/script/mod_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_readonly.txt index 77fc735d572..751f6e645e1 100644 --- a/libgo/go/cmd/go/testdata/script/mod_readonly.txt +++ b/libgo/go/cmd/go/testdata/script/mod_readonly.txt @@ -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 diff --git a/libgo/go/cmd/go/testdata/script/vet_flags.txt b/libgo/go/cmd/go/testdata/script/vet_flags.txt index 94bfd126c09..2d790c1ac99 100644 --- a/libgo/go/cmd/go/testdata/script/vet_flags.txt +++ b/libgo/go/cmd/go/testdata/script/vet_flags.txt @@ -9,6 +9,17 @@ go vet -n -unreachable=false encoding/binary stderr '-unreachable=false' ! stderr '-unsafeptr=false' +# Issue 37030: "go vet " 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 diff --git a/libgo/go/crypto/cipher/gcm.go b/libgo/go/crypto/cipher/gcm.go index 73d78550f89..ba0af84a9d0 100644 --- a/libgo/go/crypto/cipher/gcm.go +++ b/libgo/go/crypto/cipher/gcm.go @@ -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) } diff --git a/libgo/go/crypto/cipher/gcm_test.go b/libgo/go/crypto/cipher/gcm_test.go index 64d5cc0db4f..0d53e471f95 100644 --- a/libgo/go/crypto/cipher/gcm_test.go +++ b/libgo/go/crypto/cipher/gcm_test.go @@ -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 { diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go index c84657c5e36..e2f71cdb63b 100644 --- a/libgo/go/crypto/elliptic/elliptic.go +++ b/libgo/go/crypto/elliptic/elliptic.go @@ -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 { diff --git a/libgo/go/crypto/x509/pkcs8.go b/libgo/go/crypto/x509/pkcs8.go index d37fc9e1b3f..ec4ab10c573 100644 --- a/libgo/go/crypto/x509/pkcs8.go +++ b/libgo/go/crypto/x509/pkcs8.go @@ -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. diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index e250ae71125..d5987dd861e 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -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] diff --git a/libgo/go/go/doc/doc.go b/libgo/go/go/doc/doc.go index 0e50af04f62..79d38998e7b 100644 --- a/libgo/go/go/doc/doc.go +++ b/libgo/go/go/doc/doc.go @@ -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 diff --git a/libgo/go/hash/maphash/maphash.go b/libgo/go/hash/maphash/maphash.go index 3f406e9db63..071dc04b548 100644 --- a/libgo/go/hash/maphash/maphash.go +++ b/libgo/go/hash/maphash/maphash.go @@ -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. diff --git a/libgo/go/hash/maphash/maphash_test.go b/libgo/go/hash/maphash/maphash_test.go index 31d84a3b50a..0164a9e20ae 100644 --- a/libgo/go/hash/maphash/maphash_test.go +++ b/libgo/go/hash/maphash/maphash_test.go @@ -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{} diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go index bec0a81b20b..18f122e953c 100644 --- a/libgo/go/math/big/int.go +++ b/libgo/go/math/big/int.go @@ -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. // diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go index 35ace7f073d..266f5eba747 100644 --- a/libgo/go/runtime/malloc.go +++ b/libgo/go/runtime/malloc.go @@ -62,9 +62,10 @@ // 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. // diff --git a/libgo/go/runtime/mkpreempt.go b/libgo/go/runtime/mkpreempt.go index 64e220772e1..31b6f5cbac3 100644 --- a/libgo/go/runtime/mkpreempt.go +++ b/libgo/go/runtime/mkpreempt.go @@ -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") diff --git a/libgo/go/runtime/netpoll_stub.go b/libgo/go/runtime/netpoll_stub.go index fe45cfbd400..f86f2f61748 100644 --- a/libgo/go/runtime/netpoll_stub.go +++ b/libgo/go/runtime/netpoll_stub.go @@ -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) } diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go index 93f461b07a2..88ba0f02420 100644 --- a/libgo/go/testing/benchmark.go +++ b/libgo/go/testing/benchmark.go @@ -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() diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go index 3dc30ee72e2..95f8220f815 100644 --- a/libgo/go/testing/sub_test.go +++ b/libgo/go/testing/sub_test.go @@ -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 diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index 67892d71fd0..0891142d2c4 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -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