1// This file contains just a few generic helpers which are used by the
2// other test files.
3
4package check_test
5
6import (
7	"flag"
8	"fmt"
9	"os"
10	"regexp"
11	"runtime"
12	"testing"
13	"time"
14
15	"gopkg.in/check.v1"
16)
17
18// We count the number of suites run at least to get a vague hint that the
19// test suite is behaving as it should.  Otherwise a bug introduced at the
20// very core of the system could go unperceived.
21const suitesRunExpected = 8
22
23var suitesRun int = 0
24
25func Test(t *testing.T) {
26	check.TestingT(t)
27	if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" {
28		critical(fmt.Sprintf("Expected %d suites to run rather than %d",
29			suitesRunExpected, suitesRun))
30	}
31}
32
33// -----------------------------------------------------------------------
34// Helper functions.
35
36// Break down badly.  This is used in test cases which can't yet assume
37// that the fundamental bits are working.
38func critical(error string) {
39	fmt.Fprintln(os.Stderr, "CRITICAL: "+error)
40	os.Exit(1)
41}
42
43// Return the file line where it's called.
44func getMyLine() int {
45	if _, _, line, ok := runtime.Caller(1); ok {
46		return line
47	}
48	return -1
49}
50
51// -----------------------------------------------------------------------
52// Helper type implementing a basic io.Writer for testing output.
53
54// Type implementing the io.Writer interface for analyzing output.
55type String struct {
56	value string
57}
58
59// The only function required by the io.Writer interface.  Will append
60// written data to the String.value string.
61func (s *String) Write(p []byte) (n int, err error) {
62	s.value += string(p)
63	return len(p), nil
64}
65
66// Trivial wrapper to test errors happening on a different file
67// than the test itself.
68func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) {
69	return c.Check(obtained, check.Equals, expected), getMyLine()
70}
71
72// -----------------------------------------------------------------------
73// Helper suite for testing basic fail behavior.
74
75type FailHelper struct {
76	testLine int
77}
78
79func (s *FailHelper) TestLogAndFail(c *check.C) {
80	s.testLine = getMyLine() - 1
81	c.Log("Expected failure!")
82	c.Fail()
83}
84
85// -----------------------------------------------------------------------
86// Helper suite for testing basic success behavior.
87
88type SuccessHelper struct{}
89
90func (s *SuccessHelper) TestLogAndSucceed(c *check.C) {
91	c.Log("Expected success!")
92}
93
94// -----------------------------------------------------------------------
95// Helper suite for testing ordering and behavior of fixture.
96
97type FixtureHelper struct {
98	calls   []string
99	panicOn string
100	skip    bool
101	skipOnN int
102	sleepOn string
103	sleep   time.Duration
104	bytes   int64
105}
106
107func (s *FixtureHelper) trace(name string, c *check.C) {
108	s.calls = append(s.calls, name)
109	if name == s.panicOn {
110		panic(name)
111	}
112	if s.sleep > 0 && s.sleepOn == name {
113		time.Sleep(s.sleep)
114	}
115	if s.skip && s.skipOnN == len(s.calls)-1 {
116		c.Skip("skipOnN == n")
117	}
118}
119
120func (s *FixtureHelper) SetUpSuite(c *check.C) {
121	s.trace("SetUpSuite", c)
122}
123
124func (s *FixtureHelper) TearDownSuite(c *check.C) {
125	s.trace("TearDownSuite", c)
126}
127
128func (s *FixtureHelper) SetUpTest(c *check.C) {
129	s.trace("SetUpTest", c)
130}
131
132func (s *FixtureHelper) TearDownTest(c *check.C) {
133	s.trace("TearDownTest", c)
134}
135
136func (s *FixtureHelper) Test1(c *check.C) {
137	s.trace("Test1", c)
138}
139
140func (s *FixtureHelper) Test2(c *check.C) {
141	s.trace("Test2", c)
142}
143
144func (s *FixtureHelper) Benchmark1(c *check.C) {
145	s.trace("Benchmark1", c)
146	for i := 0; i < c.N; i++ {
147		time.Sleep(s.sleep)
148	}
149}
150
151func (s *FixtureHelper) Benchmark2(c *check.C) {
152	s.trace("Benchmark2", c)
153	c.SetBytes(1024)
154	for i := 0; i < c.N; i++ {
155		time.Sleep(s.sleep)
156	}
157}
158
159func (s *FixtureHelper) Benchmark3(c *check.C) {
160	var x []int64
161	s.trace("Benchmark3", c)
162	for i := 0; i < c.N; i++ {
163		time.Sleep(s.sleep)
164		x = make([]int64, 5)
165		_ = x
166	}
167}
168
169// -----------------------------------------------------------------------
170// Helper which checks the state of the test and ensures that it matches
171// the given expectations.  Depends on c.Errorf() working, so shouldn't
172// be used to test this one function.
173
174type expectedState struct {
175	name   string
176	result interface{}
177	failed bool
178	log    string
179}
180
181// Verify the state of the test.  Note that since this also verifies if
182// the test is supposed to be in a failed state, no other checks should
183// be done in addition to what is being tested.
184func checkState(c *check.C, result interface{}, expected *expectedState) {
185	failed := c.Failed()
186	c.Succeed()
187	log := c.GetTestLog()
188	matched, matchError := regexp.MatchString("^"+expected.log+"$", log)
189	if matchError != nil {
190		c.Errorf("Error in matching expression used in testing %s: %v",
191			expected.name, matchError)
192	} else if !matched {
193		c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------",
194			expected.name, log, expected.log)
195	}
196	if result != expected.result {
197		c.Errorf("%s returned %#v rather than %#v",
198			expected.name, result, expected.result)
199	}
200	if failed != expected.failed {
201		if failed {
202			c.Errorf("%s has failed when it shouldn't", expected.name)
203		} else {
204			c.Errorf("%s has not failed when it should", expected.name)
205		}
206	}
207}
208