Skip to content

Commit 70be481

Browse files
author
Jay Conrod
committed
cmd/go: fix windows test failures
search.CleanPatterns now preserves backslash separators in absolute paths in Windows. These had resulted in inconsistent error messages. search.MatchPackagesInFS is now more accepting of patterns with backslashes. It was inconsistent before. Several tests are fixed to work with Windows (mostly to match slashes or backslashes). Fixes #25300 Change-Id: Ibbf9ccd145353f7e3d345205c6fcc01d7066d1c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/206144 Run-TryBot: Jay Conrod <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 275a7be commit 70be481

File tree

9 files changed

+130
-66
lines changed

9 files changed

+130
-66
lines changed

src/cmd/go/internal/modfetch/codehost/git_test.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,16 @@ func testMain(m *testing.M) int {
7878

7979
func testRepo(remote string) (Repo, error) {
8080
if remote == "localGitRepo" {
81-
return LocalGitRepo(filepath.ToSlash(localGitRepo))
81+
// Convert absolute path to file URL. LocalGitRepo will not accept
82+
// Windows absolute paths because they look like a host:path remote.
83+
// TODO(golang.org/issue/32456): use url.FromFilePath when implemented.
84+
var url string
85+
if strings.HasPrefix(localGitRepo, "/") {
86+
url = "file://" + localGitRepo
87+
} else {
88+
url = "file:///" + filepath.ToSlash(localGitRepo)
89+
}
90+
return LocalGitRepo(url)
8291
}
8392
kind := "git"
8493
for _, k := range []string{"hg"} {

src/cmd/go/internal/search/search.go

+40-24
Original file line numberDiff line numberDiff line change
@@ -125,32 +125,43 @@ func SetModRoot(dir string) {
125125
modRoot = dir
126126
}
127127

128-
// MatchPackagesInFS is like allPackages but is passed a pattern
129-
// beginning ./ or ../, meaning it should scan the tree rooted
130-
// at the given directory. There are ... in the pattern too.
131-
// (See go help packages for pattern syntax.)
128+
// MatchPackagesInFS is like MatchPackages but is passed a pattern that
129+
// begins with an absolute path or "./" or "../". On Windows, the pattern may
130+
// use slash or backslash separators or a mix of both.
131+
//
132+
// MatchPackagesInFS scans the tree rooted at the directory that contains the
133+
// first "..." wildcard and returns a match with packages that
132134
func MatchPackagesInFS(pattern string) *Match {
133135
m := &Match{
134136
Pattern: pattern,
135137
Literal: false,
136138
}
137139

140+
// Clean the path and create a matching predicate.
141+
// filepath.Clean removes "./" prefixes (and ".\" on Windows). We need to
142+
// preserve these, since they are meaningful in MatchPattern and in
143+
// returned import paths.
144+
cleanPattern := filepath.Clean(pattern)
145+
isLocal := strings.HasPrefix(pattern, "./") || (os.PathSeparator == '\\' && strings.HasPrefix(pattern, `.\`))
146+
prefix := ""
147+
if cleanPattern != "." && isLocal {
148+
prefix = "./"
149+
cleanPattern = "." + string(os.PathSeparator) + cleanPattern
150+
}
151+
slashPattern := filepath.ToSlash(cleanPattern)
152+
match := MatchPattern(slashPattern)
153+
138154
// Find directory to begin the scan.
139155
// Could be smarter but this one optimization
140156
// is enough for now, since ... is usually at the
141157
// end of a path.
142-
i := strings.Index(pattern, "...")
143-
dir, _ := path.Split(pattern[:i])
158+
i := strings.Index(cleanPattern, "...")
159+
dir, _ := filepath.Split(cleanPattern[:i])
144160

145161
// pattern begins with ./ or ../.
146162
// path.Clean will discard the ./ but not the ../.
147163
// We need to preserve the ./ for pattern matching
148164
// and in the returned import paths.
149-
prefix := ""
150-
if strings.HasPrefix(pattern, "./") {
151-
prefix = "./"
152-
}
153-
match := MatchPattern(pattern)
154165

155166
if modRoot != "" {
156167
abs, err := filepath.Abs(dir)
@@ -381,21 +392,26 @@ func CleanPatterns(patterns []string) []string {
381392
v = a[i:]
382393
}
383394

384-
// Arguments are supposed to be import paths, but
385-
// as a courtesy to Windows developers, rewrite \ to /
386-
// in command-line arguments. Handles .\... and so on.
387-
if filepath.Separator == '\\' {
388-
p = strings.ReplaceAll(p, `\`, `/`)
389-
}
395+
// Arguments may be either file paths or import paths.
396+
// As a courtesy to Windows developers, rewrite \ to /
397+
// in arguments that look like import paths.
398+
// Don't replace slashes in absolute paths.
399+
if filepath.IsAbs(p) {
400+
p = filepath.Clean(p)
401+
} else {
402+
if filepath.Separator == '\\' {
403+
p = strings.ReplaceAll(p, `\`, `/`)
404+
}
390405

391-
// Put argument in canonical form, but preserve leading ./.
392-
if strings.HasPrefix(p, "./") {
393-
p = "./" + path.Clean(p)
394-
if p == "./." {
395-
p = "."
406+
// Put argument in canonical form, but preserve leading ./.
407+
if strings.HasPrefix(p, "./") {
408+
p = "./" + path.Clean(p)
409+
if p == "./." {
410+
p = "."
411+
}
412+
} else {
413+
p = path.Clean(p)
396414
}
397-
} else {
398-
p = path.Clean(p)
399415
}
400416

401417
out = append(out, p+v)

src/cmd/go/testdata/script/build_trimpath.txt

+67-35
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,93 @@
11
[short] skip
2-
3-
env -r GOROOT_REGEXP=$GOROOT
4-
env -r WORK_REGEXP='$WORK' # don't expand $WORK; grep replaces $WORK in text before matching.
5-
env GOROOT GOROOT_REGEXP WORK WORK_REGEXP
2+
env GO111MODULE=on
63

74
# A binary built without -trimpath should contain the current workspace
85
# and GOROOT for debugging and stack traces.
96
cd a
10-
go build -o hello.exe hello.go
11-
grep -q $WORK_REGEXP hello.exe
12-
grep -q $GOROOT_REGEXP hello.exe
7+
go build -o $WORK/paths-a.exe paths.go
8+
exec $WORK/paths-a.exe $WORK/paths-a.exe
9+
stdout 'binary contains GOPATH: true'
10+
stdout 'binary contains GOROOT: true'
1311

1412
# A binary built with -trimpath should not contain the current workspace
1513
# or GOROOT.
16-
go build -trimpath -o hello.exe hello.go
17-
! grep -q $GOROOT_REGEXP hello.exe
18-
! grep -q $WORK_REGEXP hello.exe
14+
go build -trimpath -o $WORK/paths-a.exe paths.go
15+
exec $WORK/paths-a.exe $WORK/paths-a.exe
16+
stdout 'binary contains GOPATH: false'
17+
stdout 'binary contains GOROOT: false'
1918

2019
# A binary from an external module built with -trimpath should not contain
2120
# the current workspace or GOROOT.
2221
cd $WORK
23-
env GO111MODULE=on
2422
go get -trimpath rsc.io/fortune
25-
! grep -q $GOROOT_REGEXP $GOPATH/bin/fortune$GOEXE
26-
! grep -q $WORK_REGEXP $GOPATH/bin/fortune$GOEXE
23+
exec $WORK/paths-a.exe $GOPATH/bin/fortune$GOEXE
24+
stdout 'binary contains GOPATH: false'
25+
stdout 'binary contains GOROOT: false'
2726

2827
# Two binaries built from identical packages in different directories
2928
# should be identical.
30-
cd $GOPATH/src/a
31-
go build -trimpath -o $WORK/a-GOPATH.exe .
32-
cd $WORK/_alt/src/a
33-
go build -trimpath -o $WORK/a-alt.exe .
34-
cmp -q $WORK/a-GOPATH.exe $WORK/a-alt.exe
29+
# TODO(golang.org/issue/35435): at the moment, they are not.
30+
#mkdir $GOPATH/src/b
31+
#cp $GOPATH/src/a/go.mod $GOPATH/src/b/go.mod
32+
#cp $GOPATH/src/a/paths.go $GOPATH/src/b/paths.go
33+
#cd $GOPATH/src/b
34+
#go build -trimpath -o $WORK/paths-b.exe .
35+
#cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
3536

3637
[!exec:gccgo] stop
3738

38-
# Binaries built using gccgo should also be identical to each other.
39+
# A binary built with gccgo without -trimpath should contain the current
40+
# GOPATH and GOROOT.
3941
env GO111MODULE=off # The current released gccgo does not support builds in module mode.
4042
cd $GOPATH/src/a
41-
go build -compiler=gccgo -trimpath -o $WORK/gccgo-GOPATH.exe .
43+
go build -compiler=gccgo -o $WORK/gccgo-paths-a.exe .
44+
exec $WORK/gccgo-paths-a.exe $WORK/gccgo-paths-b.exe
45+
stdout 'binary contains GOPATH: true'
46+
stdout 'binary contains GOROOT: true'
4247

43-
env old_gopath=$GOPATH
44-
env GOPATH=$WORK/_alt
45-
cd $WORK/_alt/src/a
46-
go build -compiler=gccgo -trimpath -o $WORK/gccgo-alt.exe .
47-
cd $WORK
48-
! grep -q $GOROOT_REGEXP gccgo-GOPATH.exe
49-
! grep -q $WORK_REGEXP gccgo-GOPATH.exe
50-
cmp -q gccgo-GOPATH.exe gccgo-alt.exe
48+
# A binary built with gccgo with -trimpath should not contain GOPATH or GOROOT.
49+
go build -compiler=gccgo -trimpath -o $WORK/gccgo-paths-a.exe .
50+
exec $WORK/gccgo-paths-a.exe $WORK/gccgo-paths-b.exe
51+
stdout 'binary contains GOPATH: false'
52+
stdout 'binary contains GOROOT: false'
53+
54+
# Two binaries built from identical packages in different directories
55+
# should be identical.
56+
# TODO(golang.org/issue/35435): at the moment, they are not.
57+
#cd ../b
58+
#go build -compiler=gccgo -trimpath -o $WORK/gccgo-paths-b.exe .
59+
#cmp -q $WORK/gccgo-paths-a.exe $WORK/gccgo-paths-b.exe
5160

52-
-- $GOPATH/src/a/hello.go --
61+
-- $GOPATH/src/a/paths.go --
5362
package main
54-
func main() { println("hello") }
63+
64+
import (
65+
"bytes"
66+
"fmt"
67+
"io/ioutil"
68+
"log"
69+
"os"
70+
"path/filepath"
71+
)
72+
73+
func main() {
74+
exe := os.Args[1]
75+
data, err := ioutil.ReadFile(exe)
76+
if err != nil {
77+
log.Fatal(err)
78+
}
79+
80+
gopath := []byte(filepath.ToSlash(os.Getenv("GOPATH")))
81+
if len(gopath) == 0 {
82+
log.Fatal("GOPATH not set")
83+
}
84+
fmt.Printf("binary contains GOPATH: %v\n", bytes.Contains(data, gopath))
85+
86+
goroot := []byte(filepath.ToSlash(os.Getenv("GOROOT")))
87+
if len(goroot) == 0 {
88+
log.Fatal("GOROOT not set")
89+
}
90+
fmt.Printf("binary contains GOROOT: %v\n", bytes.Contains(data, goroot))
91+
}
5592
-- $GOPATH/src/a/go.mod --
5693
module example.com/a
57-
-- $WORK/_alt/src/a/hello.go --
58-
package main
59-
func main() { println("hello") }
60-
-- $WORK/_alt/src/a/go.mod --
61-
module example.com/a

src/cmd/go/testdata/script/mod_getx.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[short] skip
22
[!net] skip
3+
[!exec:git] skip
34

45
env GO111MODULE=on
56
env GOPROXY=direct

src/cmd/go/testdata/script/mod_list_dir.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ stdout ^math$
1212
go list -f '{{.ImportPath}}' .
1313
stdout ^x$
1414
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/[email protected]
15-
stderr '^can.t load package: package '$WORK'[/\\]gopath/pkg/mod/rsc.io/[email protected]: can only use path@version syntax with .go get.'
15+
stderr '^can.t load package: package '$WORK'[/\\]gopath[/\\]pkg[/\\]mod[/\\]rsc.io[/\\][email protected]: can only use path@version syntax with .go get.'
1616

1717
go list -e -f '{{with .Error}}{{.}}{{end}}' $GOPATH/pkg/mod/rsc.io/[email protected]
18-
stdout '^package '$WORK'[/\\]gopath/pkg/mod/rsc.io/[email protected]: can only use path@version syntax with .go get.'
18+
stdout '^package '$WORK'[/\\]gopath[/\\]pkg[/\\]mod[/\\]rsc.io[/\\][email protected]: can only use path@version syntax with .go get.'
1919
go mod download rsc.io/[email protected]
2020
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/[email protected]
2121
stdout '^rsc.io/quote$'

src/cmd/go/testdata/script/mod_prefer_compatible.txt

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ stdout '^github.com/russross/blackfriday v1\.'
3434
# order to determine whether it contains a go.mod file, and part of the point of
3535
# the proxy is to avoid fetching unnecessary data.)
3636

37+
[!exec:git] stop
3738
env GOPROXY=direct
3839

3940
go list -versions -m github.com/russross/blackfriday github.com/russross/blackfriday

src/cmd/go/testdata/script/mod_sumdb_file_path.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ env GOPATH=$WORK/gopath1
1313
[windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org
1414
[!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org
1515
! go get -d golang.org/x/[email protected]
16-
stderr '^go get golang.org/x/[email protected]: golang.org/x/[email protected]: verifying module: golang.org/x/[email protected]: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/[email protected]: (no such file or directory|.*cannot find the file specified.*)'
16+
stderr '^go get golang.org/x/[email protected]: golang.org/x/[email protected]: verifying module: golang.org/x/[email protected]: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/[email protected]: (no such file or directory|.*cannot find the path specified.*)'
1717

1818
# If the proxy does not claim to support the database,
1919
# checksum verification should fall through to the next proxy,

src/cmd/go/testdata/script/mod_vendor_auto.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ stdout '^'$WORK'[/\\]auto[/\\]replacement-version$'
6262
go mod edit -go=1.14
6363

6464
! go list -f {{.Dir}} -tags tools all
65-
stderr '^go: inconsistent vendoring in '$WORK/auto':$'
65+
stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
6666
stderr '^\texample.com/[email protected]: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt'
6767
stderr '^\texample.com/unused: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
6868
stderr '^\texample.com/[email protected]: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
@@ -131,7 +131,7 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
131131
cp go.mod.orig go.mod
132132
go mod edit -go=1.14
133133
! go list -f {{.Dir}} -tags tools all
134-
stderr '^go: inconsistent vendoring in '$WORK/auto':$'
134+
stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
135135
stderr '^\texample.com/[email protected]: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt'
136136
stderr '^\texample.com/unused: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
137137
stderr '^\texample.com/[email protected]: is replaced in go.mod, but not marked as replaced in vendor/modules.txt'
@@ -149,7 +149,7 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$'
149149
# ...but a version mismatch for an explicit dependency should be noticed.
150150
cp $WORK/modules-bad-1.13.txt vendor/modules.txt
151151
! go list -mod=vendor -f {{.Dir}} -tags tools all
152-
stderr '^go: inconsistent vendoring in '$WORK/auto':$'
152+
stderr '^go: inconsistent vendoring in '$WORK[/\\]auto':$'
153153
stderr '^\texample.com/[email protected]: is explicitly required in go.mod, but vendor/modules.txt indicates example.com/[email protected]$'
154154
stderr '\n\nrun .go mod vendor. to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory$'
155155

src/cmd/go/testdata/script/version.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
env GO111MODULE=on
22
[short] skip
33

4+
# Check that 'go version' and 'go version -m' work on a binary built in module mode.
45
go build -o fortune.exe rsc.io/fortune
56
go version fortune.exe
67
stdout '^fortune.exe: .+'
78
go version -m fortune.exe
89
stdout '^\tpath\trsc.io/fortune'
910
stdout '^\tmod\trsc.io/fortune\tv1.0.0'
1011

12+
# Repeat the test with -buildmode=pie.
13+
# TODO(golang.org/issue/27144): don't skip after -buildmode=pie is implemented
14+
# on Windows.
15+
[windows] skip # -buildmode=pie not supported
1116
go build -buildmode=pie -o external.exe rsc.io/fortune
1217
go version external.exe
1318
stdout '^external.exe: .+'

0 commit comments

Comments
 (0)