libgo: update to Go 1.8.1 release
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 17 Apr 2017 22:10:58 +0000 (22:10 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 17 Apr 2017 22:10:58 +0000 (22:10 +0000)
    Reviewed-on: https://go-review.googlesource.com/40775

From-SVN: r246957

24 files changed:
libgo/MERGE
libgo/VERSION
libgo/go/cmd/go/go_test.go
libgo/go/cmd/go/pkg.go
libgo/go/cmd/go/test.go
libgo/go/crypto/tls/common.go
libgo/go/crypto/tls/tls_test.go
libgo/go/encoding/xml/marshal_test.go
libgo/go/encoding/xml/read.go
libgo/go/encoding/xml/xml_test.go
libgo/go/image/png/reader.go
libgo/go/image/png/reader_test.go
libgo/go/internal/testenv/testenv.go
libgo/go/internal/testenv/testenv_cgo.go [new file with mode: 0644]
libgo/go/net/http/http.go
libgo/go/net/net.go
libgo/go/os/exec/exec_test.go
libgo/go/reflect/all_test.go
libgo/go/runtime/crash_unix_test.go
libgo/go/runtime/export_test.go
libgo/go/runtime/runtime1.go
libgo/go/runtime/sema.go
libgo/go/text/template/multi_test.go
libgo/go/text/template/template.go

index 16f346a2b8e6832e3f4eb9b29ad7203bc055e5ed..a5808db54ff4c4fcb01fae79c808159cd73385c6 100644 (file)
@@ -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.
index 436edd93930654ba96603e796227c537f3534a52..dce1d463ba144a2d58ae0d9a336b2796938d8f15 100644 (file)
@@ -1 +1 @@
-go1.8
+go1.8.1
index 56de65ce55ae3d65e6bf0db6d7538a2d022572fa..fa78578d1215142efbe3a31ee451e12888340c57 100644 (file)
@@ -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")
index 61c1b9960ead782fe75cd592427472da62caaab5..f0dc95670f99289821a32cc124db1cff0ef05376 100644 (file)
@@ -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,
index 5c13b653f014f689577be89b148d1e0156d2515e..12990feb43c97e5a6d0e391ec79db79f9c703df8 100644 (file)
@@ -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 {
index 276d1761ea04033672d5ad0354327fa36bd34a4c..de833a905637259351433976f1c06b36d713a5f9 100644 (file)
@@ -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,
index 8933f4f2015e1be457e55d2ad7fb8e66e23cb460..86812f0c974cf36076d133e46106596f668f9654 100644 (file)
@@ -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()
index 5ec7ececa4d039331bfec347269bccf2e2b71e31..0126146d332e0e098450074325228a84401e1e40 100644 (file)
@@ -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")
        }
 }
index 5a89d5f504aeba6cea7579583729a4684be6a44d..799b57e9d1515a09c81d8f8932f21871bf7c567c 100644 (file)
@@ -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 (
index dad6ed98c1bffe1f45b82001b14184937c524112..f43a5e7eebc83cd9f6592b7ac5a9f7017bcfb9d4 100644 (file)
@@ -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)
+                       }
+               }
+       }
+}
index 32f78f0ffe84c0ccef600bad00c556264f35f7be..8299df56735df09e27669143245bd9a365c3e67a 100644 (file)
@@ -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:
index b9e9f4d02c671e652dff9f2345fdd8d3c8d8e26f..503b5dc567b27df9d58385464feb726bd2d2bb35 100644 (file)
@@ -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)
+       }
+}
index fdba8b25c3a6ca670eeba8164f49ce206ae73675..71a692b367e239d8771e7f5a655281c8d3472263 100644 (file)
@@ -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 (file)
index 0000000..e3d4d16
--- /dev/null
@@ -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
+}
index 826f7ff3da5bd01165668e0c8267aac79281c25f..b95ca89f4094c5f04445c83ad5c3d9069cc777f9 100644 (file)
@@ -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.
index 81206ea1cb6c837cad43ab04d0f5e8f707900595..a8b57361e6c6b65b956be90b9b32af97b2c213bd 100644 (file)
@@ -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.
index a9cceecd2a890e9fa102cac8b754558a0d14fd61..f13635138a1bef98f786a3aff3444dfca8037174 100644 (file)
@@ -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
index 859de7c86706c0bae9ad5e27adc10df1394f7fe3..3686167ed42cff52e1104337f8010b0db919f069 100644 (file)
@@ -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)
        }
index 97deed8b9d97ec44a7937ef64f5ae6a7828d4d18..182c84b6392c661534049b574ccb7efa4487197f 100644 (file)
@@ -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")
index fcc1e6199a452aaab1c09867dc3905858b4abff0..cc4b188b60c0a4502f9162b943a992b96e160fef 100644 (file)
@@ -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)
+}
index a41cfc81181722d482f206776f6b5b3b69607a5c..99c0f11930fdfcca231099a61a5d7fc339c06798 100644 (file)
@@ -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")
index 576a1fb7a207f56eb08a6e6ff67f113535e2b291..37318ff9d55cd387a6617532e89c9a8eb6c87337 100644 (file)
@@ -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)
index 8142f008fdf4602162c80cc86d21b949ebbe6fab..5d8c08f06f1ceaf92586c61b3a544163dddd05c4 100644 (file)
@@ -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")
+               }
+       }
+}
index b6fceb1795c2f52889f9b13983bd46be7598e625..3b4f34b4db0efe37febe0c637d4a2a8f06124562 100644 (file)
@@ -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