145
|
1 // Copyright 2019 The Go Authors. All rights reserved.
|
|
2 // Use of this source code is governed by a BSD-style
|
|
3 // license that can be found in the LICENSE file.
|
|
4
|
|
5 package plugin_test
|
|
6
|
|
7 import (
|
|
8 "bytes"
|
|
9 "context"
|
|
10 "flag"
|
|
11 "fmt"
|
|
12 "io/ioutil"
|
|
13 "log"
|
|
14 "os"
|
|
15 "os/exec"
|
|
16 "path/filepath"
|
|
17 "strings"
|
|
18 "testing"
|
|
19 "time"
|
|
20 )
|
|
21
|
|
22 var gcflags string = os.Getenv("GO_GCFLAGS")
|
|
23
|
|
24 func TestMain(m *testing.M) {
|
|
25 flag.Parse()
|
|
26 if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
|
|
27 fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
|
|
28 os.Exit(0)
|
|
29 }
|
|
30 log.SetFlags(log.Lshortfile)
|
|
31 os.Exit(testMain(m))
|
|
32 }
|
|
33
|
|
34 func testMain(m *testing.M) int {
|
|
35 // Copy testdata into GOPATH/src/testarchive, along with a go.mod file
|
|
36 // declaring the same path.
|
|
37
|
|
38 GOPATH, err := ioutil.TempDir("", "plugin_test")
|
|
39 if err != nil {
|
|
40 log.Panic(err)
|
|
41 }
|
|
42 defer os.RemoveAll(GOPATH)
|
|
43
|
|
44 modRoot := filepath.Join(GOPATH, "src", "testplugin")
|
|
45 altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
|
|
46 for srcRoot, dstRoot := range map[string]string{
|
|
47 "testdata": modRoot,
|
|
48 filepath.Join("altpath", "testdata"): altRoot,
|
|
49 } {
|
|
50 if err := overlayDir(dstRoot, srcRoot); err != nil {
|
|
51 log.Panic(err)
|
|
52 }
|
|
53 if err := ioutil.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
|
|
54 log.Panic(err)
|
|
55 }
|
|
56 }
|
|
57
|
|
58 os.Setenv("GOPATH", filepath.Join(GOPATH, "alt"))
|
|
59 if err := os.Chdir(altRoot); err != nil {
|
|
60 log.Panic(err)
|
|
61 }
|
|
62 os.Setenv("PWD", altRoot)
|
|
63 goCmd(nil, "build", "-buildmode=plugin", "-o", filepath.Join(modRoot, "plugin-mismatch.so"), "./plugin-mismatch")
|
|
64
|
|
65 os.Setenv("GOPATH", GOPATH)
|
|
66 if err := os.Chdir(modRoot); err != nil {
|
|
67 log.Panic(err)
|
|
68 }
|
|
69 os.Setenv("PWD", modRoot)
|
|
70
|
|
71 os.Setenv("LD_LIBRARY_PATH", modRoot)
|
|
72
|
|
73 goCmd(nil, "build", "-buildmode=plugin", "./plugin1")
|
|
74 goCmd(nil, "build", "-buildmode=plugin", "./plugin2")
|
|
75 so, err := ioutil.ReadFile("plugin2.so")
|
|
76 if err != nil {
|
|
77 log.Panic(err)
|
|
78 }
|
|
79 if err := ioutil.WriteFile("plugin2-dup.so", so, 0444); err != nil {
|
|
80 log.Panic(err)
|
|
81 }
|
|
82
|
|
83 goCmd(nil, "build", "-buildmode=plugin", "-o=sub/plugin1.so", "./sub/plugin1")
|
|
84 goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed1.so", "./unnamed1/main.go")
|
|
85 goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed2.so", "./unnamed2/main.go")
|
|
86 goCmd(nil, "build", "-o", "host.exe", "./host")
|
|
87
|
|
88 return m.Run()
|
|
89 }
|
|
90
|
|
91 func goCmd(t *testing.T, op string, args ...string) {
|
|
92 if t != nil {
|
|
93 t.Helper()
|
|
94 }
|
|
95 run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...)
|
|
96 }
|
|
97
|
|
98 func run(t *testing.T, bin string, args ...string) string {
|
|
99 cmd := exec.Command(bin, args...)
|
|
100 cmd.Stderr = new(strings.Builder)
|
|
101 out, err := cmd.Output()
|
|
102 if err != nil {
|
|
103 if t == nil {
|
|
104 log.Panicf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
|
|
105 } else {
|
|
106 t.Helper()
|
|
107 t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
|
|
108 }
|
|
109 }
|
|
110
|
|
111 return string(bytes.TrimSpace(out))
|
|
112 }
|
|
113
|
|
114 func TestDWARFSections(t *testing.T) {
|
|
115 // test that DWARF sections are emitted for plugins and programs importing "plugin"
|
|
116 goCmd(t, "run", "./checkdwarf/main.go", "plugin2.so", "plugin2.UnexportedNameReuse")
|
|
117 goCmd(t, "run", "./checkdwarf/main.go", "./host.exe", "main.main")
|
|
118 }
|
|
119
|
|
120 func TestRunHost(t *testing.T) {
|
|
121 run(t, "./host.exe")
|
|
122 }
|
|
123
|
|
124 func TestUniqueTypesAndItabs(t *testing.T) {
|
|
125 goCmd(t, "build", "-buildmode=plugin", "./iface_a")
|
|
126 goCmd(t, "build", "-buildmode=plugin", "./iface_b")
|
|
127 goCmd(t, "build", "-o", "iface.exe", "./iface")
|
|
128 run(t, "./iface.exe")
|
|
129 }
|
|
130
|
|
131 func TestIssue18676(t *testing.T) {
|
|
132 // make sure we don't add the same itab twice.
|
|
133 // The buggy code hangs forever, so use a timeout to check for that.
|
|
134 goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./issue18676/plugin.go")
|
|
135 goCmd(t, "build", "-o", "issue18676.exe", "./issue18676/main.go")
|
|
136
|
|
137 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
138 defer cancel()
|
|
139 cmd := exec.CommandContext(ctx, "./issue18676.exe")
|
|
140 out, err := cmd.CombinedOutput()
|
|
141 if err != nil {
|
|
142 t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
|
143 }
|
|
144 }
|
|
145
|
|
146 func TestIssue19534(t *testing.T) {
|
|
147 // Test that we can load a plugin built in a path with non-alpha characters.
|
|
148 goCmd(t, "build", "-buildmode=plugin", "-ldflags='-pluginpath=issue.19534'", "-o", "plugin.so", "./issue19534/plugin.go")
|
|
149 goCmd(t, "build", "-o", "issue19534.exe", "./issue19534/main.go")
|
|
150 run(t, "./issue19534.exe")
|
|
151 }
|
|
152
|
|
153 func TestIssue18584(t *testing.T) {
|
|
154 goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./issue18584/plugin.go")
|
|
155 goCmd(t, "build", "-o", "issue18584.exe", "./issue18584/main.go")
|
|
156 run(t, "./issue18584.exe")
|
|
157 }
|
|
158
|
|
159 func TestIssue19418(t *testing.T) {
|
|
160 goCmd(t, "build", "-buildmode=plugin", "-ldflags=-X main.Val=linkstr", "-o", "plugin.so", "./issue19418/plugin.go")
|
|
161 goCmd(t, "build", "-o", "issue19418.exe", "./issue19418/main.go")
|
|
162 run(t, "./issue19418.exe")
|
|
163 }
|
|
164
|
|
165 func TestIssue19529(t *testing.T) {
|
|
166 goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./issue19529/plugin.go")
|
|
167 }
|
|
168
|
|
169 func TestIssue22175(t *testing.T) {
|
|
170 goCmd(t, "build", "-buildmode=plugin", "-o", "issue22175_plugin1.so", "./issue22175/plugin1.go")
|
|
171 goCmd(t, "build", "-buildmode=plugin", "-o", "issue22175_plugin2.so", "./issue22175/plugin2.go")
|
|
172 goCmd(t, "build", "-o", "issue22175.exe", "./issue22175/main.go")
|
|
173 run(t, "./issue22175.exe")
|
|
174 }
|
|
175
|
|
176 func TestIssue22295(t *testing.T) {
|
|
177 goCmd(t, "build", "-buildmode=plugin", "-o", "issue.22295.so", "./issue22295.pkg")
|
|
178 goCmd(t, "build", "-o", "issue22295.exe", "./issue22295.pkg/main.go")
|
|
179 run(t, "./issue22295.exe")
|
|
180 }
|
|
181
|
|
182 func TestIssue24351(t *testing.T) {
|
|
183 goCmd(t, "build", "-buildmode=plugin", "-o", "issue24351.so", "./issue24351/plugin.go")
|
|
184 goCmd(t, "build", "-o", "issue24351.exe", "./issue24351/main.go")
|
|
185 run(t, "./issue24351.exe")
|
|
186 }
|
|
187
|
|
188 func TestIssue25756(t *testing.T) {
|
|
189 goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin")
|
|
190 goCmd(t, "build", "-o", "issue25756.exe", "./issue25756/main.go")
|
|
191 // Fails intermittently, but 20 runs should cause the failure
|
|
192 for n := 20; n > 0; n-- {
|
|
193 t.Run(fmt.Sprint(n), func(t *testing.T) {
|
|
194 t.Parallel()
|
|
195 run(t, "./issue25756.exe")
|
|
196 })
|
|
197 }
|
|
198 }
|