summaryrefslogtreecommitdiffstats
path: root/src/cmd/cover/testdata/main.go
blob: be74b4aa6559422f6aa33ddf1152a88e5627347b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// 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
// "thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest".

package main

import (
	"fmt"
	"os"
)

func main() {
	testAll()
	verify()
}

type block struct {
	count uint32
	line  uint32
}

var counters = make(map[block]bool)

// shorthand for the long counter variable.
var coverTest = &thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest

// check records the location and expected value for a counter.
func check(line, count uint32) {
	b := block{
		count,
		line,
	}
	counters[b] = true
}

// checkVal is a version of check that returns its extra argument,
// so it can be used in conditionals.
func checkVal(line, count uint32, val int) int {
	b := block{
		count,
		line,
	}
	counters[b] = true
	return val
}

var PASS = true

// verify checks the expected counts against the actual. It runs after the test has completed.
func verify() {
	for b := range counters {
		got, index := 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 [counter %d]\n", b.line, b.count, got, index)
			PASS = false
		}
	}
	verifyPanic()
	if !PASS {
		fmt.Fprintf(os.Stderr, "FAIL\n")
		os.Exit(2)
	}
}

// verifyPanic is a special check for the known counter that should be
// after the panic call in testPanic.
func verifyPanic() {
	if coverTest.Count[panicIndex-1] != 1 {
		// Sanity check for test before panic.
		fmt.Fprintf(os.Stderr, "bad before panic")
		PASS = false
	}
	if coverTest.Count[panicIndex] != 0 {
		fmt.Fprintf(os.Stderr, "bad at panic: %d should be 0\n", coverTest.Count[panicIndex])
		PASS = false
	}
	if coverTest.Count[panicIndex+1] != 1 {
		fmt.Fprintf(os.Stderr, "bad after panic")
		PASS = false
	}
}

// count returns the count and index for the counter at the specified line.
func count(line uint32) (uint32, int) {
	// Linear search is fine. Choose perfect fit over approximate.
	// We can have a closing brace for a range on the same line as a condition for an "else if"
	// and we don't want that brace to steal the count for the condition on the "if".
	// Therefore we test for a perfect (lo==line && hi==line) match, but if we can't
	// find that we take the first imperfect match.
	index := -1
	indexLo := uint32(1e9)
	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], i
		}
		// Choose the earliest match (the counters are in unpredictable order).
		if lo <= line && line <= hi && indexLo > lo {
			index = i
			indexLo = lo
		}
	}
	if index == -1 {
		fmt.Fprintln(os.Stderr, "cover_test: no counter for line", line)
		PASS = false
		return 0, 0
	}
	return coverTest.Count[index], index
}