1
2
3
4
5
6 package scripttest
7
8 import (
9 "errors"
10 "internal/testenv"
11 "io"
12 "io/fs"
13 "os"
14 "path/filepath"
15 "runtime"
16 "strings"
17 "sync"
18 "testing"
19 )
20
21
22
23
24
25 func SetupTestGoRoot(t *testing.T, tmpdir string, goroot string) string {
26 mustMkdir := func(path string) {
27 if err := os.MkdirAll(path, 0777); err != nil {
28 t.Fatalf("SetupTestGoRoot mkdir %s failed: %v", path, err)
29 }
30 }
31
32 replicateDir := func(srcdir, dstdir string) {
33 files, err := os.ReadDir(srcdir)
34 if err != nil {
35 t.Fatalf("inspecting %s: %v", srcdir, err)
36 }
37 for _, file := range files {
38 fn := file.Name()
39 linkOrCopy(t, filepath.Join(srcdir, fn), filepath.Join(dstdir, fn))
40 }
41 }
42
43
44 findToolOnce.Do(func() { findToolSub(t) })
45 if toolsub == "" {
46 t.Fatal("failed to find toolsub")
47 }
48
49 tomake := []string{
50 "bin",
51 "src",
52 "pkg",
53 filepath.Join("pkg", "include"),
54 toolsub,
55 }
56 made := []string{}
57 tgr := filepath.Join(tmpdir, "testgoroot")
58 mustMkdir(tgr)
59 for _, targ := range tomake {
60 path := filepath.Join(tgr, targ)
61 mustMkdir(path)
62 made = append(made, path)
63 }
64
65
66 replicateDir(filepath.Join(goroot, "bin"), made[0])
67 replicateDir(filepath.Join(goroot, "src"), made[1])
68 replicateDir(filepath.Join(goroot, "pkg", "include"), made[3])
69 replicateDir(filepath.Join(goroot, toolsub), made[4])
70
71 return tgr
72 }
73
74
75
76
77 func ReplaceGoToolInTestGoRoot(t *testing.T, testgoroot, toolname, newtoolpath string) {
78 findToolOnce.Do(func() { findToolSub(t) })
79 if toolsub == "" {
80 t.Fatal("failed to find toolsub")
81 }
82
83 exename := toolname
84 if runtime.GOOS == "windows" {
85 exename += ".exe"
86 }
87 toolpath := filepath.Join(testgoroot, toolsub, exename)
88 if err := os.Remove(toolpath); err != nil && !errors.Is(err, fs.ErrNotExist) {
89 t.Fatalf("removing %s: %v", toolpath, err)
90 }
91 linkOrCopy(t, newtoolpath, toolpath)
92 }
93
94
95 var toolsub string
96
97
98 var findToolOnce sync.Once
99
100
101 func findToolSub(t *testing.T) {
102 gocmd := testenv.Command(t, testenv.GoToolPath(t), "env", "GOHOSTARCH")
103 gocmd = testenv.CleanCmdEnv(gocmd)
104 goHostArchBytes, err := gocmd.CombinedOutput()
105 if err != nil {
106 t.Fatalf("%s failed: %v\n%s", gocmd, err, goHostArchBytes)
107 }
108 goHostArch := strings.TrimSpace(string(goHostArchBytes))
109 toolsub = filepath.Join("pkg", "tool", runtime.GOOS+"_"+goHostArch)
110 }
111
112
113
114 func linkOrCopy(t *testing.T, src, dst string) {
115 err := os.Symlink(src, dst)
116 if err == nil {
117 return
118 }
119 fi, err := os.Stat(src)
120 if err != nil {
121 t.Fatalf("copying %s to %s: %v", src, dst, err)
122 }
123 if fi.IsDir() {
124 if err := os.CopyFS(dst, os.DirFS(src)); err != nil {
125 t.Fatalf("copying %s to %s: %v", src, dst, err)
126 }
127 return
128 }
129 srcf, err := os.Open(src)
130 if err != nil {
131 t.Fatalf("copying %s to %s: %v", src, dst, err)
132 }
133 defer srcf.Close()
134 perm := os.O_WRONLY | os.O_CREATE | os.O_EXCL
135 dstf, err := os.OpenFile(dst, perm, 0o777)
136 if err != nil {
137 t.Fatalf("copying %s to %s: %v", src, dst, err)
138 }
139 _, err = io.Copy(dstf, srcf)
140 if closeErr := dstf.Close(); err == nil {
141 err = closeErr
142 }
143 if err != nil {
144 t.Fatalf("copying %s to %s: %v", src, dst, err)
145 }
146 }
147
View as plain text