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