cmd/go: convert some coverage tests to the script framework

This change converts TestCoverageFunc, TestCoverageDashC,
TestCoverageSyncAtomicImport, TestCoverageErrorLine,
TestCoverageDepLoop, TestCoverageDotImport, and
TestTestBuildFailureOutput to the script framework.

It adds a -exec modifier to the script framework's [exists] check
to check that a file is executable.

Updates #17751

Change-Id: Idc1e36c3702c94918631936f637510a6679d18a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/212624
Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
Michael Matloob 2019-12-26 19:24:41 -05:00
parent b15fd6b39e
commit 8df6a5d9ad
25 changed files with 252 additions and 196 deletions

View File

@ -2052,40 +2052,6 @@ func TestCoverageRuns(t *testing.T) {
checkCoverage(tg, data)
}
func TestCoverageDotImport(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("test", "-coverpkg=coverdot1,coverdot2", "coverdot2")
data := tg.getStdout() + tg.getStderr()
checkCoverage(tg, data)
}
func TestCoverageSyncAtomicImport(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("test", "-short", "-cover", "-covermode=atomic", "-coverpkg=coverdep/p1", "coverdep")
}
func TestCoverageDepLoop(t *testing.T) {
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
// coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1.
// Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2.
tg.run("test", "-short", "-cover", "coverdep2/p1")
tg.grepStdout("coverage: 100.0% of statements", "expected 100.0% coverage")
}
func TestCoverageNoStatements(t *testing.T) {
tooSlow(t)
tg := testgo(t)
@ -2094,78 +2060,6 @@ func TestCoverageNoStatements(t *testing.T) {
tg.grepStdout("[no statements]", "expected [no statements] for pkg4")
}
func TestCoverageErrorLine(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.makeTempdir()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.setenv("GOTMPDIR", tg.tempdir)
tg.runFail("test", "coverbad")
tg.grepStderr(`coverbad[\\/]p\.go:4`, "did not find coverbad/p.go:4")
if canCgo {
tg.grepStderr(`coverbad[\\/]p1\.go:6`, "did not find coverbad/p1.go:6")
}
tg.grepStderrNot(regexp.QuoteMeta(tg.tempdir), "found temporary directory in error")
stderr := tg.getStderr()
tg.runFail("test", "-cover", "coverbad")
stderr2 := tg.getStderr()
// It's OK that stderr2 drops the character position in the error,
// because of the //line directive (see golang.org/issue/22662).
stderr = strings.ReplaceAll(stderr, "p.go:4:2:", "p.go:4:")
if stderr != stderr2 {
t.Logf("test -cover changed error messages:\nbefore:\n%s\n\nafter:\n%s", stderr, stderr2)
t.Skip("golang.org/issue/22660")
t.FailNow()
}
}
func TestTestBuildFailureOutput(t *testing.T) {
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
// Doesn't build, -x output should not claim to run test.
tg.runFail("test", "-x", "coverbad")
tg.grepStderrNot(`[\\/]coverbad\.test( |$)`, "claimed to run test")
}
func TestCoverageFunc(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.makeTempdir()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("test", "-outputdir="+tg.tempdir, "-coverprofile=cover.out", "coverasm")
tg.run("tool", "cover", "-func="+tg.path("cover.out"))
tg.grepStdout(`\tg\t*100.0%`, "did not find g 100% covered")
tg.grepStdoutNot(`\tf\t*[0-9]`, "reported coverage for assembly function f")
}
// Issue 24588.
func TestCoverageDashC(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.makeTempdir()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("test", "-c", "-o", tg.path("coverdep"), "-coverprofile="+tg.path("no/such/dir/cover.out"), "coverdep")
tg.wantExecutable(tg.path("coverdep"), "go -test -c -coverprofile did not create executable")
}
func TestTestEmpty(t *testing.T) {
if !canRace {
t.Skip("no race detector")

View File

@ -658,13 +658,22 @@ func (ts *testScript) cmdExec(neg bool, args []string) {
// exists checks that the list of files exists.
func (ts *testScript) cmdExists(neg bool, args []string) {
var readonly bool
if len(args) > 0 && args[0] == "-readonly" {
readonly = true
args = args[1:]
var readonly, exec bool
loop:
for len(args) > 0 {
switch args[0] {
case "-readonly":
readonly = true
args = args[1:]
case "-exec":
exec = true
args = args[1:]
default:
break loop
}
}
if len(args) == 0 {
ts.fatalf("usage: exists [-readonly] file...")
ts.fatalf("usage: exists [-readonly] [-exec] file...")
}
for _, file := range args {
@ -683,6 +692,9 @@ func (ts *testScript) cmdExists(neg bool, args []string) {
if err == nil && !neg && readonly && info.Mode()&0222 != 0 {
ts.fatalf("%s exists but is writable", file)
}
if err == nil && !neg && exec && runtime.GOOS != "windows" && info.Mode()&0111 == 0 {
ts.fatalf("%s exists but is not executable", file)
}
}
}

View File

@ -134,9 +134,10 @@ The commands are:
test. At the end of the test, any remaining background processes are
terminated using os.Interrupt (if supported) or os.Kill.
- [!] exists [-readonly] file...
- [!] exists [-readonly] [-exec] file...
Each of the listed files or directories must (or must not) exist.
If -readonly is given, the files or directories must be unwritable.
If -exec is given, the files or directories must be executable.
- [!] go args... [&]
Run the (test copy of the) go command with the given arguments.

View File

@ -0,0 +1,29 @@
[short] skip
[gccgo] skip # gccgo has no cover tool
# Test cover for a package that has an assembly function.
go test -outputdir=$WORK -coverprofile=cover.out coverasm
go tool cover -func=$WORK/cover.out
stdout '\tg\t*100.0%' # Check g is 100% covered.
! stdout '\tf\t*[0-9]' # Check for no coverage on the assembly function
-- coverasm/p.go --
package p
func f()
func g() {
println("g")
}
-- coverasm/p.s --
// empty asm file,
// so go test doesn't complain about declaration of f in p.go.
-- coverasm/p_test.go --
package p
import "testing"
func Test(t *testing.T) {
g()
}

View File

@ -0,0 +1,27 @@
[short] skip
[gccgo] skip
# Test for issue 24588
go test -c -o $WORK/coverdep -coverprofile=$WORK/no/such/dir/cover.out coverdep
exists -exec $WORK/coverdep
-- coverdep/p.go --
package p
import _ "coverdep/p1"
func F() {
}
-- coverdep/p1/p1.go --
package p1
import _ "errors"
-- coverdep/p_test.go --
package p
import "testing"
func Test(t *testing.T) {
F()
}

View File

@ -0,0 +1,32 @@
[short] skip
[gccgo] skip
# coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1.
# Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2.
go test -short -cover coverdep2/p1
stdout 'coverage: 100.0% of statements' # expect 100.0% coverage
-- coverdep2/p1/p.go --
package p1
func F() int { return 1 }
-- coverdep2/p1/p_test.go --
package p1_test
import (
"coverdep2/p2"
"testing"
)
func Test(t *testing.T) {
p2.F()
}
-- coverdep2/p2/p2.go --
package p2
import "coverdep2/p1"
func F() {
p1.F()
}

View File

@ -0,0 +1,25 @@
[short] skip
[gccgo] skip # gccgo has no cover tool
go test -coverpkg=coverdot1,coverdot2 coverdot2
! stderr '[^0-9]0\.0%'
! stdout '[^0-9]0\.0%'
-- coverdot1/p.go --
package coverdot1
func F() {}
-- coverdot2/p.go --
package coverdot2
import . "coverdot1"
func G() { F() }
-- coverdot2/p_test.go --
package coverdot2
import "testing"
func TestG(t *testing.T) {
G()
}

View File

@ -0,0 +1,69 @@
[short] skip
[gccgo] skip
# Test line numbers in cover errors.
# Get errors from a go test into stderr.txt
! go test coverbad
stderr 'coverbad[\\/]p\.go:4' # look for error at coverbad/p.go:4
[cgo] stderr 'coverbad[\\/]p1\.go:6' # look for error at coverbad/p.go:6
! stderr $WORK # make sure temporary directory isn't in error
cp stderr $WORK/stderr.txt
# Clean out character positions from stderr.txt
# It's OK that stderr2 drops the character position in the error,
# because of the //line directive (see golang.org/issue/22662).
go run clean_charpos.go $WORK/stderr.txt &
# Get errors from coverage into stderr2.txt
! go test -cover coverbad
cp stderr $WORK/stderr2.txt
wait # for go run above
cmp $WORK/stderr.txt $WORK/stderr2.txt
-- coverbad/p.go --
package p
func f() {
g()
}
-- coverbad/p1.go --
package p
import "C"
func h() {
j()
}
-- coverbad/p_test.go --
package p
import "testing"
func Test(t *testing.T) {}
-- clean_charpos.go --
package main
import (
"io/ioutil"
"log"
"os"
"strings"
)
func main() {
log.SetFlags(0)
b, err := ioutil.ReadFile(os.Args[1])
if err != nil {
log.Fatal(err)
}
s := strings.ReplaceAll(string(b), "p.go:4:2:", "p.go:4:")
s = strings.ReplaceAll(s, "p1.go:6:2:", "p1.go:6:")
ioutil.WriteFile(os.Args[1], []byte(s), 0644)
if err != nil {
log.Fatal(err)
}
}

View File

@ -0,0 +1,24 @@
[short] skip
[gccgo] skip # gccgo has no cover tool
go test -short -cover -covermode=atomic -coverpkg=coverdep/p1 coverdep
-- coverdep/p.go --
package p
import _ "coverdep/p1"
func F() {
}
-- coverdep/p1/p1.go --
package p1
import _ "errors"
-- coverdep/p_test.go --
package p
import "testing"
func Test(t *testing.T) {
F()
}

View File

@ -0,0 +1,27 @@
[short] skip
! go test -x coverbad
! stderr '[\\/]coverbad\.test( |$)' # 'go test' should not claim to have run the test.
stderr 'undefined: g'
stderr 'undefined: j'
-- coverbad/p.go --
package p
func f() {
g()
}
-- coverbad/p1.go --
package p
import "C"
func h() {
j()
}
-- coverbad/p_test.go --
package p
import "testing"
func Test(t *testing.T) {}

View File

@ -1,7 +0,0 @@
package p
func f()
func g() {
println("g")
}

View File

@ -1,2 +0,0 @@
// empty asm file,
// so go test doesn't complain about declaration of f in p.go.

View File

@ -1,7 +0,0 @@
package p
import "testing"
func Test(t *testing.T) {
g()
}

View File

@ -1,5 +0,0 @@
package p
func f() {
g()
}

View File

@ -1,7 +0,0 @@
package p
import "C"
func h() {
j()
}

View File

@ -1,5 +0,0 @@
package p
import "testing"
func Test(t *testing.T) {}

View File

@ -1,6 +0,0 @@
package p
import _ "coverdep/p1"
func F() {
}

View File

@ -1,3 +0,0 @@
package p1
import _ "errors"

View File

@ -1,7 +0,0 @@
package p
import "testing"
func Test(t *testing.T) {
F()
}

View File

@ -1,3 +0,0 @@
package p1
func F() int { return 1 }

View File

@ -1,10 +0,0 @@
package p1_test
import (
"coverdep2/p2"
"testing"
)
func Test(t *testing.T) {
p2.F()
}

View File

@ -1,7 +0,0 @@
package p2
import "coverdep2/p1"
func F() {
p1.F()
}

View File

@ -1,3 +0,0 @@
package coverdot1
func F() {}

View File

@ -1,5 +0,0 @@
package coverdot2
import . "coverdot1"
func G() { F() }

View File

@ -1,7 +0,0 @@
package coverdot2
import "testing"
func TestG(t *testing.T) {
G()
}