1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Test runner for coverage test. This file is not coverage-annotated; test.go is.
6// It knows the coverage counter is called
7// "thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest".
8
9package main
10
11import (
12	"fmt"
13	"os"
14)
15
16func main() {
17	testAll()
18	verify()
19}
20
21type block struct {
22	count uint32
23	line  uint32
24}
25
26var counters = make(map[block]bool)
27
28// shorthand for the long counter variable.
29var coverTest = &thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest
30
31// check records the location and expected value for a counter.
32func check(line, count uint32) {
33	b := block{
34		count,
35		line,
36	}
37	counters[b] = true
38}
39
40// checkVal is a version of check that returns its extra argument,
41// so it can be used in conditionals.
42func checkVal(line, count uint32, val int) int {
43	b := block{
44		count,
45		line,
46	}
47	counters[b] = true
48	return val
49}
50
51var PASS = true
52
53// verify checks the expected counts against the actual. It runs after the test has completed.
54func verify() {
55	for b := range counters {
56		got, index := count(b.line)
57		if b.count == anything && got != 0 {
58			got = anything
59		}
60		if got != b.count {
61			fmt.Fprintf(os.Stderr, "test_go:%d expected count %d got %d [counter %d]\n", b.line, b.count, got, index)
62			PASS = false
63		}
64	}
65	verifyPanic()
66	if !PASS {
67		fmt.Fprintf(os.Stderr, "FAIL\n")
68		os.Exit(2)
69	}
70}
71
72// verifyPanic is a special check for the known counter that should be
73// after the panic call in testPanic.
74func verifyPanic() {
75	if coverTest.Count[panicIndex-1] != 1 {
76		// Sanity check for test before panic.
77		fmt.Fprintf(os.Stderr, "bad before panic")
78		PASS = false
79	}
80	if coverTest.Count[panicIndex] != 0 {
81		fmt.Fprintf(os.Stderr, "bad at panic: %d should be 0\n", coverTest.Count[panicIndex])
82		PASS = false
83	}
84	if coverTest.Count[panicIndex+1] != 1 {
85		fmt.Fprintf(os.Stderr, "bad after panic")
86		PASS = false
87	}
88}
89
90// count returns the count and index for the counter at the specified line.
91func count(line uint32) (uint32, int) {
92	// Linear search is fine. Choose perfect fit over approximate.
93	// We can have a closing brace for a range on the same line as a condition for an "else if"
94	// and we don't want that brace to steal the count for the condition on the "if".
95	// Therefore we test for a perfect (lo==line && hi==line) match, but if we can't
96	// find that we take the first imperfect match.
97	index := -1
98	indexLo := uint32(1e9)
99	for i := range coverTest.Count {
100		lo, hi := coverTest.Pos[3*i], coverTest.Pos[3*i+1]
101		if lo == line && line == hi {
102			return coverTest.Count[i], i
103		}
104		// Choose the earliest match (the counters are in unpredictable order).
105		if lo <= line && line <= hi && indexLo > lo {
106			index = i
107			indexLo = lo
108		}
109	}
110	if index == -1 {
111		fmt.Fprintln(os.Stderr, "cover_test: no counter for line", line)
112		PASS = false
113		return 0, 0
114	}
115	return coverTest.Count[index], index
116}
117