mirror of
https://github.com/golang/go
synced 2024-11-18 17:34:51 -07:00
go.tools/cmd/cover: add a test
Test the statistics work as expected for a simple program, which can be extended as needed. This is all a bit meta. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/10392050
This commit is contained in:
parent
628104465d
commit
c28528d489
87
cmd/cover/cover_test.go
Normal file
87
cmd/cover/cover_test.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// 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"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"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")
|
||||||
|
)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666)
|
||||||
|
|
||||||
|
// defer removal of test_line_go
|
||||||
|
if !debug {
|
||||||
|
defer os.Remove(coverInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
// go build -o testcover
|
||||||
|
cmd := exec.Command("go", "build", "-o", testcover)
|
||||||
|
run(cmd, t)
|
||||||
|
|
||||||
|
// defer removal of testcover
|
||||||
|
defer os.Remove(testcover)
|
||||||
|
|
||||||
|
// ./testcover -mode=count -var=coverTest -o ./testdata/test_cover.go testdata/test_line.go
|
||||||
|
cmd = exec.Command(testcover, "-mode=count", "-var=coverTest", "-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("go", "run", testMain, coverOutput)
|
||||||
|
run(cmd, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
64
cmd/cover/testdata/main.go
vendored
Normal file
64
cmd/cover/testdata/main.go
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Test runner for coverage test. This file is not coverage-annotated; test.go is.
|
||||||
|
// It knows the coverage counter is called "coverTest".
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
testAll()
|
||||||
|
verify()
|
||||||
|
}
|
||||||
|
|
||||||
|
type block struct {
|
||||||
|
count uint32
|
||||||
|
line uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
var counters = make(map[block]bool)
|
||||||
|
|
||||||
|
// check records the location and expected value for a counter.
|
||||||
|
func check(line, count uint32) {
|
||||||
|
b := block{
|
||||||
|
count,
|
||||||
|
line,
|
||||||
|
}
|
||||||
|
counters[b] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify checks the expected counts against the actual. It runs after the test has completed.
|
||||||
|
func verify() {
|
||||||
|
ok := true
|
||||||
|
for b := range counters {
|
||||||
|
got := count(b.line)
|
||||||
|
if b.count == anything && got != 0 {
|
||||||
|
got = anything
|
||||||
|
}
|
||||||
|
if got != b.count {
|
||||||
|
fmt.Fprintf(os.Stderr, "test_go:%d expected count %d got %d\n", b.line, b.count, got)
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
fmt.Fprintf(os.Stderr, "FAIL\n")
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func count(line uint32) uint32 {
|
||||||
|
// Linear search is fine.
|
||||||
|
for i := range coverTest.Count {
|
||||||
|
lo, hi := coverTest.Pos[3*i], coverTest.Pos[3*i+1]
|
||||||
|
if lo <= line && line <= hi {
|
||||||
|
return coverTest.Count[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
105
cmd/cover/testdata/test.go
vendored
Normal file
105
cmd/cover/testdata/test.go
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// This program is processed by the cover command, and then testAll is called.
|
||||||
|
// The test driver in main.go can then compare the coverage statistics with expectation.
|
||||||
|
|
||||||
|
// The word LINE is replaced by the line number in this file. When the file is executed,
|
||||||
|
// the coverage processing has changed the line numbers, so we can't use runtime.Caller.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often"
|
||||||
|
|
||||||
|
func testAll() {
|
||||||
|
testSimple()
|
||||||
|
testBlockRun()
|
||||||
|
testFor()
|
||||||
|
testSwitch()
|
||||||
|
testSelect1()
|
||||||
|
testSelect2()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSimple() {
|
||||||
|
check(LINE, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFor() {
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
check(LINE, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBlockRun() {
|
||||||
|
check(LINE, 1)
|
||||||
|
{
|
||||||
|
check(LINE, 1)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
check(LINE, 1)
|
||||||
|
}
|
||||||
|
check(LINE, 1)
|
||||||
|
{
|
||||||
|
check(LINE, 1)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
check(LINE, 1)
|
||||||
|
}
|
||||||
|
check(LINE, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSwitch() {
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
check(LINE, 1)
|
||||||
|
case 1:
|
||||||
|
check(LINE, 1)
|
||||||
|
case 2:
|
||||||
|
check(LINE, 1)
|
||||||
|
default:
|
||||||
|
check(LINE, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSelect1() {
|
||||||
|
c := make(chan int)
|
||||||
|
go func() {
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
c <- i
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c:
|
||||||
|
check(LINE, anything)
|
||||||
|
case <-c:
|
||||||
|
check(LINE, anything)
|
||||||
|
default:
|
||||||
|
check(LINE, 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSelect2() {
|
||||||
|
c1 := make(chan int, 1000)
|
||||||
|
c2 := make(chan int, 1000)
|
||||||
|
for i := 0; i < 1000; i++ {
|
||||||
|
c1 <- i
|
||||||
|
c2 <- i
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c1:
|
||||||
|
check(LINE, 1000)
|
||||||
|
case <-c2:
|
||||||
|
check(LINE, 1000)
|
||||||
|
default:
|
||||||
|
check(LINE, 1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user