@@ -19,43 +19,103 @@ import (
19
19
"path/filepath"
20
20
"regexp"
21
21
"strings"
22
+ "sync"
22
23
"testing"
23
24
)
24
25
25
26
const (
26
27
// Data directory, also the package directory for the test.
27
28
testdata = "testdata"
28
-
29
- // Binaries we compile.
30
- testcover = "./testcover.exe"
31
29
)
32
30
33
31
var (
34
- // Files we use .
32
+ // Input files .
35
33
testMain = filepath .Join (testdata , "main.go" )
36
34
testTest = filepath .Join (testdata , "test.go" )
37
- coverInput = filepath .Join (testdata , "test_line.go" )
38
- coverOutput = filepath .Join (testdata , "test_cover.go" )
39
35
coverProfile = filepath .Join (testdata , "profile.cov" )
40
36
41
37
// The HTML test files are in a separate directory
42
38
// so they are a complete package.
43
- htmlProfile = filepath .Join (testdata , "html" , "html.cov" )
44
- htmlHTML = filepath .Join (testdata , "html" , "html.html" )
45
- htmlGolden = filepath .Join (testdata , "html" , "html.golden" )
39
+ htmlGolden = filepath .Join (testdata , "html" , "html.golden" )
40
+
41
+ // Temporary files.
42
+ tmpTestMain string
43
+ coverInput string
44
+ coverOutput string
45
+ htmlProfile string
46
+ htmlHTML string
47
+ )
48
+
49
+ var (
50
+ // testTempDir is a temporary directory created in TestMain.
51
+ testTempDir string
52
+
53
+ // testcover is a newly built version of the cover program.
54
+ testcover string
55
+
56
+ // testcoverErr records an error building testcover.
57
+ testcoverErr error
58
+
59
+ // testcoverOnce is used to build testcover once.
60
+ testcoverOnce sync.Once
46
61
)
47
62
48
63
var debug = flag .Bool ("debug" , false , "keep rewritten files for debugging" )
49
64
65
+ // We use TestMain to set up a temporary directory and remove it when
66
+ // the tests are done.
67
+ func TestMain (m * testing.M ) {
68
+ dir , err := ioutil .TempDir ("" , "gotestcover" )
69
+ if err != nil {
70
+ fmt .Fprintln (os .Stderr , err )
71
+ os .Exit (1 )
72
+ }
73
+
74
+ testTempDir = dir
75
+
76
+ tmpTestMain = filepath .Join (dir , "main.go" )
77
+ coverInput = filepath .Join (dir , "test_line.go" )
78
+ coverOutput = filepath .Join (dir , "test_cover.go" )
79
+ htmlProfile = filepath .Join (dir , "html.cov" )
80
+ htmlHTML = filepath .Join (dir , "html.html" )
81
+
82
+ status := m .Run ()
83
+
84
+ if ! * debug {
85
+ os .RemoveAll (dir )
86
+ }
87
+
88
+ os .Exit (status )
89
+ }
90
+
91
+ // buildCover builds a version of the cover program for testing.
92
+ // This ensures that "go test cmd/cover" tests the current cmd/cover.
93
+ func buildCover (t * testing.T ) {
94
+ t .Helper ()
95
+ testenv .MustHaveGoBuild (t )
96
+ testcoverOnce .Do (func () {
97
+ testcover = filepath .Join (testTempDir , "testcover.exe" )
98
+ t .Logf ("running [go build -o %s]" , testcover )
99
+ out , err := exec .Command (testenv .GoToolPath (t ), "build" , "-o" , testcover ).CombinedOutput ()
100
+ t .Logf ("%s" , out )
101
+ testcoverErr = err
102
+ })
103
+ if testcoverErr != nil {
104
+ t .Fatal ("failed to build testcover program:" , testcoverErr )
105
+ }
106
+ }
107
+
50
108
// Run this shell script, but do it in Go so it can be run by "go test".
51
109
//
52
110
// replace the word LINE with the line number < testdata/test.go > testdata/test_line.go
53
- // go build -o ./ testcover
54
- // ./ testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go
111
+ // go build -o testcover
112
+ // testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go
55
113
// go run ./testdata/main.go ./testdata/test.go
56
114
//
57
115
func TestCover (t * testing.T ) {
58
- testenv .MustHaveGoBuild (t )
116
+ t .Parallel ()
117
+ testenv .MustHaveGoRun (t )
118
+ buildCover (t )
59
119
60
120
// Read in the test file (testTest) and write it, with LINEs specified, to coverInput.
61
121
file , err := ioutil .ReadFile (testTest )
@@ -81,29 +141,22 @@ func TestCover(t *testing.T) {
81
141
t .Fatal (err )
82
142
}
83
143
84
- // defer removal of test_line.go
85
- if ! * debug {
86
- defer os .Remove (coverInput )
87
- }
88
-
89
- // go build -o testcover
90
- cmd := exec .Command (testenv .GoToolPath (t ), "build" , "-o" , testcover )
144
+ // testcover -mode=count -var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest -o ./testdata/test_cover.go testdata/test_line.go
145
+ cmd := exec .Command (testcover , "-mode=count" , "-var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest" , "-o" , coverOutput , coverInput )
91
146
run (cmd , t )
92
147
93
- // defer removal of testcover
94
- defer os .Remove (testcover )
95
-
96
- // ./testcover -mode=count -var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest -o ./testdata/test_cover.go testdata/test_line.go
97
- cmd = exec .Command (testcover , "-mode=count" , "-var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest" , "-o" , coverOutput , coverInput )
98
- run (cmd , t )
99
-
100
- // defer removal of ./testdata/test_cover.go
101
- if ! * debug {
102
- defer os .Remove (coverOutput )
148
+ // Copy testmain to testTempDir, so that it is in the same directory
149
+ // as coverOutput.
150
+ b , err := ioutil .ReadFile (testMain )
151
+ if err != nil {
152
+ t .Fatal (err )
153
+ }
154
+ if err := ioutil .WriteFile (tmpTestMain , b , 0444 ); err != nil {
155
+ t .Fatal (err )
103
156
}
104
157
105
158
// go run ./testdata/main.go ./testdata/test.go
106
- cmd = exec .Command (testenv .GoToolPath (t ), "run" , testMain , coverOutput )
159
+ cmd = exec .Command (testenv .GoToolPath (t ), "run" , tmpTestMain , coverOutput )
107
160
run (cmd , t )
108
161
109
162
file , err = ioutil .ReadFile (coverOutput )
@@ -131,6 +184,9 @@ func TestCover(t *testing.T) {
131
184
// above those declarations, even if they are not part of the block of
132
185
// documentation comments.
133
186
func TestDirectives (t * testing.T ) {
187
+ t .Parallel ()
188
+ buildCover (t )
189
+
134
190
// Read the source file and find all the directives. We'll keep
135
191
// track of whether each one has been seen in the output.
136
192
testDirectives := filepath .Join (testdata , "directives.go" )
@@ -140,8 +196,8 @@ func TestDirectives(t *testing.T) {
140
196
}
141
197
sourceDirectives := findDirectives (source )
142
198
143
- // go tool cover -mode=atomic ./testdata/directives.go
144
- cmd := exec .Command (testenv . GoToolPath ( t ), "tool" , "cover" , "-mode=atomic" , testDirectives )
199
+ // testcover -mode=atomic ./testdata/directives.go
200
+ cmd := exec .Command (testcover , "-mode=atomic" , testDirectives )
145
201
cmd .Stderr = os .Stderr
146
202
output , err := cmd .Output ()
147
203
if err != nil {
@@ -247,8 +303,10 @@ func findDirectives(source []byte) []directiveInfo {
247
303
// Makes sure that `cover -func=profile.cov` reports accurate coverage.
248
304
// Issue #20515.
249
305
func TestCoverFunc (t * testing.T ) {
250
- // go tool cover -func ./testdata/profile.cov
251
- cmd := exec .Command (testenv .GoToolPath (t ), "tool" , "cover" , "-func" , coverProfile )
306
+ t .Parallel ()
307
+ buildCover (t )
308
+ // testcover -func ./testdata/profile.cov
309
+ cmd := exec .Command (testcover , "-func" , coverProfile )
252
310
out , err := cmd .Output ()
253
311
if err != nil {
254
312
if ee , ok := err .(* exec.ExitError ); ok {
@@ -266,19 +324,14 @@ func TestCoverFunc(t *testing.T) {
266
324
// Check that cover produces correct HTML.
267
325
// Issue #25767.
268
326
func TestCoverHTML (t * testing.T ) {
269
- testenv .MustHaveGoBuild (t )
270
- if ! * debug {
271
- defer os .Remove (testcover )
272
- defer os .Remove (htmlProfile )
273
- defer os .Remove (htmlHTML )
274
- }
275
- // go build -o testcover
276
- cmd := exec .Command (testenv .GoToolPath (t ), "build" , "-o" , testcover )
277
- run (cmd , t )
327
+ t .Parallel ()
328
+ testenv .MustHaveGoRun (t )
329
+ buildCover (t )
330
+
278
331
// go test -coverprofile testdata/html/html.cov cmd/cover/testdata/html
279
- cmd = exec .Command (testenv .GoToolPath (t ), "test" , "-coverprofile" , htmlProfile , "cmd/cover/testdata/html" )
332
+ cmd : = exec .Command (testenv .GoToolPath (t ), "test" , "-coverprofile" , htmlProfile , "cmd/cover/testdata/html" )
280
333
run (cmd , t )
281
- // ./ testcover -html testdata/html/html.cov -o testdata/html/html.html
334
+ // testcover -html testdata/html/html.cov -o testdata/html/html.html
282
335
cmd = exec .Command (testcover , "-html" , htmlProfile , "-o" , htmlHTML )
283
336
run (cmd , t )
284
337
@@ -303,6 +356,9 @@ func TestCoverHTML(t *testing.T) {
303
356
in = false
304
357
}
305
358
}
359
+ if scan .Err () != nil {
360
+ t .Error (scan .Err ())
361
+ }
306
362
golden , err := ioutil .ReadFile (htmlGolden )
307
363
if err != nil {
308
364
t .Fatalf ("reading golden file: %v" , err )
@@ -331,6 +387,7 @@ func TestCoverHTML(t *testing.T) {
331
387
332
388
func run (c * exec.Cmd , t * testing.T ) {
333
389
t .Helper ()
390
+ t .Log ("running" , c .Args )
334
391
c .Stdout = os .Stdout
335
392
c .Stderr = os .Stderr
336
393
err := c .Run ()
0 commit comments