-392e9b3da473070f24dbe6c12c282a0e06e73b54
+a69f7c05f1880bb90544fb0c3577109cb1d7f3ab
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
-0380c9ad38843d523d9c9804fe300cb7edd7cd3c
+ac02fdec7cd16ea8d3de1fc33def9cfabec5170d
The first line of this file holds the git revision number of the
last merge done from the master library sources.
var foldPath = make(map[string]string)
+// DefaultExecName returns the default executable name
+// for a package with the import path importPath.
+//
+// The default executable name is the last element of the import path.
+// In module-aware mode, an additional rule is used. If the last element
+// is a vN path element specifying the major version, then the second last
+// element of the import path is used instead.
+func DefaultExecName(importPath string) string {
+ _, elem := pathpkg.Split(importPath)
+ if cfg.ModulesEnabled {
+ // If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
+ // See golang.org/issue/24667.
+ isVersion := func(v string) bool {
+ if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
+ return false
+ }
+ for i := 2; i < len(v); i++ {
+ if c := v[i]; c < '0' || '9' < c {
+ return false
+ }
+ }
+ return true
+ }
+ if isVersion(elem) {
+ _, elem = pathpkg.Split(pathpkg.Dir(importPath))
+ }
+ }
+ return elem
+}
+
// load populates p using information from bp, err, which should
// be the result of calling build.Context.Import.
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
}
_, elem := filepath.Split(p.Dir)
if cfg.ModulesEnabled {
- // NOTE(rsc): Using p.ImportPath instead of p.Dir
+ // NOTE(rsc,dmitshur): Using p.ImportPath instead of p.Dir
// makes sure we install a package in the root of a
// cached module directory as that package name
// not name@v1.2.3.
// even for non-module-enabled code,
// but I'm not brave enough to change the
// non-module behavior this late in the
- // release cycle. Maybe for Go 1.12.
+ // release cycle. Can be done for Go 1.13.
// See golang.org/issue/26869.
- _, elem = pathpkg.Split(p.ImportPath)
-
- // If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
- // See golang.org/issue/24667.
- isVersion := func(v string) bool {
- if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
- return false
- }
- for i := 2; i < len(v); i++ {
- if c := v[i]; c < '0' || '9' < c {
- return false
- }
- }
- return true
- }
- if isVersion(elem) {
- _, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
- }
+ elem = DefaultExecName(p.ImportPath)
}
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
pmain.Imports = pmain.Imports[:w]
pmain.Internal.RawImports = str.StringList(pmain.Imports)
- if ptest != p {
- // We have made modifications to the package p being tested
- // and are rebuilding p (as ptest).
- // Arrange to rebuild all packages q such that
- // the test depends on q and q depends on p.
- // This makes sure that q sees the modifications to p.
- // Strictly speaking, the rebuild is only necessary if the
- // modifications to p change its export metadata, but
- // determining that is a bit tricky, so we rebuild always.
- recompileForTest(pmain, p, ptest, pxtest)
- }
+ // Replace pmain's transitive dependencies with test copies, as necessary.
+ recompileForTest(pmain, p, ptest, pxtest)
// Should we apply coverage analysis locally,
// only for this package and only for this test?
return stk
}
+// recompileForTest copies and replaces certain packages in pmain's dependency
+// graph. This is necessary for two reasons. First, if ptest is different than
+// preal, packages that import the package under test should get ptest instead
+// of preal. This is particularly important if pxtest depends on functionality
+// exposed in test sources in ptest. Second, if there is a main package
+// (other than pmain) anywhere, we need to clear p.Internal.BuildInfo in
+// the test copy to prevent link conflicts. This may happen if both -coverpkg
+// and the command line patterns include multiple main packages.
func recompileForTest(pmain, preal, ptest, pxtest *Package) {
// The "test copy" of preal is ptest.
// For each package that depends on preal, make a "test copy"
// Don't compile build info from a main package. This can happen
// if -coverpkg patterns include main packages, since those packages
- // are imported by pmain.
+ // are imported by pmain. See golang.org/issue/30907.
if p.Internal.BuildInfo != "" && p != pmain {
split()
}
if p.ImportPath == "command-line-arguments" {
elem = p.Name
} else {
- _, elem = path.Split(p.ImportPath)
+ elem = load.DefaultExecName(p.ImportPath)
}
testBinary := elem + ".test"
"go/build"
"os"
"os/exec"
- "path"
"path/filepath"
"runtime"
"strings"
pkgs := load.PackagesForBuild(args)
if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
- _, cfg.BuildO = path.Split(pkgs[0].ImportPath)
+ cfg.BuildO = load.DefaultExecName(pkgs[0].ImportPath)
cfg.BuildO += cfg.ExeSuffix
}
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
// Compute file 'go build' would have created.
// If it exists and is an executable file, remove it.
- _, targ := filepath.Split(pkgs[0].ImportPath)
+ targ := load.DefaultExecName(pkgs[0].ImportPath)
targ += cfg.ExeSuffix
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
fi, err := os.Stat(targ)
if p.Internal.CoverMode != "" {
fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover"))
}
+ fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo)
// Configuration specific to compiler toolchain.
switch cfg.BuildToolchainName {
func main() {
println(quote.Hello())
}
+-- fortune_test.go --
+package main
+
+import "testing"
+
+func TestFortuneV2(t *testing.T) {}
--- /dev/null
+# This test checks that multiple main packages can be tested
+# with -coverpkg=all without duplicate symbol errors.
+# Verifies golang.org/issue/30374.
+
+env GO111MODULE=on
+
+[short] skip
+
+go test -coverpkg=all ./...
+
+-- go.mod --
+module example.com/cov
+
+-- mainonly/mainonly.go --
+package main
+
+func main() {}
+
+-- mainwithtest/mainwithtest.go --
+package main
+
+func main() {}
+
+func Foo() {}
+
+-- mainwithtest/mainwithtest_test.go --
+package main
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+ Foo()
+}
+
+-- xtest/x.go --
+package x
+
+-- xtest/x_test.go --
+package x_test
+
+import "testing"
+
+func TestX(t *testing.T) {}
return 0, err
}
defer fd.writeUnlock()
+ if fd.isFile || fd.isDir || fd.isConsole {
+ fd.l.Lock()
+ defer fd.l.Unlock()
+ }
ntotal := 0
for len(buf) > 0 {
var n int
var err error
if fd.isFile || fd.isDir || fd.isConsole {
- fd.l.Lock()
- defer fd.l.Unlock()
if fd.isConsole {
n, err = fd.writeConsole(b)
} else {
latency: flushInterval,
}
defer mlw.stop()
+
+ // set up initial timer so headers get flushed even if body writes are delayed
+ mlw.flushPending = true
+ mlw.t = time.AfterFunc(flushInterval, mlw.delayedFlush)
+
dst = mlw
}
}
import (
"bufio"
"bytes"
+ "context"
"errors"
"fmt"
"io"
}
}
+func TestReverseProxyFlushIntervalHeaders(t *testing.T) {
+ const expected = "hi"
+ stopCh := make(chan struct{})
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("MyHeader", expected)
+ w.WriteHeader(200)
+ w.(http.Flusher).Flush()
+ <-stopCh
+ }))
+ defer backend.Close()
+ defer close(stopCh)
+
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.FlushInterval = time.Microsecond
+
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+
+ req, _ := http.NewRequest("GET", frontend.URL, nil)
+ req.Close = true
+
+ ctx, cancel := context.WithTimeout(req.Context(), 10*time.Second)
+ defer cancel()
+ req = req.WithContext(ctx)
+
+ res, err := frontend.Client().Do(req)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+
+ if res.Header.Get("MyHeader") != expected {
+ t.Errorf("got header %q; expected %q", res.Header.Get("MyHeader"), expected)
+ }
+}
+
func TestReverseProxyCancelation(t *testing.T) {
const backendResponse = "I am the backend"
// only the values in context. See Issue 28600.
lookupGroupCtx, lookupGroupCancel := context.WithCancel(withUnexpiredValuesPreserved(ctx))
+ lookupKey := network + "\000" + host
dnsWaitGroup.Add(1)
- ch, called := r.getLookupGroup().DoChan(host, func() (interface{}, error) {
+ ch, called := r.getLookupGroup().DoChan(lookupKey, func() (interface{}, error) {
defer dnsWaitGroup.Done()
return testHookLookupIP(lookupGroupCtx, resolverFunc, network, host)
})
// let the lookup continue uncanceled, and let later
// lookups with the same key share the result.
// See issues 8602, 20703, 22724.
- if r.getLookupGroup().ForgetUnshared(host) {
+ if r.getLookupGroup().ForgetUnshared(lookupKey) {
lookupGroupCancel()
} else {
go func() {
"sort"
"strings"
"sync"
+ "sync/atomic"
"testing"
"time"
)
}
}
-var lookupGooglePublicDNSAddrTests = []struct {
- addr, name string
-}{
- {"8.8.8.8", ".google.com."},
- {"8.8.4.4", ".google.com."},
-
- {"2001:4860:4860::8888", ".google.com."},
- {"2001:4860:4860::8844", ".google.com."},
+var lookupGooglePublicDNSAddrTests = []string{
+ "8.8.8.8",
+ "8.8.4.4",
+ "2001:4860:4860::8888",
+ "2001:4860:4860::8844",
}
func TestLookupGooglePublicDNSAddr(t *testing.T) {
defer dnsWaitGroup.Wait()
- for _, tt := range lookupGooglePublicDNSAddrTests {
- names, err := LookupAddr(tt.addr)
+ for _, ip := range lookupGooglePublicDNSAddrTests {
+ names, err := LookupAddr(ip)
if err != nil {
t.Fatal(err)
}
t.Error("got no record")
}
for _, name := range names {
- if !strings.HasSuffix(name, tt.name) {
- t.Errorf("got %s; want a record containing %s", name, tt.name)
+ if !strings.HasSuffix(name, ".google.com.") && !strings.HasSuffix(name, ".google.") {
+ t.Errorf("got %q; want a record ending in .google.com. or .google.", name)
}
}
}
t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
} else {
for _, name := range names {
- if !strings.HasSuffix(name, ".google.com.") {
- t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
+ if !strings.HasSuffix(name, ".google.com.") && !strings.HasSuffix(name, ".google.") {
+ t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com or .google with trailing dot (mode=%v)", names, mode)
break
}
}
}
}
+// Issue 30521: The lookup group should call the resolver for each network.
+func TestLookupIPAddrConcurrentCallsForNetworks(t *testing.T) {
+ origTestHookLookupIP := testHookLookupIP
+ defer func() { testHookLookupIP = origTestHookLookupIP }()
+
+ queries := [][]string{
+ {"udp", "golang.org"},
+ {"udp4", "golang.org"},
+ {"udp6", "golang.org"},
+ {"udp", "golang.org"},
+ {"udp", "golang.org"},
+ }
+ results := map[[2]string][]IPAddr{
+ {"udp", "golang.org"}: {
+ {IP: IPv4(127, 0, 0, 1)},
+ {IP: IPv6loopback},
+ },
+ {"udp4", "golang.org"}: {
+ {IP: IPv4(127, 0, 0, 1)},
+ },
+ {"udp6", "golang.org"}: {
+ {IP: IPv6loopback},
+ },
+ }
+ calls := int32(0)
+ waitCh := make(chan struct{})
+ testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
+ // We'll block until this is called one time for each different
+ // expected result. This will ensure that the lookup group would wait
+ // for the existing call if it was to be reused.
+ if atomic.AddInt32(&calls, 1) == int32(len(results)) {
+ close(waitCh)
+ }
+ select {
+ case <-waitCh:
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ return results[[2]string{network, host}], nil
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ wg := sync.WaitGroup{}
+ for _, q := range queries {
+ network := q[0]
+ host := q[1]
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ gotIPs, err := DefaultResolver.lookupIPAddr(ctx, network, host)
+ if err != nil {
+ t.Errorf("lookupIPAddr(%v, %v): unexpected error: %v", network, host, err)
+ }
+ wantIPs := results[[2]string{network, host}]
+ if !reflect.DeepEqual(gotIPs, wantIPs) {
+ t.Errorf("lookupIPAddr(%v, %v): mismatched IPAddr results\n\tGot: %v\n\tWant: %v", network, host, gotIPs, wantIPs)
+ }
+ }()
+ }
+ wg.Wait()
+}
+
func TestWithUnexpiredValuesPreserved(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
// It removes everything it can but returns the first error
// it encounters. If the path does not exist, RemoveAll
// returns nil (no error).
+// If there is an error, it will be of type *PathError.
func RemoveAll(path string) error {
return removeAll(path)
}
// Remove leading directory path
for i--; i >= 0; i-- {
if path[i] == '/' {
- dirname = path[:i+1]
+ dirname = path[:i]
basename = path[i+1:]
break
}
}
defer parent.Close()
- return removeAllFrom(parent, base)
+ if err := removeAllFrom(parent, base); err != nil {
+ if pathErr, ok := err.(*PathError); ok {
+ pathErr.Path = parentDir + string(PathSeparator) + pathErr.Path
+ err = pathErr
+ }
+ return err
+ }
+ return nil
}
-func removeAllFrom(parent *File, path string) error {
+func removeAllFrom(parent *File, base string) error {
parentFd := int(parent.Fd())
// Simple case: if Unlink (aka remove) works, we're done.
- err := unix.Unlinkat(parentFd, path, 0)
+ err := unix.Unlinkat(parentFd, base, 0)
if err == nil || IsNotExist(err) {
return nil
}
// whose contents need to be removed.
// Otherwise just return the error.
if err != syscall.EISDIR && err != syscall.EPERM && err != syscall.EACCES {
- return err
+ return &PathError{"unlinkat", base, err}
}
// Is this a directory we need to recurse into?
var statInfo syscall.Stat_t
- statErr := unix.Fstatat(parentFd, path, &statInfo, unix.AT_SYMLINK_NOFOLLOW)
+ statErr := unix.Fstatat(parentFd, base, &statInfo, unix.AT_SYMLINK_NOFOLLOW)
if statErr != nil {
if IsNotExist(statErr) {
return nil
}
- return statErr
+ return &PathError{"fstatat", base, statErr}
}
if statInfo.Mode&syscall.S_IFMT != syscall.S_IFDIR {
- // Not a directory; return the error from the Remove.
- return err
+ // Not a directory; return the error from the unix.Unlinkat.
+ return &PathError{"unlinkat", base, err}
}
// Remove the directory's entries.
const request = 1024
// Open the directory to recurse into
- file, err := openFdAt(parentFd, path)
+ file, err := openFdAt(parentFd, base)
if err != nil {
if IsNotExist(err) {
return nil
}
- recurseErr = err
+ recurseErr = &PathError{"openfdat", base, err}
break
}
if IsNotExist(readErr) {
return nil
}
- return readErr
+ return &PathError{"readdirnames", base, readErr}
}
for _, name := range names {
err := removeAllFrom(file, name)
if err != nil {
+ if pathErr, ok := err.(*PathError); ok {
+ pathErr.Path = base + string(PathSeparator) + pathErr.Path
+ }
recurseErr = err
}
}
}
// Remove the directory itself.
- unlinkError := unix.Unlinkat(parentFd, path, unix.AT_REMOVEDIR)
+ unlinkError := unix.Unlinkat(parentFd, base, unix.AT_REMOVEDIR)
if unlinkError == nil || IsNotExist(unlinkError) {
return nil
}
if recurseErr != nil {
return recurseErr
}
- return unlinkError
+ return &PathError{"unlinkat", base, unlinkError}
}
// openFdAt opens path relative to the directory in fd.
continue
}
- return nil, &PathError{"openat", name, e}
+ return nil, e
}
if !supportsCloseOnExec {
}
// Issue #29983.
-func TestRemoveAllButReadOnly(t *testing.T) {
+func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
switch runtime.GOOS {
case "nacl", "js", "windows":
t.Skipf("skipping test on %s", runtime.GOOS)
defer Chmod(d, 0777)
}
- if err := RemoveAll(tempDir); err == nil {
+ err = RemoveAll(tempDir)
+ if err == nil {
t.Fatal("RemoveAll succeeded unexpectedly")
}
+ // The error should be of type *PathError.
+ // see issue 30491 for details.
+ if pathErr, ok := err.(*PathError); ok {
+ if g, w := pathErr.Path, filepath.Join(tempDir, "b", "y"); g != w {
+ t.Errorf("got %q, expected pathErr.path %q", g, w)
+ }
+ } else {
+ t.Errorf("got %T, expected *os.PathError", err)
+ }
+
for _, dir := range dirs {
_, err := Stat(filepath.Join(tempDir, dir))
if inReadonly(dir) {
if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
t.Skip("gdb test can fail with GOROOT_FINAL pending")
}
+ testenv.SkipFlaky(t, 31188)
checkLldbPython(t)
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
+//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
// An access token contains the security information for a logon session.
// The system creates an access token when a user logs on, and every