diff options
author | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-17 22:10:58 +0000 |
---|---|---|
committer | ian <ian@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-04-17 22:10:58 +0000 |
commit | 956a9d3770ca7cfcec334147c98e26bc00d044e0 (patch) | |
tree | a190311458c423b71ed9f800fd5bd43faa7dccc3 | |
parent | 13be6c20301280dbd9172dc0fac31a6ed9c1e8e2 (diff) | |
download | gcc-956a9d3770ca7cfcec334147c98e26bc00d044e0.tar.gz |
libgo: update to Go 1.8.1 release
Reviewed-on: https://go-review.googlesource.com/40775
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@246957 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libgo/MERGE | 2 | ||||
-rw-r--r-- | libgo/VERSION | 2 | ||||
-rw-r--r-- | libgo/go/cmd/go/go_test.go | 18 | ||||
-rw-r--r-- | libgo/go/cmd/go/pkg.go | 4 | ||||
-rw-r--r-- | libgo/go/cmd/go/test.go | 21 | ||||
-rw-r--r-- | libgo/go/crypto/tls/common.go | 1 | ||||
-rw-r--r-- | libgo/go/crypto/tls/tls_test.go | 90 | ||||
-rw-r--r-- | libgo/go/encoding/xml/marshal_test.go | 7 | ||||
-rw-r--r-- | libgo/go/encoding/xml/read.go | 3 | ||||
-rw-r--r-- | libgo/go/encoding/xml/xml_test.go | 34 | ||||
-rw-r--r-- | libgo/go/image/png/reader.go | 5 | ||||
-rw-r--r-- | libgo/go/image/png/reader_test.go | 10 | ||||
-rw-r--r-- | libgo/go/internal/testenv/testenv.go | 9 | ||||
-rw-r--r-- | libgo/go/internal/testenv/testenv_cgo.go | 11 | ||||
-rw-r--r-- | libgo/go/net/http/http.go | 2 | ||||
-rw-r--r-- | libgo/go/net/net.go | 2 | ||||
-rw-r--r-- | libgo/go/os/exec/exec_test.go | 10 | ||||
-rw-r--r-- | libgo/go/reflect/all_test.go | 35 | ||||
-rw-r--r-- | libgo/go/runtime/crash_unix_test.go | 73 | ||||
-rw-r--r-- | libgo/go/runtime/export_test.go | 13 | ||||
-rw-r--r-- | libgo/go/runtime/runtime1.go | 6 | ||||
-rw-r--r-- | libgo/go/runtime/sema.go | 1 | ||||
-rw-r--r-- | libgo/go/text/template/multi_test.go | 37 | ||||
-rw-r--r-- | libgo/go/text/template/template.go | 4 |
24 files changed, 359 insertions, 41 deletions
diff --git a/libgo/MERGE b/libgo/MERGE index 16f346a2b8e..a5808db54ff 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -cd6b6202dd1559b3ac63179b45f1833fcfbe7eca +a4c18f063b6659079ca2848ca217a0587dabc001 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 436edd93930..dce1d463ba1 100644 --- a/libgo/VERSION +++ b/libgo/VERSION @@ -1 +1 @@ -go1.8 +go1.8.1 diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go index 56de65ce55a..fa78578d121 100644 --- a/libgo/go/cmd/go/go_test.go +++ b/libgo/go/cmd/go/go_test.go @@ -2227,6 +2227,24 @@ func TestTestEmpty(t *testing.T) { } } +func TestTestRaceInstall(t *testing.T) { + if !canRace { + t.Skip("no race detector") + } + + tg := testgo(t) + defer tg.cleanup() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + + tg.tempDir("pkg") + pkgdir := tg.path("pkg") + tg.run("install", "-race", "-pkgdir="+pkgdir, "std") + tg.run("test", "-race", "-pkgdir="+pkgdir, "-i", "-v", "empty/pkg") + if tg.getStderr() != "" { + t.Error("go test -i -race: rebuilds cached packages") + } +} + func TestBuildDryRunWithCgo(t *testing.T) { if !canCgo { t.Skip("skipping because cgo not enabled") diff --git a/libgo/go/cmd/go/pkg.go b/libgo/go/cmd/go/pkg.go index 61c1b9960ea..f0dc95670f9 100644 --- a/libgo/go/cmd/go/pkg.go +++ b/libgo/go/cmd/go/pkg.go @@ -970,10 +970,6 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package if p.Name == "main" && goarch == "arm" { importPaths = append(importPaths, "math") } - // In coverage atomic mode everything depends on sync/atomic. - if testCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) { - importPaths = append(importPaths, "sync/atomic") - } } // Runtime and its internal packages depend on runtime/internal/sys, diff --git a/libgo/go/cmd/go/test.go b/libgo/go/cmd/go/test.go index 5c13b653f01..12990feb43c 100644 --- a/libgo/go/cmd/go/test.go +++ b/libgo/go/cmd/go/test.go @@ -548,6 +548,10 @@ func runTest(cmd *Command, args []string) { // Prepare build + run + print actions for all packages being tested. for _, p := range pkgs { + // sync/atomic import is inserted by the cover tool. See #18486 + if testCover && testCoverMode == "atomic" { + ensureImport(p, "sync/atomic") + } buildTest, runTest, printTest, err := b.test(p) if err != nil { str := err.Error() @@ -639,6 +643,23 @@ func runTest(cmd *Command, args []string) { b.do(root) } +// ensures that package p imports the named package. +func ensureImport(p *Package, pkg string) { + for _, d := range p.deps { + if d.Name == pkg { + return + } + } + + a := loadPackage(pkg, &importStack{}) + if a.Error != nil { + fatalf("load %s: %v", pkg, a.Error) + } + computeStale(a) + + p.imports = append(p.imports, a) +} + func contains(x []string, s string) bool { for _, t := range x { if t == s { diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go index 276d1761ea0..de833a90563 100644 --- a/libgo/go/crypto/tls/common.go +++ b/libgo/go/crypto/tls/common.go @@ -563,6 +563,7 @@ func (c *Config) Clone() *Config { Certificates: c.Certificates, NameToCertificate: c.NameToCertificate, GetCertificate: c.GetCertificate, + GetClientCertificate: c.GetClientCertificate, GetConfigForClient: c.GetConfigForClient, VerifyPeerCertificate: c.VerifyPeerCertificate, RootCAs: c.RootCAs, diff --git a/libgo/go/crypto/tls/tls_test.go b/libgo/go/crypto/tls/tls_test.go index 8933f4f2015..86812f0c974 100644 --- a/libgo/go/crypto/tls/tls_test.go +++ b/libgo/go/crypto/tls/tls_test.go @@ -13,13 +13,11 @@ import ( "io" "io/ioutil" "math" - "math/rand" "net" "os" "reflect" "strings" "testing" - "testing/quick" "time" ) @@ -568,11 +566,50 @@ func TestConnCloseWrite(t *testing.T) { } } -func TestClone(t *testing.T) { +func TestCloneFuncFields(t *testing.T) { + const expectedCount = 5 + called := 0 + + c1 := Config{ + Time: func() time.Time { + called |= 1 << 0 + return time.Time{} + }, + GetCertificate: func(*ClientHelloInfo) (*Certificate, error) { + called |= 1 << 1 + return nil, nil + }, + GetClientCertificate: func(*CertificateRequestInfo) (*Certificate, error) { + called |= 1 << 2 + return nil, nil + }, + GetConfigForClient: func(*ClientHelloInfo) (*Config, error) { + called |= 1 << 3 + return nil, nil + }, + VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + called |= 1 << 4 + return nil + }, + } + + c2 := c1.Clone() + + c2.Time() + c2.GetCertificate(nil) + c2.GetClientCertificate(nil) + c2.GetConfigForClient(nil) + c2.VerifyPeerCertificate(nil, nil) + + if called != (1<<expectedCount)-1 { + t.Fatalf("expected %d calls but saw calls %b", expectedCount, called) + } +} + +func TestCloneNonFuncFields(t *testing.T) { var c1 Config v := reflect.ValueOf(&c1).Elem() - rnd := rand.New(rand.NewSource(time.Now().Unix())) typ := v.Type() for i := 0; i < typ.NumField(); i++ { f := v.Field(i) @@ -581,40 +618,49 @@ func TestClone(t *testing.T) { continue } - // testing/quick can't handle functions or interfaces. - fn := typ.Field(i).Name - switch fn { + // testing/quick can't handle functions or interfaces and so + // isn't used here. + switch fn := typ.Field(i).Name; fn { case "Rand": f.Set(reflect.ValueOf(io.Reader(os.Stdin))) - continue case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate": - // DeepEqual can't compare functions. - continue + // DeepEqual can't compare functions. If you add a + // function field to this list, you must also change + // TestCloneFuncFields to ensure that the func field is + // cloned. case "Certificates": f.Set(reflect.ValueOf([]Certificate{ {Certificate: [][]byte{{'b'}}}, })) - continue case "NameToCertificate": f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil})) - continue case "RootCAs", "ClientCAs": f.Set(reflect.ValueOf(x509.NewCertPool())) - continue case "ClientSessionCache": f.Set(reflect.ValueOf(NewLRUClientSessionCache(10))) - continue case "KeyLogWriter": f.Set(reflect.ValueOf(io.Writer(os.Stdout))) - continue - - } - - q, ok := quick.Value(f.Type(), rnd) - if !ok { - t.Fatalf("quick.Value failed on field %s", fn) + case "NextProtos": + f.Set(reflect.ValueOf([]string{"a", "b"})) + case "ServerName": + f.Set(reflect.ValueOf("b")) + case "ClientAuth": + f.Set(reflect.ValueOf(VerifyClientCertIfGiven)) + case "InsecureSkipVerify", "SessionTicketsDisabled", "DynamicRecordSizingDisabled", "PreferServerCipherSuites": + f.Set(reflect.ValueOf(true)) + case "MinVersion", "MaxVersion": + f.Set(reflect.ValueOf(uint16(VersionTLS12))) + case "SessionTicketKey": + f.Set(reflect.ValueOf([32]byte{})) + case "CipherSuites": + f.Set(reflect.ValueOf([]uint16{1, 2})) + case "CurvePreferences": + f.Set(reflect.ValueOf([]CurveID{CurveP256})) + case "Renegotiation": + f.Set(reflect.ValueOf(RenegotiateOnceAsClient)) + default: + t.Errorf("all fields must be accounted for, but saw unknown field %q", fn) } - f.Set(q) } c2 := c1.Clone() diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go index 5ec7ececa4d..0126146d332 100644 --- a/libgo/go/encoding/xml/marshal_test.go +++ b/libgo/go/encoding/xml/marshal_test.go @@ -2428,7 +2428,10 @@ func TestIssue16158(t *testing.T) { err := Unmarshal([]byte(data), &struct { B byte `xml:"b,attr,omitempty"` }{}) - if err == nil { - t.Errorf("Unmarshal: expected error, got nil") + + // For Go 1.8.1 we've restored the old "no errors reported" behavior. + // We'll try again in Go 1.9 to report errors. + if err != nil { + t.Errorf("Unmarshal: expected nil, got error") } } diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go index 5a89d5f504a..799b57e9d15 100644 --- a/libgo/go/encoding/xml/read.go +++ b/libgo/go/encoding/xml/read.go @@ -285,7 +285,8 @@ func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { return nil } - return copyValue(val, []byte(attr.Value)) + copyValue(val, []byte(attr.Value)) + return nil } var ( diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go index dad6ed98c1b..f43a5e7eebc 100644 --- a/libgo/go/encoding/xml/xml_test.go +++ b/libgo/go/encoding/xml/xml_test.go @@ -797,3 +797,37 @@ func TestIssue12417(t *testing.T) { } } } + +func TestIssue19333(t *testing.T) { + type X struct { + XMLName Name `xml:"X"` + A int `xml:",attr"` + C int + } + + var tests = []struct { + input string + ok bool + }{ + {`<X></X>`, true}, + {`<X A=""></X>`, true}, + {`<X A="bad"></X>`, true}, + {`<X></X>`, true}, + {`<X><C></C></X>`, false}, + {`<X><C/></X>`, false}, + {`<X><C>bad</C></X>`, false}, + } + + for _, tt := range tests { + err := Unmarshal([]byte(tt.input), new(X)) + if tt.ok { + if err != nil { + t.Errorf("%s: unexpected error: %v", tt.input, err) + } + } else { + if err == nil { + t.Errorf("%s: unexpected success", tt.input) + } + } + } +} diff --git a/libgo/go/image/png/reader.go b/libgo/go/image/png/reader.go index 32f78f0ffe8..8299df56735 100644 --- a/libgo/go/image/png/reader.go +++ b/libgo/go/image/png/reader.go @@ -612,6 +612,11 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image } } case cbG8: + if d.useTransparent { + // Match error from Go 1.7 and earlier. + // Go 1.9 will decode this properly. + return nil, chunkOrderError + } copy(gray.Pix[pixOffset:], cdat) pixOffset += gray.Stride case cbGA8: diff --git a/libgo/go/image/png/reader_test.go b/libgo/go/image/png/reader_test.go index b9e9f4d02c6..503b5dc567b 100644 --- a/libgo/go/image/png/reader_test.go +++ b/libgo/go/image/png/reader_test.go @@ -629,3 +629,13 @@ func BenchmarkDecodeRGB(b *testing.B) { func BenchmarkDecodeInterlacing(b *testing.B) { benchmarkDecode(b, "testdata/benchRGB-interlace.png", 4) } + +func TestIssue19553(t *testing.T) { + var buf = []byte{ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x85, 0x2c, 0x88, 0x80, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x00, 0xff, 0x5b, 0x91, 0x22, 0xb5, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x0a, 0xf0, 0x01, 0x42, 0xac, 0x34, 0x98, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x04, 0x02, 0x12, 0x11, 0x11, 0xf7, 0x65, 0x3d, 0x8b, 0x00, 0x00, 0x00, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0xff, 0xff, 0xb9, 0xbd, 0x70, 0xf0, 0x8c, 0x01, 0xc8, 0xaf, 0x6e, 0x99, 0x02, 0x05, 0xd9, 0x7b, 0xc1, 0xfc, 0x6b, 0xff, 0xa1, 0xa0, 0x87, 0x30, 0xff, 0xd9, 0xde, 0xbd, 0xd5, 0x4b, 0xf7, 0xee, 0xfd, 0x0e, 0xe3, 0xef, 0xcd, 0x06, 0x19, 0x14, 0xf5, 0x1e, 0xce, 0xef, 0x01, 0x31, 0x92, 0xd7, 0x82, 0x41, 0x31, 0x9c, 0x3f, 0x07, 0x02, 0xee, 0xa1, 0xaa, 0xff, 0xff, 0x9f, 0xe1, 0xd9, 0x56, 0x30, 0xf8, 0x0e, 0xe5, 0x03, 0x00, 0xa9, 0x42, 0x84, 0x3d, 0xdf, 0x8f, 0xa6, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, + } + _, err := Decode(bytes.NewReader(buf)) + if err != chunkOrderError { + t.Errorf("Decode: expected chunkOrderError for transparent gray8, got %v", err) + } +} diff --git a/libgo/go/internal/testenv/testenv.go b/libgo/go/internal/testenv/testenv.go index fdba8b25c3a..71a692b367e 100644 --- a/libgo/go/internal/testenv/testenv.go +++ b/libgo/go/internal/testenv/testenv.go @@ -141,6 +141,15 @@ func MustHaveExternalNetwork(t *testing.T) { } } +var haveCGO bool + +// MustHaveCGO calls t.Skip if cgo is not available. +func MustHaveCGO(t *testing.T) { + if !haveCGO { + t.Skipf("skipping test: no cgo") + } +} + // HasSymlink reports whether the current system can use os.Symlink. func HasSymlink() bool { ok, _ := hasSymlink() diff --git a/libgo/go/internal/testenv/testenv_cgo.go b/libgo/go/internal/testenv/testenv_cgo.go new file mode 100644 index 00000000000..e3d4d16b33e --- /dev/null +++ b/libgo/go/internal/testenv/testenv_cgo.go @@ -0,0 +1,11 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build cgo + +package testenv + +func init() { + haveCGO = true +} diff --git a/libgo/go/net/http/http.go b/libgo/go/net/http/http.go index 826f7ff3da5..b95ca89f409 100644 --- a/libgo/go/net/http/http.go +++ b/libgo/go/net/http/http.go @@ -20,7 +20,7 @@ const maxInt64 = 1<<63 - 1 // aLongTimeAgo is a non-zero time, far in the past, used for // immediate cancelation of network operations. -var aLongTimeAgo = time.Unix(233431200, 0) +var aLongTimeAgo = time.Unix(1, 0) // TODO(bradfitz): move common stuff here. The other files have accumulated // generic http stuff in random places. diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go index 81206ea1cb6..a8b57361e6c 100644 --- a/libgo/go/net/net.go +++ b/libgo/go/net/net.go @@ -468,7 +468,7 @@ func (e *OpError) Error() string { var ( // aLongTimeAgo is a non-zero time, far in the past, used for // immediate cancelation of dials. - aLongTimeAgo = time.Unix(233431200, 0) + aLongTimeAgo = time.Unix(1, 0) // nonDeadline and noCancel are just zero values for // readability with functions taking too many parameters. diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go index a9cceecd2a8..f13635138a1 100644 --- a/libgo/go/os/exec/exec_test.go +++ b/libgo/go/os/exec/exec_test.go @@ -266,9 +266,13 @@ func TestStdinCloseRace(t *testing.T) { t.Fatalf("Start: %v", err) } go func() { - if err := cmd.Process.Kill(); err != nil { - t.Errorf("Kill: %v", err) - } + // We don't check the error return of Kill. It is + // possible that the process has already exited, in + // which case Kill will return an error "process + // already finished". The purpose of this test is to + // see whether the race detector reports an error; it + // doesn't matter whether this Kill succeeds or not. + cmd.Process.Kill() }() go func() { // Send the wrong string, so that the child fails even diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index 859de7c8670..3686167ed42 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -1681,6 +1681,11 @@ func (p Point) GCMethod(k int) int { } // This will be index 3. +func (p Point) NoArgs() { + // Exercise no-argument/no-result paths. +} + +// This will be index 4. func (p Point) TotalDist(points ...Point) int { tot := 0 for _, q := range points { @@ -1709,6 +1714,15 @@ func TestMethod(t *testing.T) { t.Errorf("Type MethodByName returned %d; want 275", i) } + m, ok = TypeOf(p).MethodByName("NoArgs") + if !ok { + t.Fatalf("method by name failed") + } + n := len(m.Func.Call([]Value{ValueOf(p)})) + if n != 0 { + t.Errorf("NoArgs returned %d values; want 0", n) + } + i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int() if i != 300 { t.Errorf("Pointer Type Method returned %d; want 300", i) @@ -1723,6 +1737,15 @@ func TestMethod(t *testing.T) { t.Errorf("Pointer Type MethodByName returned %d; want 325", i) } + m, ok = TypeOf(&p).MethodByName("NoArgs") + if !ok { + t.Fatalf("method by name failed") + } + n = len(m.Func.Call([]Value{ValueOf(&p)})) + if n != 0 { + t.Errorf("NoArgs returned %d values; want 0", n) + } + // Curried method of value. tfunc := TypeOf((func(int) int)(nil)) v := ValueOf(p).Method(1) @@ -1741,6 +1764,8 @@ func TestMethod(t *testing.T) { if i != 375 { t.Errorf("Value MethodByName returned %d; want 375", i) } + v = ValueOf(p).MethodByName("NoArgs") + v.Call(nil) // Curried method of pointer. v = ValueOf(&p).Method(1) @@ -1759,6 +1784,8 @@ func TestMethod(t *testing.T) { if i != 425 { t.Errorf("Pointer Value MethodByName returned %d; want 425", i) } + v = ValueOf(&p).MethodByName("NoArgs") + v.Call(nil) // Curried method of interface value. // Have to wrap interface value in a struct to get at it. @@ -1808,6 +1835,9 @@ func TestMethodValue(t *testing.T) { if i != 275 { t.Errorf("Value MethodByName returned %d; want 275", i) } + v = ValueOf(p).MethodByName("NoArgs") + ValueOf(v.Interface()).Call(nil) + v.Interface().(func())() // Curried method of pointer. v = ValueOf(&p).Method(1) @@ -1826,6 +1856,9 @@ func TestMethodValue(t *testing.T) { if i != 325 { t.Errorf("Pointer Value MethodByName returned %d; want 325", i) } + v = ValueOf(&p).MethodByName("NoArgs") + ValueOf(v.Interface()).Call(nil) + v.Interface().(func())() // Curried method of pointer to pointer. pp := &p @@ -1881,7 +1914,7 @@ func TestVariadicMethodValue(t *testing.T) { // Curried method of value. tfunc := TypeOf((func(...Point) int)(nil)) - v := ValueOf(p).Method(3) + v := ValueOf(p).Method(4) if tt := v.Type(); tt != tfunc { t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc) } diff --git a/libgo/go/runtime/crash_unix_test.go b/libgo/go/runtime/crash_unix_test.go index 97deed8b9d9..182c84b6392 100644 --- a/libgo/go/runtime/crash_unix_test.go +++ b/libgo/go/runtime/crash_unix_test.go @@ -9,6 +9,7 @@ package runtime_test import ( "bytes" "internal/testenv" + "io" "io/ioutil" "os" "os/exec" @@ -153,6 +154,78 @@ func loop(i int, c chan bool) { } ` +func TestPanicSystemstack(t *testing.T) { + // Test that GOTRACEBACK=crash prints both the system and user + // stack of other threads. + + // The GOTRACEBACK=crash handler takes 0.1 seconds even if + // it's not writing a core file and potentially much longer if + // it is. Skip in short mode. + if testing.Short() { + t.Skip("Skipping in short mode (GOTRACEBACK=crash is slow)") + } + + t.Parallel() + cmd := exec.Command(os.Args[0], "testPanicSystemstackInternal") + cmd = testEnv(cmd) + cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") + pr, pw, err := os.Pipe() + if err != nil { + t.Fatal("creating pipe: ", err) + } + cmd.Stderr = pw + if err := cmd.Start(); err != nil { + t.Fatal("starting command: ", err) + } + defer cmd.Process.Wait() + defer cmd.Process.Kill() + if err := pw.Close(); err != nil { + t.Log("closing write pipe: ", err) + } + defer pr.Close() + + // Wait for "x\nx\n" to indicate readiness. + buf := make([]byte, 4) + _, err = io.ReadFull(pr, buf) + if err != nil || string(buf) != "x\nx\n" { + t.Fatal("subprocess failed; output:\n", string(buf)) + } + + // Send SIGQUIT. + if err := cmd.Process.Signal(syscall.SIGQUIT); err != nil { + t.Fatal("signaling subprocess: ", err) + } + + // Get traceback. + tb, err := ioutil.ReadAll(pr) + if err != nil { + t.Fatal("reading traceback from pipe: ", err) + } + + // Traceback should have two testPanicSystemstackInternal's + // and two blockOnSystemStackInternal's. + if bytes.Count(tb, []byte("testPanicSystemstackInternal")) != 2 { + t.Fatal("traceback missing user stack:\n", string(tb)) + } else if bytes.Count(tb, []byte("blockOnSystemStackInternal")) != 2 { + t.Fatal("traceback missing system stack:\n", string(tb)) + } +} + +func init() { + if len(os.Args) >= 2 && os.Args[1] == "testPanicSystemstackInternal" { + // Get two threads running on the system stack with + // something recognizable in the stack trace. + runtime.GOMAXPROCS(2) + go testPanicSystemstackInternal() + testPanicSystemstackInternal() + } +} + +func testPanicSystemstackInternal() { + runtime.BlockOnSystemStack() + os.Exit(1) // Should be unreachable. +} + func TestSignalExitStatus(t *testing.T) { testenv.MustHaveGoBuild(t) exe, err := buildTestProg(t, "testprog") diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go index fcc1e6199a4..cc4b188b60c 100644 --- a/libgo/go/runtime/export_test.go +++ b/libgo/go/runtime/export_test.go @@ -243,3 +243,16 @@ func CountPagesInUse() (pagesInUse, counted uintptr) { return } */ + +// BlockOnSystemStack switches to the system stack, prints "x\n" to +// stderr, and blocks in a stack containing +// "runtime.blockOnSystemStackInternal". +func BlockOnSystemStack() { + systemstack(blockOnSystemStackInternal) +} + +func blockOnSystemStackInternal() { + print("x\n") + lock(&deadlock) + lock(&deadlock) +} diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go index a41cfc81181..99c0f11930f 100644 --- a/libgo/go/runtime/runtime1.go +++ b/libgo/go/runtime/runtime1.go @@ -280,6 +280,12 @@ func check() { throw("atomicor8") } + m = [4]byte{0xff, 0xff, 0xff, 0xff} + atomic.And8(&m[1], 0x1) + if m[0] != 0xff || m[1] != 0x1 || m[2] != 0xff || m[3] != 0xff { + throw("atomicand8") + } + *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0) if j == j { throw("float64nan") diff --git a/libgo/go/runtime/sema.go b/libgo/go/runtime/sema.go index 576a1fb7a20..37318ff9d55 100644 --- a/libgo/go/runtime/sema.go +++ b/libgo/go/runtime/sema.go @@ -171,6 +171,7 @@ func semrelease(addr *uint32) { for x := root.head; x != nil; x = x.next { if x.elem == unsafe.Pointer(addr) { x.acquiretime = t0 + break } } mutexevent(t0-s.acquiretime, 3) diff --git a/libgo/go/text/template/multi_test.go b/libgo/go/text/template/multi_test.go index 8142f008fdf..5d8c08f06f1 100644 --- a/libgo/go/text/template/multi_test.go +++ b/libgo/go/text/template/multi_test.go @@ -363,7 +363,7 @@ func TestEmptyTemplate(t *testing.T) { {[]string{"{{.}}", ""}, "twice", ""}, } - for _, c := range cases { + for i, c := range cases { root := New("root") var ( @@ -378,10 +378,43 @@ func TestEmptyTemplate(t *testing.T) { } buf := &bytes.Buffer{} if err := m.Execute(buf, c.in); err != nil { - t.Fatal(err) + t.Error(i, err) + continue } if buf.String() != c.want { t.Errorf("expected string %q: got %q", c.want, buf.String()) } } } + +// Issue 19249 was a regression in 1.8 caused by the handling of empty +// templates added in that release, which got different answers depending +// on the order templates appeared in the internal map. +func TestIssue19294(t *testing.T) { + // The empty block in "xhtml" should be replaced during execution + // by the contents of "stylesheet", but if the internal map associating + // names with templates is built in the wrong order, the empty block + // looks non-empty and this doesn't happen. + var inlined = map[string]string{ + "stylesheet": `{{define "stylesheet"}}stylesheet{{end}}`, + "xhtml": `{{block "stylesheet" .}}{{end}}`, + } + all := []string{"stylesheet", "xhtml"} + for i := 0; i < 100; i++ { + res, err := New("title.xhtml").Parse(`{{template "xhtml" .}}`) + if err != nil { + t.Fatal(err) + } + for _, name := range all { + _, err := res.New(name).Parse(inlined[name]) + if err != nil { + t.Fatal(err) + } + } + var buf bytes.Buffer + res.Execute(&buf, 0) + if buf.String() != "stylesheet" { + t.Fatalf("iteration %d: got %q; expected %q", i, buf.String(), "stylesheet") + } + } +} diff --git a/libgo/go/text/template/template.go b/libgo/go/text/template/template.go index b6fceb1795c..3b4f34b4db0 100644 --- a/libgo/go/text/template/template.go +++ b/libgo/go/text/template/template.go @@ -127,7 +127,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error // Even if nt == t, we need to install it in the common.tmpl map. if replace, err := t.associate(nt, tree); err != nil { return nil, err - } else if replace { + } else if replace || nt.Tree == nil { nt.Tree = tree } return nt, nil @@ -215,7 +215,7 @@ func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) { if new.common != t.common { panic("internal error: associate not common") } - if t.tmpl[new.name] != nil && parse.IsEmptyTree(tree.Root) && t.Tree != nil { + if old := t.tmpl[new.name]; old != nil && parse.IsEmptyTree(tree.Root) && old.Tree != nil { // If a template by that name exists, // don't replace it with an empty template. return false, nil |