| // Copyright 2013 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main_test |
| |
| import ( |
| "bytes" |
| "fmt" |
| "internal/testenv" |
| "io/ioutil" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "regexp" |
| "testing" |
| ) |
| |
| const ( |
| // Data directory, also the package directory for the test. |
| testdata = "testdata" |
| |
| // Binaries we compile. |
| testcover = "./testcover.exe" |
| ) |
| |
| var ( |
| // Files we use. |
| testMain = filepath.Join(testdata, "main.go") |
| testTest = filepath.Join(testdata, "test.go") |
| coverInput = filepath.Join(testdata, "test_line.go") |
| coverOutput = filepath.Join(testdata, "test_cover.go") |
| coverProfile = filepath.Join(testdata, "profile.cov") |
| ) |
| |
| var debug = false // Keeps the rewritten files around if set. |
| |
| // Run this shell script, but do it in Go so it can be run by "go test". |
| // |
| // replace the word LINE with the line number < testdata/test.go > testdata/test_line.go |
| // go build -o ./testcover |
| // ./testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go |
| // go run ./testdata/main.go ./testdata/test.go |
| // |
| func TestCover(t *testing.T) { |
| testenv.MustHaveGoBuild(t) |
| |
| // Read in the test file (testTest) and write it, with LINEs specified, to coverInput. |
| file, err := ioutil.ReadFile(testTest) |
| if err != nil { |
| t.Fatal(err) |
| } |
| lines := bytes.Split(file, []byte("\n")) |
| for i, line := range lines { |
| lines[i] = bytes.Replace(line, []byte("LINE"), []byte(fmt.Sprint(i+1)), -1) |
| } |
| if err := ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil { |
| t.Fatal(err) |
| } |
| |
| // defer removal of test_line.go |
| if !debug { |
| defer os.Remove(coverInput) |
| } |
| |
| // go build -o testcover |
| cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", testcover) |
| run(cmd, t) |
| |
| // defer removal of testcover |
| defer os.Remove(testcover) |
| |
| // ./testcover -mode=count -var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest -o ./testdata/test_cover.go testdata/test_line.go |
| cmd = exec.Command(testcover, "-mode=count", "-var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest", "-o", coverOutput, coverInput) |
| run(cmd, t) |
| |
| // defer removal of ./testdata/test_cover.go |
| if !debug { |
| defer os.Remove(coverOutput) |
| } |
| |
| // go run ./testdata/main.go ./testdata/test.go |
| cmd = exec.Command(testenv.GoToolPath(t), "run", testMain, coverOutput) |
| run(cmd, t) |
| |
| file, err = ioutil.ReadFile(coverOutput) |
| if err != nil { |
| t.Fatal(err) |
| } |
| // compiler directive must appear right next to function declaration. |
| if got, err := regexp.MatchString(".*\n//go:nosplit\nfunc someFunction().*", string(file)); err != nil || !got { |
| t.Errorf("misplaced compiler directive: got=(%v, %v); want=(true; nil)", got, err) |
| } |
| // "go:linkname" compiler directive should be present. |
| if got, err := regexp.MatchString(`.*go\:linkname some\_name some\_name.*`, string(file)); err != nil || !got { |
| t.Errorf("'go:linkname' compiler directive not found: got=(%v, %v); want=(true; nil)", got, err) |
| } |
| |
| // No other comments should be present in generated code. |
| c := ".*// This comment shouldn't appear in generated go code.*" |
| if got, err := regexp.MatchString(c, string(file)); err != nil || got { |
| t.Errorf("non compiler directive comment %q found. got=(%v, %v); want=(false; nil)", c, got, err) |
| } |
| } |
| |
| // Makes sure that `cover -func=profile.cov` reports accurate coverage. |
| // Issue #20515. |
| func TestCoverFunc(t *testing.T) { |
| // go tool cover -func ./testdata/profile.cov |
| cmd := exec.Command(testenv.GoToolPath(t), "tool", "cover", "-func", coverProfile) |
| out, err := cmd.Output() |
| if err != nil { |
| if ee, ok := err.(*exec.ExitError); ok { |
| t.Logf("%s", ee.Stderr) |
| } |
| t.Fatal(err) |
| } |
| |
| if got, err := regexp.Match(".*total:.*100.0.*", out); err != nil || !got { |
| t.Logf("%s", out) |
| t.Errorf("invalid coverage counts. got=(%v, %v); want=(true; nil)", got, err) |
| } |
| } |
| |
| func run(c *exec.Cmd, t *testing.T) { |
| c.Stdout = os.Stdout |
| c.Stderr = os.Stderr |
| err := c.Run() |
| if err != nil { |
| t.Fatal(err) |
| } |
| } |