Commit ea250f56 by Ian Lance Taylor

libgo: update to Go 1.8.1 release

    
    Reviewed-on: https://go-review.googlesource.com/40775

From-SVN: r246957
parent 1adb82e1
cd6b6202dd1559b3ac63179b45f1833fcfbe7eca a4c18f063b6659079ca2848ca217a0587dabc001
The first line of this file holds the git revision number of the The first line of this file holds the git revision number of the
last merge done from the master library sources. last merge done from the master library sources.
...@@ -2227,6 +2227,24 @@ func TestTestEmpty(t *testing.T) { ...@@ -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) { func TestBuildDryRunWithCgo(t *testing.T) {
if !canCgo { if !canCgo {
t.Skip("skipping because cgo not enabled") t.Skip("skipping because cgo not enabled")
......
...@@ -970,10 +970,6 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package ...@@ -970,10 +970,6 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if p.Name == "main" && goarch == "arm" { if p.Name == "main" && goarch == "arm" {
importPaths = append(importPaths, "math") 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, // Runtime and its internal packages depend on runtime/internal/sys,
......
...@@ -548,6 +548,10 @@ func runTest(cmd *Command, args []string) { ...@@ -548,6 +548,10 @@ func runTest(cmd *Command, args []string) {
// Prepare build + run + print actions for all packages being tested. // Prepare build + run + print actions for all packages being tested.
for _, p := range pkgs { 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) buildTest, runTest, printTest, err := b.test(p)
if err != nil { if err != nil {
str := err.Error() str := err.Error()
...@@ -639,6 +643,23 @@ func runTest(cmd *Command, args []string) { ...@@ -639,6 +643,23 @@ func runTest(cmd *Command, args []string) {
b.do(root) 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 { func contains(x []string, s string) bool {
for _, t := range x { for _, t := range x {
if t == s { if t == s {
......
...@@ -563,6 +563,7 @@ func (c *Config) Clone() *Config { ...@@ -563,6 +563,7 @@ func (c *Config) Clone() *Config {
Certificates: c.Certificates, Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate, NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate, GetCertificate: c.GetCertificate,
GetClientCertificate: c.GetClientCertificate,
GetConfigForClient: c.GetConfigForClient, GetConfigForClient: c.GetConfigForClient,
VerifyPeerCertificate: c.VerifyPeerCertificate, VerifyPeerCertificate: c.VerifyPeerCertificate,
RootCAs: c.RootCAs, RootCAs: c.RootCAs,
......
...@@ -13,13 +13,11 @@ import ( ...@@ -13,13 +13,11 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"math" "math"
"math/rand"
"net" "net"
"os" "os"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"testing/quick"
"time" "time"
) )
...@@ -568,11 +566,50 @@ func TestConnCloseWrite(t *testing.T) { ...@@ -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 var c1 Config
v := reflect.ValueOf(&c1).Elem() v := reflect.ValueOf(&c1).Elem()
rnd := rand.New(rand.NewSource(time.Now().Unix()))
typ := v.Type() typ := v.Type()
for i := 0; i < typ.NumField(); i++ { for i := 0; i < typ.NumField(); i++ {
f := v.Field(i) f := v.Field(i)
...@@ -581,40 +618,49 @@ func TestClone(t *testing.T) { ...@@ -581,40 +618,49 @@ func TestClone(t *testing.T) {
continue continue
} }
// testing/quick can't handle functions or interfaces. // testing/quick can't handle functions or interfaces and so
fn := typ.Field(i).Name // isn't used here.
switch fn { switch fn := typ.Field(i).Name; fn {
case "Rand": case "Rand":
f.Set(reflect.ValueOf(io.Reader(os.Stdin))) f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
continue
case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate": case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate":
// DeepEqual can't compare functions. // DeepEqual can't compare functions. If you add a
continue // function field to this list, you must also change
// TestCloneFuncFields to ensure that the func field is
// cloned.
case "Certificates": case "Certificates":
f.Set(reflect.ValueOf([]Certificate{ f.Set(reflect.ValueOf([]Certificate{
{Certificate: [][]byte{{'b'}}}, {Certificate: [][]byte{{'b'}}},
})) }))
continue
case "NameToCertificate": case "NameToCertificate":
f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil})) f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil}))
continue
case "RootCAs", "ClientCAs": case "RootCAs", "ClientCAs":
f.Set(reflect.ValueOf(x509.NewCertPool())) f.Set(reflect.ValueOf(x509.NewCertPool()))
continue
case "ClientSessionCache": case "ClientSessionCache":
f.Set(reflect.ValueOf(NewLRUClientSessionCache(10))) f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
continue
case "KeyLogWriter": case "KeyLogWriter":
f.Set(reflect.ValueOf(io.Writer(os.Stdout))) f.Set(reflect.ValueOf(io.Writer(os.Stdout)))
continue case "NextProtos":
f.Set(reflect.ValueOf([]string{"a", "b"}))
} case "ServerName":
f.Set(reflect.ValueOf("b"))
q, ok := quick.Value(f.Type(), rnd) case "ClientAuth":
if !ok { f.Set(reflect.ValueOf(VerifyClientCertIfGiven))
t.Fatalf("quick.Value failed on field %s", fn) 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() c2 := c1.Clone()
......
...@@ -2428,7 +2428,10 @@ func TestIssue16158(t *testing.T) { ...@@ -2428,7 +2428,10 @@ func TestIssue16158(t *testing.T) {
err := Unmarshal([]byte(data), &struct { err := Unmarshal([]byte(data), &struct {
B byte `xml:"b,attr,omitempty"` 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")
} }
} }
...@@ -285,7 +285,8 @@ func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { ...@@ -285,7 +285,8 @@ func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
return nil return nil
} }
return copyValue(val, []byte(attr.Value)) copyValue(val, []byte(attr.Value))
return nil
} }
var ( var (
......
...@@ -797,3 +797,37 @@ func TestIssue12417(t *testing.T) { ...@@ -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)
}
}
}
}
...@@ -612,6 +612,11 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image ...@@ -612,6 +612,11 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
} }
} }
case cbG8: 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) copy(gray.Pix[pixOffset:], cdat)
pixOffset += gray.Stride pixOffset += gray.Stride
case cbGA8: case cbGA8:
......
...@@ -629,3 +629,13 @@ func BenchmarkDecodeRGB(b *testing.B) { ...@@ -629,3 +629,13 @@ func BenchmarkDecodeRGB(b *testing.B) {
func BenchmarkDecodeInterlacing(b *testing.B) { func BenchmarkDecodeInterlacing(b *testing.B) {
benchmarkDecode(b, "testdata/benchRGB-interlace.png", 4) 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)
}
}
...@@ -141,6 +141,15 @@ func MustHaveExternalNetwork(t *testing.T) { ...@@ -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. // HasSymlink reports whether the current system can use os.Symlink.
func HasSymlink() bool { func HasSymlink() bool {
ok, _ := hasSymlink() ok, _ := hasSymlink()
......
// 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
}
...@@ -20,7 +20,7 @@ const maxInt64 = 1<<63 - 1 ...@@ -20,7 +20,7 @@ const maxInt64 = 1<<63 - 1
// aLongTimeAgo is a non-zero time, far in the past, used for // aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations. // 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 // TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places. // generic http stuff in random places.
......
...@@ -468,7 +468,7 @@ func (e *OpError) Error() string { ...@@ -468,7 +468,7 @@ func (e *OpError) Error() string {
var ( var (
// aLongTimeAgo is a non-zero time, far in the past, used for // aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of dials. // immediate cancelation of dials.
aLongTimeAgo = time.Unix(233431200, 0) aLongTimeAgo = time.Unix(1, 0)
// nonDeadline and noCancel are just zero values for // nonDeadline and noCancel are just zero values for
// readability with functions taking too many parameters. // readability with functions taking too many parameters.
......
...@@ -266,9 +266,13 @@ func TestStdinCloseRace(t *testing.T) { ...@@ -266,9 +266,13 @@ func TestStdinCloseRace(t *testing.T) {
t.Fatalf("Start: %v", err) t.Fatalf("Start: %v", err)
} }
go func() { go func() {
if err := cmd.Process.Kill(); err != nil { // We don't check the error return of Kill. It is
t.Errorf("Kill: %v", err) // 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() { go func() {
// Send the wrong string, so that the child fails even // Send the wrong string, so that the child fails even
......
...@@ -1681,6 +1681,11 @@ func (p Point) GCMethod(k int) int { ...@@ -1681,6 +1681,11 @@ func (p Point) GCMethod(k int) int {
} }
// This will be index 3. // 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 { func (p Point) TotalDist(points ...Point) int {
tot := 0 tot := 0
for _, q := range points { for _, q := range points {
...@@ -1709,6 +1714,15 @@ func TestMethod(t *testing.T) { ...@@ -1709,6 +1714,15 @@ func TestMethod(t *testing.T) {
t.Errorf("Type MethodByName returned %d; want 275", i) 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() i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()
if i != 300 { if i != 300 {
t.Errorf("Pointer Type Method returned %d; want 300", i) t.Errorf("Pointer Type Method returned %d; want 300", i)
...@@ -1723,6 +1737,15 @@ func TestMethod(t *testing.T) { ...@@ -1723,6 +1737,15 @@ func TestMethod(t *testing.T) {
t.Errorf("Pointer Type MethodByName returned %d; want 325", i) 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. // Curried method of value.
tfunc := TypeOf((func(int) int)(nil)) tfunc := TypeOf((func(int) int)(nil))
v := ValueOf(p).Method(1) v := ValueOf(p).Method(1)
...@@ -1741,6 +1764,8 @@ func TestMethod(t *testing.T) { ...@@ -1741,6 +1764,8 @@ func TestMethod(t *testing.T) {
if i != 375 { if i != 375 {
t.Errorf("Value MethodByName returned %d; want 375", i) t.Errorf("Value MethodByName returned %d; want 375", i)
} }
v = ValueOf(p).MethodByName("NoArgs")
v.Call(nil)
// Curried method of pointer. // Curried method of pointer.
v = ValueOf(&p).Method(1) v = ValueOf(&p).Method(1)
...@@ -1759,6 +1784,8 @@ func TestMethod(t *testing.T) { ...@@ -1759,6 +1784,8 @@ func TestMethod(t *testing.T) {
if i != 425 { if i != 425 {
t.Errorf("Pointer Value MethodByName returned %d; want 425", i) t.Errorf("Pointer Value MethodByName returned %d; want 425", i)
} }
v = ValueOf(&p).MethodByName("NoArgs")
v.Call(nil)
// Curried method of interface value. // Curried method of interface value.
// Have to wrap interface value in a struct to get at it. // Have to wrap interface value in a struct to get at it.
...@@ -1808,6 +1835,9 @@ func TestMethodValue(t *testing.T) { ...@@ -1808,6 +1835,9 @@ func TestMethodValue(t *testing.T) {
if i != 275 { if i != 275 {
t.Errorf("Value MethodByName returned %d; want 275", i) 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. // Curried method of pointer.
v = ValueOf(&p).Method(1) v = ValueOf(&p).Method(1)
...@@ -1826,6 +1856,9 @@ func TestMethodValue(t *testing.T) { ...@@ -1826,6 +1856,9 @@ func TestMethodValue(t *testing.T) {
if i != 325 { if i != 325 {
t.Errorf("Pointer Value MethodByName returned %d; want 325", i) 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. // Curried method of pointer to pointer.
pp := &p pp := &p
...@@ -1881,7 +1914,7 @@ func TestVariadicMethodValue(t *testing.T) { ...@@ -1881,7 +1914,7 @@ func TestVariadicMethodValue(t *testing.T) {
// Curried method of value. // Curried method of value.
tfunc := TypeOf((func(...Point) int)(nil)) tfunc := TypeOf((func(...Point) int)(nil))
v := ValueOf(p).Method(3) v := ValueOf(p).Method(4)
if tt := v.Type(); tt != tfunc { if tt := v.Type(); tt != tfunc {
t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc) t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc)
} }
......
...@@ -9,6 +9,7 @@ package runtime_test ...@@ -9,6 +9,7 @@ package runtime_test
import ( import (
"bytes" "bytes"
"internal/testenv" "internal/testenv"
"io"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
...@@ -153,6 +154,78 @@ func loop(i int, c chan bool) { ...@@ -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) { func TestSignalExitStatus(t *testing.T) {
testenv.MustHaveGoBuild(t) testenv.MustHaveGoBuild(t)
exe, err := buildTestProg(t, "testprog") exe, err := buildTestProg(t, "testprog")
......
...@@ -243,3 +243,16 @@ func CountPagesInUse() (pagesInUse, counted uintptr) { ...@@ -243,3 +243,16 @@ func CountPagesInUse() (pagesInUse, counted uintptr) {
return 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)
}
...@@ -280,6 +280,12 @@ func check() { ...@@ -280,6 +280,12 @@ func check() {
throw("atomicor8") 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) *(*uint64)(unsafe.Pointer(&j)) = ^uint64(0)
if j == j { if j == j {
throw("float64nan") throw("float64nan")
......
...@@ -171,6 +171,7 @@ func semrelease(addr *uint32) { ...@@ -171,6 +171,7 @@ func semrelease(addr *uint32) {
for x := root.head; x != nil; x = x.next { for x := root.head; x != nil; x = x.next {
if x.elem == unsafe.Pointer(addr) { if x.elem == unsafe.Pointer(addr) {
x.acquiretime = t0 x.acquiretime = t0
break
} }
} }
mutexevent(t0-s.acquiretime, 3) mutexevent(t0-s.acquiretime, 3)
......
...@@ -363,7 +363,7 @@ func TestEmptyTemplate(t *testing.T) { ...@@ -363,7 +363,7 @@ func TestEmptyTemplate(t *testing.T) {
{[]string{"{{.}}", ""}, "twice", ""}, {[]string{"{{.}}", ""}, "twice", ""},
} }
for _, c := range cases { for i, c := range cases {
root := New("root") root := New("root")
var ( var (
...@@ -378,10 +378,43 @@ func TestEmptyTemplate(t *testing.T) { ...@@ -378,10 +378,43 @@ func TestEmptyTemplate(t *testing.T) {
} }
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
if err := m.Execute(buf, c.in); err != nil { if err := m.Execute(buf, c.in); err != nil {
t.Fatal(err) t.Error(i, err)
continue
} }
if buf.String() != c.want { if buf.String() != c.want {
t.Errorf("expected string %q: got %q", c.want, buf.String()) 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")
}
}
}
...@@ -127,7 +127,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error ...@@ -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. // Even if nt == t, we need to install it in the common.tmpl map.
if replace, err := t.associate(nt, tree); err != nil { if replace, err := t.associate(nt, tree); err != nil {
return nil, err return nil, err
} else if replace { } else if replace || nt.Tree == nil {
nt.Tree = tree nt.Tree = tree
} }
return nt, nil return nt, nil
...@@ -215,7 +215,7 @@ func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) { ...@@ -215,7 +215,7 @@ func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
if new.common != t.common { if new.common != t.common {
panic("internal error: associate not 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, // If a template by that name exists,
// don't replace it with an empty template. // don't replace it with an empty template.
return false, nil return false, nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment