Browse code

Add gocheck to vendored deps

Signed-off-by: Alexander Morozov <lk4d4@docker.com>

Alexander Morozov authored on 2015/04/19 01:45:24
Showing 21 changed files
... ...
@@ -57,6 +57,8 @@ clone git github.com/Sirupsen/logrus v0.7.2
57 57
 
58 58
 clone git github.com/go-fsnotify/fsnotify v1.0.4
59 59
 
60
+clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673
61
+
60 62
 # get Go tip's archive/tar, for xattr support and improved performance
61 63
 # TODO after Go 1.4 drops, bump our minimum supported version and drop this vendored dep
62 64
 if [ "$1" = '--go' ]; then
63 65
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+_*
1
+*.swp
2
+*.[568]
3
+[568].out
0 4
new file mode 100644
... ...
@@ -0,0 +1,25 @@
0
+Gocheck - A rich testing framework for Go
1
+ 
2
+Copyright (c) 2010-2013 Gustavo Niemeyer <gustavo@niemeyer.net>
3
+
4
+All rights reserved.
5
+
6
+Redistribution and use in source and binary forms, with or without
7
+modification, are permitted provided that the following conditions are met: 
8
+
9
+1. Redistributions of source code must retain the above copyright notice, this
10
+   list of conditions and the following disclaimer. 
11
+2. Redistributions in binary form must reproduce the above copyright notice,
12
+   this list of conditions and the following disclaimer in the documentation
13
+   and/or other materials provided with the distribution. 
14
+
15
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 25
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+Instructions
1
+============
2
+
3
+Install the package with:
4
+
5
+    go get gopkg.in/check.v1
6
+    
7
+Import it with:
8
+
9
+    import "gopkg.in/check.v1"
10
+
11
+and use _check_ as the package name inside the code.
12
+
13
+For more details, visit the project page:
14
+
15
+* http://labix.org/gocheck
16
+
17
+and the API documentation:
18
+
19
+* https://gopkg.in/check.v1
0 20
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+- Assert(slice, Contains, item)
1
+- Parallel test support
0 2
new file mode 100644
... ...
@@ -0,0 +1,163 @@
0
+// Copyright 2009 The Go Authors. All rights reserved.
1
+// Use of this source code is governed by a BSD-style
2
+// license that can be found in the LICENSE file.
3
+
4
+package check
5
+
6
+import (
7
+	"fmt"
8
+	"runtime"
9
+	"time"
10
+)
11
+
12
+var memStats runtime.MemStats
13
+
14
+// testingB is a type passed to Benchmark functions to manage benchmark
15
+// timing and to specify the number of iterations to run.
16
+type timer struct {
17
+	start     time.Time // Time test or benchmark started
18
+	duration  time.Duration
19
+	N         int
20
+	bytes     int64
21
+	timerOn   bool
22
+	benchTime time.Duration
23
+	// The initial states of memStats.Mallocs and memStats.TotalAlloc.
24
+	startAllocs uint64
25
+	startBytes  uint64
26
+	// The net total of this test after being run.
27
+	netAllocs uint64
28
+	netBytes  uint64
29
+}
30
+
31
+// StartTimer starts timing a test. This function is called automatically
32
+// before a benchmark starts, but it can also used to resume timing after
33
+// a call to StopTimer.
34
+func (c *C) StartTimer() {
35
+	if !c.timerOn {
36
+		c.start = time.Now()
37
+		c.timerOn = true
38
+
39
+		runtime.ReadMemStats(&memStats)
40
+		c.startAllocs = memStats.Mallocs
41
+		c.startBytes = memStats.TotalAlloc
42
+	}
43
+}
44
+
45
+// StopTimer stops timing a test. This can be used to pause the timer
46
+// while performing complex initialization that you don't
47
+// want to measure.
48
+func (c *C) StopTimer() {
49
+	if c.timerOn {
50
+		c.duration += time.Now().Sub(c.start)
51
+		c.timerOn = false
52
+		runtime.ReadMemStats(&memStats)
53
+		c.netAllocs += memStats.Mallocs - c.startAllocs
54
+		c.netBytes += memStats.TotalAlloc - c.startBytes
55
+	}
56
+}
57
+
58
+// ResetTimer sets the elapsed benchmark time to zero.
59
+// It does not affect whether the timer is running.
60
+func (c *C) ResetTimer() {
61
+	if c.timerOn {
62
+		c.start = time.Now()
63
+		runtime.ReadMemStats(&memStats)
64
+		c.startAllocs = memStats.Mallocs
65
+		c.startBytes = memStats.TotalAlloc
66
+	}
67
+	c.duration = 0
68
+	c.netAllocs = 0
69
+	c.netBytes = 0
70
+}
71
+
72
+// SetBytes informs the number of bytes that the benchmark processes
73
+// on each iteration. If this is called in a benchmark it will also
74
+// report MB/s.
75
+func (c *C) SetBytes(n int64) {
76
+	c.bytes = n
77
+}
78
+
79
+func (c *C) nsPerOp() int64 {
80
+	if c.N <= 0 {
81
+		return 0
82
+	}
83
+	return c.duration.Nanoseconds() / int64(c.N)
84
+}
85
+
86
+func (c *C) mbPerSec() float64 {
87
+	if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 {
88
+		return 0
89
+	}
90
+	return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds()
91
+}
92
+
93
+func (c *C) timerString() string {
94
+	if c.N <= 0 {
95
+		return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9)
96
+	}
97
+	mbs := c.mbPerSec()
98
+	mb := ""
99
+	if mbs != 0 {
100
+		mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
101
+	}
102
+	nsop := c.nsPerOp()
103
+	ns := fmt.Sprintf("%10d ns/op", nsop)
104
+	if c.N > 0 && nsop < 100 {
105
+		// The format specifiers here make sure that
106
+		// the ones digits line up for all three possible formats.
107
+		if nsop < 10 {
108
+			ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N))
109
+		} else {
110
+			ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N))
111
+		}
112
+	}
113
+	memStats := ""
114
+	if c.benchMem {
115
+		allocedBytes := fmt.Sprintf("%8d B/op", int64(c.netBytes)/int64(c.N))
116
+		allocs := fmt.Sprintf("%8d allocs/op", int64(c.netAllocs)/int64(c.N))
117
+		memStats = fmt.Sprintf("\t%s\t%s", allocedBytes, allocs)
118
+	}
119
+	return fmt.Sprintf("%8d\t%s%s%s", c.N, ns, mb, memStats)
120
+}
121
+
122
+func min(x, y int) int {
123
+	if x > y {
124
+		return y
125
+	}
126
+	return x
127
+}
128
+
129
+func max(x, y int) int {
130
+	if x < y {
131
+		return y
132
+	}
133
+	return x
134
+}
135
+
136
+// roundDown10 rounds a number down to the nearest power of 10.
137
+func roundDown10(n int) int {
138
+	var tens = 0
139
+	// tens = floor(log_10(n))
140
+	for n > 10 {
141
+		n = n / 10
142
+		tens++
143
+	}
144
+	// result = 10^tens
145
+	result := 1
146
+	for i := 0; i < tens; i++ {
147
+		result *= 10
148
+	}
149
+	return result
150
+}
151
+
152
+// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
153
+func roundUp(n int) int {
154
+	base := roundDown10(n)
155
+	if n < (2 * base) {
156
+		return 2 * base
157
+	}
158
+	if n < (5 * base) {
159
+		return 5 * base
160
+	}
161
+	return 10 * base
162
+}
0 163
new file mode 100644
... ...
@@ -0,0 +1,91 @@
0
+// These tests verify the test running logic.
1
+
2
+package check_test
3
+
4
+import (
5
+	"time"
6
+	. "gopkg.in/check.v1"
7
+)
8
+
9
+var benchmarkS = Suite(&BenchmarkS{})
10
+
11
+type BenchmarkS struct{}
12
+
13
+func (s *BenchmarkS) TestCountSuite(c *C) {
14
+	suitesRun += 1
15
+}
16
+
17
+func (s *BenchmarkS) TestBasicTestTiming(c *C) {
18
+	helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond}
19
+	output := String{}
20
+	runConf := RunConf{Output: &output, Verbose: true}
21
+	Run(&helper, &runConf)
22
+
23
+	expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.001s\n" +
24
+		"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.000s\n"
25
+	c.Assert(output.value, Matches, expected)
26
+}
27
+
28
+func (s *BenchmarkS) TestStreamTestTiming(c *C) {
29
+	helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond}
30
+	output := String{}
31
+	runConf := RunConf{Output: &output, Stream: true}
32
+	Run(&helper, &runConf)
33
+
34
+	expected := "(?s).*\nPASS: check_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t *0\\.001s\n.*"
35
+	c.Assert(output.value, Matches, expected)
36
+}
37
+
38
+func (s *BenchmarkS) TestBenchmark(c *C) {
39
+	helper := FixtureHelper{sleep: 100000}
40
+	output := String{}
41
+	runConf := RunConf{
42
+		Output:        &output,
43
+		Benchmark:     true,
44
+		BenchmarkTime: 10000000,
45
+		Filter:        "Benchmark1",
46
+	}
47
+	Run(&helper, &runConf)
48
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
49
+	c.Check(helper.calls[1], Equals, "SetUpTest")
50
+	c.Check(helper.calls[2], Equals, "Benchmark1")
51
+	c.Check(helper.calls[3], Equals, "TearDownTest")
52
+	c.Check(helper.calls[4], Equals, "SetUpTest")
53
+	c.Check(helper.calls[5], Equals, "Benchmark1")
54
+	c.Check(helper.calls[6], Equals, "TearDownTest")
55
+	// ... and more.
56
+
57
+	expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t *100\t *[12][0-9]{5} ns/op\n"
58
+	c.Assert(output.value, Matches, expected)
59
+}
60
+
61
+func (s *BenchmarkS) TestBenchmarkBytes(c *C) {
62
+	helper := FixtureHelper{sleep: 100000}
63
+	output := String{}
64
+	runConf := RunConf{
65
+		Output:        &output,
66
+		Benchmark:     true,
67
+		BenchmarkTime: 10000000,
68
+		Filter:        "Benchmark2",
69
+	}
70
+	Run(&helper, &runConf)
71
+
72
+	expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t *100\t *[12][0-9]{5} ns/op\t *[4-9]\\.[0-9]{2} MB/s\n"
73
+	c.Assert(output.value, Matches, expected)
74
+}
75
+
76
+func (s *BenchmarkS) TestBenchmarkMem(c *C) {
77
+	helper := FixtureHelper{sleep: 100000}
78
+	output := String{}
79
+	runConf := RunConf{
80
+		Output:        &output,
81
+		Benchmark:     true,
82
+		BenchmarkMem:  true,
83
+		BenchmarkTime: 10000000,
84
+		Filter:        "Benchmark3",
85
+	}
86
+	Run(&helper, &runConf)
87
+
88
+	expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark3\t *100\t *[12][0-9]{5} ns/op\t *[0-9]+ B/op\t *[1-9] allocs/op\n"
89
+	c.Assert(output.value, Matches, expected)
90
+}
0 91
new file mode 100644
... ...
@@ -0,0 +1,82 @@
0
+// These initial tests are for bootstrapping.  They verify that we can
1
+// basically use the testing infrastructure itself to check if the test
2
+// system is working.
3
+//
4
+// These tests use will break down the test runner badly in case of
5
+// errors because if they simply fail, we can't be sure the developer
6
+// will ever see anything (because failing means the failing system
7
+// somehow isn't working! :-)
8
+//
9
+// Do not assume *any* internal functionality works as expected besides
10
+// what's actually tested here.
11
+
12
+package check_test
13
+
14
+import (
15
+	"fmt"
16
+	"gopkg.in/check.v1"
17
+	"strings"
18
+)
19
+
20
+type BootstrapS struct{}
21
+
22
+var boostrapS = check.Suite(&BootstrapS{})
23
+
24
+func (s *BootstrapS) TestCountSuite(c *check.C) {
25
+	suitesRun += 1
26
+}
27
+
28
+func (s *BootstrapS) TestFailedAndFail(c *check.C) {
29
+	if c.Failed() {
30
+		critical("c.Failed() must be false first!")
31
+	}
32
+	c.Fail()
33
+	if !c.Failed() {
34
+		critical("c.Fail() didn't put the test in a failed state!")
35
+	}
36
+	c.Succeed()
37
+}
38
+
39
+func (s *BootstrapS) TestFailedAndSucceed(c *check.C) {
40
+	c.Fail()
41
+	c.Succeed()
42
+	if c.Failed() {
43
+		critical("c.Succeed() didn't put the test back in a non-failed state")
44
+	}
45
+}
46
+
47
+func (s *BootstrapS) TestLogAndGetTestLog(c *check.C) {
48
+	c.Log("Hello there!")
49
+	log := c.GetTestLog()
50
+	if log != "Hello there!\n" {
51
+		critical(fmt.Sprintf("Log() or GetTestLog() is not working! Got: %#v", log))
52
+	}
53
+}
54
+
55
+func (s *BootstrapS) TestLogfAndGetTestLog(c *check.C) {
56
+	c.Logf("Hello %v", "there!")
57
+	log := c.GetTestLog()
58
+	if log != "Hello there!\n" {
59
+		critical(fmt.Sprintf("Logf() or GetTestLog() is not working! Got: %#v", log))
60
+	}
61
+}
62
+
63
+func (s *BootstrapS) TestRunShowsErrors(c *check.C) {
64
+	output := String{}
65
+	check.Run(&FailHelper{}, &check.RunConf{Output: &output})
66
+	if strings.Index(output.value, "Expected failure!") == -1 {
67
+		critical(fmt.Sprintf("RunWithWriter() output did not contain the "+
68
+			"expected failure! Got: %#v",
69
+			output.value))
70
+	}
71
+}
72
+
73
+func (s *BootstrapS) TestRunDoesntShowSuccesses(c *check.C) {
74
+	output := String{}
75
+	check.Run(&SuccessHelper{}, &check.RunConf{Output: &output})
76
+	if strings.Index(output.value, "Expected success!") != -1 {
77
+		critical(fmt.Sprintf("RunWithWriter() output contained a successful "+
78
+			"test! Got: %#v",
79
+			output.value))
80
+	}
81
+}
0 82
new file mode 100644
... ...
@@ -0,0 +1,945 @@
0
+// Package check is a rich testing extension for Go's testing package.
1
+//
2
+// For details about the project, see:
3
+//
4
+//     http://labix.org/gocheck
5
+//
6
+package check
7
+
8
+import (
9
+	"bytes"
10
+	"errors"
11
+	"fmt"
12
+	"io"
13
+	"math/rand"
14
+	"os"
15
+	"path"
16
+	"path/filepath"
17
+	"reflect"
18
+	"regexp"
19
+	"runtime"
20
+	"strconv"
21
+	"strings"
22
+	"sync"
23
+	"time"
24
+)
25
+
26
+// -----------------------------------------------------------------------
27
+// Internal type which deals with suite method calling.
28
+
29
+const (
30
+	fixtureKd = iota
31
+	testKd
32
+)
33
+
34
+type funcKind int
35
+
36
+const (
37
+	succeededSt = iota
38
+	failedSt
39
+	skippedSt
40
+	panickedSt
41
+	fixturePanickedSt
42
+	missedSt
43
+)
44
+
45
+type funcStatus int
46
+
47
+// A method value can't reach its own Method structure.
48
+type methodType struct {
49
+	reflect.Value
50
+	Info reflect.Method
51
+}
52
+
53
+func newMethod(receiver reflect.Value, i int) *methodType {
54
+	return &methodType{receiver.Method(i), receiver.Type().Method(i)}
55
+}
56
+
57
+func (method *methodType) PC() uintptr {
58
+	return method.Info.Func.Pointer()
59
+}
60
+
61
+func (method *methodType) suiteName() string {
62
+	t := method.Info.Type.In(0)
63
+	if t.Kind() == reflect.Ptr {
64
+		t = t.Elem()
65
+	}
66
+	return t.Name()
67
+}
68
+
69
+func (method *methodType) String() string {
70
+	return method.suiteName() + "." + method.Info.Name
71
+}
72
+
73
+func (method *methodType) matches(re *regexp.Regexp) bool {
74
+	return (re.MatchString(method.Info.Name) ||
75
+		re.MatchString(method.suiteName()) ||
76
+		re.MatchString(method.String()))
77
+}
78
+
79
+type C struct {
80
+	method    *methodType
81
+	kind      funcKind
82
+	testName  string
83
+	status    funcStatus
84
+	logb      *logger
85
+	logw      io.Writer
86
+	done      chan *C
87
+	reason    string
88
+	mustFail  bool
89
+	tempDir   *tempDir
90
+	benchMem  bool
91
+	startTime time.Time
92
+	timer
93
+}
94
+
95
+func (c *C) stopNow() {
96
+	runtime.Goexit()
97
+}
98
+
99
+// logger is a concurrency safe byte.Buffer
100
+type logger struct {
101
+	sync.Mutex
102
+	writer bytes.Buffer
103
+}
104
+
105
+func (l *logger) Write(buf []byte) (int, error) {
106
+	l.Lock()
107
+	defer l.Unlock()
108
+	return l.writer.Write(buf)
109
+}
110
+
111
+func (l *logger) WriteTo(w io.Writer) (int64, error) {
112
+	l.Lock()
113
+	defer l.Unlock()
114
+	return l.writer.WriteTo(w)
115
+}
116
+
117
+func (l *logger) String() string {
118
+	l.Lock()
119
+	defer l.Unlock()
120
+	return l.writer.String()
121
+}
122
+
123
+// -----------------------------------------------------------------------
124
+// Handling of temporary files and directories.
125
+
126
+type tempDir struct {
127
+	sync.Mutex
128
+	path    string
129
+	counter int
130
+}
131
+
132
+func (td *tempDir) newPath() string {
133
+	td.Lock()
134
+	defer td.Unlock()
135
+	if td.path == "" {
136
+		var err error
137
+		for i := 0; i != 100; i++ {
138
+			path := fmt.Sprintf("%s%ccheck-%d", os.TempDir(), os.PathSeparator, rand.Int())
139
+			if err = os.Mkdir(path, 0700); err == nil {
140
+				td.path = path
141
+				break
142
+			}
143
+		}
144
+		if td.path == "" {
145
+			panic("Couldn't create temporary directory: " + err.Error())
146
+		}
147
+	}
148
+	result := filepath.Join(td.path, strconv.Itoa(td.counter))
149
+	td.counter += 1
150
+	return result
151
+}
152
+
153
+func (td *tempDir) removeAll() {
154
+	td.Lock()
155
+	defer td.Unlock()
156
+	if td.path != "" {
157
+		err := os.RemoveAll(td.path)
158
+		if err != nil {
159
+			fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: "+err.Error())
160
+		}
161
+	}
162
+}
163
+
164
+// Create a new temporary directory which is automatically removed after
165
+// the suite finishes running.
166
+func (c *C) MkDir() string {
167
+	path := c.tempDir.newPath()
168
+	if err := os.Mkdir(path, 0700); err != nil {
169
+		panic(fmt.Sprintf("Couldn't create temporary directory %s: %s", path, err.Error()))
170
+	}
171
+	return path
172
+}
173
+
174
+// -----------------------------------------------------------------------
175
+// Low-level logging functions.
176
+
177
+func (c *C) log(args ...interface{}) {
178
+	c.writeLog([]byte(fmt.Sprint(args...) + "\n"))
179
+}
180
+
181
+func (c *C) logf(format string, args ...interface{}) {
182
+	c.writeLog([]byte(fmt.Sprintf(format+"\n", args...)))
183
+}
184
+
185
+func (c *C) logNewLine() {
186
+	c.writeLog([]byte{'\n'})
187
+}
188
+
189
+func (c *C) writeLog(buf []byte) {
190
+	c.logb.Write(buf)
191
+	if c.logw != nil {
192
+		c.logw.Write(buf)
193
+	}
194
+}
195
+
196
+func hasStringOrError(x interface{}) (ok bool) {
197
+	_, ok = x.(fmt.Stringer)
198
+	if ok {
199
+		return
200
+	}
201
+	_, ok = x.(error)
202
+	return
203
+}
204
+
205
+func (c *C) logValue(label string, value interface{}) {
206
+	if label == "" {
207
+		if hasStringOrError(value) {
208
+			c.logf("... %#v (%q)", value, value)
209
+		} else {
210
+			c.logf("... %#v", value)
211
+		}
212
+	} else if value == nil {
213
+		c.logf("... %s = nil", label)
214
+	} else {
215
+		if hasStringOrError(value) {
216
+			fv := fmt.Sprintf("%#v", value)
217
+			qv := fmt.Sprintf("%q", value)
218
+			if fv != qv {
219
+				c.logf("... %s %s = %s (%s)", label, reflect.TypeOf(value), fv, qv)
220
+				return
221
+			}
222
+		}
223
+		if s, ok := value.(string); ok && isMultiLine(s) {
224
+			c.logf(`... %s %s = "" +`, label, reflect.TypeOf(value))
225
+			c.logMultiLine(s)
226
+		} else {
227
+			c.logf("... %s %s = %#v", label, reflect.TypeOf(value), value)
228
+		}
229
+	}
230
+}
231
+
232
+func (c *C) logMultiLine(s string) {
233
+	b := make([]byte, 0, len(s)*2)
234
+	i := 0
235
+	n := len(s)
236
+	for i < n {
237
+		j := i + 1
238
+		for j < n && s[j-1] != '\n' {
239
+			j++
240
+		}
241
+		b = append(b, "...     "...)
242
+		b = strconv.AppendQuote(b, s[i:j])
243
+		if j < n {
244
+			b = append(b, " +"...)
245
+		}
246
+		b = append(b, '\n')
247
+		i = j
248
+	}
249
+	c.writeLog(b)
250
+}
251
+
252
+func isMultiLine(s string) bool {
253
+	for i := 0; i+1 < len(s); i++ {
254
+		if s[i] == '\n' {
255
+			return true
256
+		}
257
+	}
258
+	return false
259
+}
260
+
261
+func (c *C) logString(issue string) {
262
+	c.log("... ", issue)
263
+}
264
+
265
+func (c *C) logCaller(skip int) {
266
+	// This is a bit heavier than it ought to be.
267
+	skip += 1 // Our own frame.
268
+	pc, callerFile, callerLine, ok := runtime.Caller(skip)
269
+	if !ok {
270
+		return
271
+	}
272
+	var testFile string
273
+	var testLine int
274
+	testFunc := runtime.FuncForPC(c.method.PC())
275
+	if runtime.FuncForPC(pc) != testFunc {
276
+		for {
277
+			skip += 1
278
+			if pc, file, line, ok := runtime.Caller(skip); ok {
279
+				// Note that the test line may be different on
280
+				// distinct calls for the same test.  Showing
281
+				// the "internal" line is helpful when debugging.
282
+				if runtime.FuncForPC(pc) == testFunc {
283
+					testFile, testLine = file, line
284
+					break
285
+				}
286
+			} else {
287
+				break
288
+			}
289
+		}
290
+	}
291
+	if testFile != "" && (testFile != callerFile || testLine != callerLine) {
292
+		c.logCode(testFile, testLine)
293
+	}
294
+	c.logCode(callerFile, callerLine)
295
+}
296
+
297
+func (c *C) logCode(path string, line int) {
298
+	c.logf("%s:%d:", nicePath(path), line)
299
+	code, err := printLine(path, line)
300
+	if code == "" {
301
+		code = "..." // XXX Open the file and take the raw line.
302
+		if err != nil {
303
+			code += err.Error()
304
+		}
305
+	}
306
+	c.log(indent(code, "    "))
307
+}
308
+
309
+var valueGo = filepath.Join("reflect", "value.go")
310
+var asmGo = filepath.Join("runtime", "asm_")
311
+
312
+func (c *C) logPanic(skip int, value interface{}) {
313
+	skip++ // Our own frame.
314
+	initialSkip := skip
315
+	for ; ; skip++ {
316
+		if pc, file, line, ok := runtime.Caller(skip); ok {
317
+			if skip == initialSkip {
318
+				c.logf("... Panic: %s (PC=0x%X)\n", value, pc)
319
+			}
320
+			name := niceFuncName(pc)
321
+			path := nicePath(file)
322
+			if strings.Contains(path, "/gopkg.in/check.v") {
323
+				continue
324
+			}
325
+			if name == "Value.call" && strings.HasSuffix(path, valueGo) {
326
+				continue
327
+			}
328
+			if name == "call16" && strings.Contains(path, asmGo) {
329
+				continue
330
+			}
331
+			c.logf("%s:%d\n  in %s", nicePath(file), line, name)
332
+		} else {
333
+			break
334
+		}
335
+	}
336
+}
337
+
338
+func (c *C) logSoftPanic(issue string) {
339
+	c.log("... Panic: ", issue)
340
+}
341
+
342
+func (c *C) logArgPanic(method *methodType, expectedType string) {
343
+	c.logf("... Panic: %s argument should be %s",
344
+		niceFuncName(method.PC()), expectedType)
345
+}
346
+
347
+// -----------------------------------------------------------------------
348
+// Some simple formatting helpers.
349
+
350
+var initWD, initWDErr = os.Getwd()
351
+
352
+func init() {
353
+	if initWDErr == nil {
354
+		initWD = strings.Replace(initWD, "\\", "/", -1) + "/"
355
+	}
356
+}
357
+
358
+func nicePath(path string) string {
359
+	if initWDErr == nil {
360
+		if strings.HasPrefix(path, initWD) {
361
+			return path[len(initWD):]
362
+		}
363
+	}
364
+	return path
365
+}
366
+
367
+func niceFuncPath(pc uintptr) string {
368
+	function := runtime.FuncForPC(pc)
369
+	if function != nil {
370
+		filename, line := function.FileLine(pc)
371
+		return fmt.Sprintf("%s:%d", nicePath(filename), line)
372
+	}
373
+	return "<unknown path>"
374
+}
375
+
376
+func niceFuncName(pc uintptr) string {
377
+	function := runtime.FuncForPC(pc)
378
+	if function != nil {
379
+		name := path.Base(function.Name())
380
+		if i := strings.Index(name, "."); i > 0 {
381
+			name = name[i+1:]
382
+		}
383
+		if strings.HasPrefix(name, "(*") {
384
+			if i := strings.Index(name, ")"); i > 0 {
385
+				name = name[2:i] + name[i+1:]
386
+			}
387
+		}
388
+		if i := strings.LastIndex(name, ".*"); i != -1 {
389
+			name = name[:i] + "." + name[i+2:]
390
+		}
391
+		if i := strings.LastIndex(name, "·"); i != -1 {
392
+			name = name[:i] + "." + name[i+2:]
393
+		}
394
+		return name
395
+	}
396
+	return "<unknown function>"
397
+}
398
+
399
+// -----------------------------------------------------------------------
400
+// Result tracker to aggregate call results.
401
+
402
+type Result struct {
403
+	Succeeded        int
404
+	Failed           int
405
+	Skipped          int
406
+	Panicked         int
407
+	FixturePanicked  int
408
+	ExpectedFailures int
409
+	Missed           int    // Not even tried to run, related to a panic in the fixture.
410
+	RunError         error  // Houston, we've got a problem.
411
+	WorkDir          string // If KeepWorkDir is true
412
+}
413
+
414
+type resultTracker struct {
415
+	result          Result
416
+	_lastWasProblem bool
417
+	_waiting        int
418
+	_missed         int
419
+	_expectChan     chan *C
420
+	_doneChan       chan *C
421
+	_stopChan       chan bool
422
+}
423
+
424
+func newResultTracker() *resultTracker {
425
+	return &resultTracker{_expectChan: make(chan *C), // Synchronous
426
+		_doneChan: make(chan *C, 32), // Asynchronous
427
+		_stopChan: make(chan bool)}   // Synchronous
428
+}
429
+
430
+func (tracker *resultTracker) start() {
431
+	go tracker._loopRoutine()
432
+}
433
+
434
+func (tracker *resultTracker) waitAndStop() {
435
+	<-tracker._stopChan
436
+}
437
+
438
+func (tracker *resultTracker) expectCall(c *C) {
439
+	tracker._expectChan <- c
440
+}
441
+
442
+func (tracker *resultTracker) callDone(c *C) {
443
+	tracker._doneChan <- c
444
+}
445
+
446
+func (tracker *resultTracker) _loopRoutine() {
447
+	for {
448
+		var c *C
449
+		if tracker._waiting > 0 {
450
+			// Calls still running. Can't stop.
451
+			select {
452
+			// XXX Reindent this (not now to make diff clear)
453
+			case c = <-tracker._expectChan:
454
+				tracker._waiting += 1
455
+			case c = <-tracker._doneChan:
456
+				tracker._waiting -= 1
457
+				switch c.status {
458
+				case succeededSt:
459
+					if c.kind == testKd {
460
+						if c.mustFail {
461
+							tracker.result.ExpectedFailures++
462
+						} else {
463
+							tracker.result.Succeeded++
464
+						}
465
+					}
466
+				case failedSt:
467
+					tracker.result.Failed++
468
+				case panickedSt:
469
+					if c.kind == fixtureKd {
470
+						tracker.result.FixturePanicked++
471
+					} else {
472
+						tracker.result.Panicked++
473
+					}
474
+				case fixturePanickedSt:
475
+					// Track it as missed, since the panic
476
+					// was on the fixture, not on the test.
477
+					tracker.result.Missed++
478
+				case missedSt:
479
+					tracker.result.Missed++
480
+				case skippedSt:
481
+					if c.kind == testKd {
482
+						tracker.result.Skipped++
483
+					}
484
+				}
485
+			}
486
+		} else {
487
+			// No calls.  Can stop, but no done calls here.
488
+			select {
489
+			case tracker._stopChan <- true:
490
+				return
491
+			case c = <-tracker._expectChan:
492
+				tracker._waiting += 1
493
+			case c = <-tracker._doneChan:
494
+				panic("Tracker got an unexpected done call.")
495
+			}
496
+		}
497
+	}
498
+}
499
+
500
+// -----------------------------------------------------------------------
501
+// The underlying suite runner.
502
+
503
+type suiteRunner struct {
504
+	suite                     interface{}
505
+	setUpSuite, tearDownSuite *methodType
506
+	setUpTest, tearDownTest   *methodType
507
+	tests                     []*methodType
508
+	tracker                   *resultTracker
509
+	tempDir                   *tempDir
510
+	keepDir                   bool
511
+	output                    *outputWriter
512
+	reportedProblemLast       bool
513
+	benchTime                 time.Duration
514
+	benchMem                  bool
515
+}
516
+
517
+type RunConf struct {
518
+	Output        io.Writer
519
+	Stream        bool
520
+	Verbose       bool
521
+	Filter        string
522
+	Benchmark     bool
523
+	BenchmarkTime time.Duration // Defaults to 1 second
524
+	BenchmarkMem  bool
525
+	KeepWorkDir   bool
526
+}
527
+
528
+// Create a new suiteRunner able to run all methods in the given suite.
529
+func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner {
530
+	var conf RunConf
531
+	if runConf != nil {
532
+		conf = *runConf
533
+	}
534
+	if conf.Output == nil {
535
+		conf.Output = os.Stdout
536
+	}
537
+	if conf.Benchmark {
538
+		conf.Verbose = true
539
+	}
540
+
541
+	suiteType := reflect.TypeOf(suite)
542
+	suiteNumMethods := suiteType.NumMethod()
543
+	suiteValue := reflect.ValueOf(suite)
544
+
545
+	runner := &suiteRunner{
546
+		suite:     suite,
547
+		output:    newOutputWriter(conf.Output, conf.Stream, conf.Verbose),
548
+		tracker:   newResultTracker(),
549
+		benchTime: conf.BenchmarkTime,
550
+		benchMem:  conf.BenchmarkMem,
551
+		tempDir:   &tempDir{},
552
+		keepDir:   conf.KeepWorkDir,
553
+		tests:     make([]*methodType, 0, suiteNumMethods),
554
+	}
555
+	if runner.benchTime == 0 {
556
+		runner.benchTime = 1 * time.Second
557
+	}
558
+
559
+	var filterRegexp *regexp.Regexp
560
+	if conf.Filter != "" {
561
+		if regexp, err := regexp.Compile(conf.Filter); err != nil {
562
+			msg := "Bad filter expression: " + err.Error()
563
+			runner.tracker.result.RunError = errors.New(msg)
564
+			return runner
565
+		} else {
566
+			filterRegexp = regexp
567
+		}
568
+	}
569
+
570
+	for i := 0; i != suiteNumMethods; i++ {
571
+		method := newMethod(suiteValue, i)
572
+		switch method.Info.Name {
573
+		case "SetUpSuite":
574
+			runner.setUpSuite = method
575
+		case "TearDownSuite":
576
+			runner.tearDownSuite = method
577
+		case "SetUpTest":
578
+			runner.setUpTest = method
579
+		case "TearDownTest":
580
+			runner.tearDownTest = method
581
+		default:
582
+			prefix := "Test"
583
+			if conf.Benchmark {
584
+				prefix = "Benchmark"
585
+			}
586
+			if !strings.HasPrefix(method.Info.Name, prefix) {
587
+				continue
588
+			}
589
+			if filterRegexp == nil || method.matches(filterRegexp) {
590
+				runner.tests = append(runner.tests, method)
591
+			}
592
+		}
593
+	}
594
+	return runner
595
+}
596
+
597
+// Run all methods in the given suite.
598
+func (runner *suiteRunner) run() *Result {
599
+	if runner.tracker.result.RunError == nil && len(runner.tests) > 0 {
600
+		runner.tracker.start()
601
+		if runner.checkFixtureArgs() {
602
+			c := runner.runFixture(runner.setUpSuite, "", nil)
603
+			if c == nil || c.status == succeededSt {
604
+				for i := 0; i != len(runner.tests); i++ {
605
+					c := runner.runTest(runner.tests[i])
606
+					if c.status == fixturePanickedSt {
607
+						runner.skipTests(missedSt, runner.tests[i+1:])
608
+						break
609
+					}
610
+				}
611
+			} else if c != nil && c.status == skippedSt {
612
+				runner.skipTests(skippedSt, runner.tests)
613
+			} else {
614
+				runner.skipTests(missedSt, runner.tests)
615
+			}
616
+			runner.runFixture(runner.tearDownSuite, "", nil)
617
+		} else {
618
+			runner.skipTests(missedSt, runner.tests)
619
+		}
620
+		runner.tracker.waitAndStop()
621
+		if runner.keepDir {
622
+			runner.tracker.result.WorkDir = runner.tempDir.path
623
+		} else {
624
+			runner.tempDir.removeAll()
625
+		}
626
+	}
627
+	return &runner.tracker.result
628
+}
629
+
630
+// Create a call object with the given suite method, and fork a
631
+// goroutine with the provided dispatcher for running it.
632
+func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C {
633
+	var logw io.Writer
634
+	if runner.output.Stream {
635
+		logw = runner.output
636
+	}
637
+	if logb == nil {
638
+		logb = new(logger)
639
+	}
640
+	c := &C{
641
+		method:    method,
642
+		kind:      kind,
643
+		testName:  testName,
644
+		logb:      logb,
645
+		logw:      logw,
646
+		tempDir:   runner.tempDir,
647
+		done:      make(chan *C, 1),
648
+		timer:     timer{benchTime: runner.benchTime},
649
+		startTime: time.Now(),
650
+		benchMem:  runner.benchMem,
651
+	}
652
+	runner.tracker.expectCall(c)
653
+	go (func() {
654
+		runner.reportCallStarted(c)
655
+		defer runner.callDone(c)
656
+		dispatcher(c)
657
+	})()
658
+	return c
659
+}
660
+
661
+// Same as forkCall(), but wait for call to finish before returning.
662
+func (runner *suiteRunner) runFunc(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C {
663
+	c := runner.forkCall(method, kind, testName, logb, dispatcher)
664
+	<-c.done
665
+	return c
666
+}
667
+
668
+// Handle a finished call.  If there were any panics, update the call status
669
+// accordingly.  Then, mark the call as done and report to the tracker.
670
+func (runner *suiteRunner) callDone(c *C) {
671
+	value := recover()
672
+	if value != nil {
673
+		switch v := value.(type) {
674
+		case *fixturePanic:
675
+			if v.status == skippedSt {
676
+				c.status = skippedSt
677
+			} else {
678
+				c.logSoftPanic("Fixture has panicked (see related PANIC)")
679
+				c.status = fixturePanickedSt
680
+			}
681
+		default:
682
+			c.logPanic(1, value)
683
+			c.status = panickedSt
684
+		}
685
+	}
686
+	if c.mustFail {
687
+		switch c.status {
688
+		case failedSt:
689
+			c.status = succeededSt
690
+		case succeededSt:
691
+			c.status = failedSt
692
+			c.logString("Error: Test succeeded, but was expected to fail")
693
+			c.logString("Reason: " + c.reason)
694
+		}
695
+	}
696
+
697
+	runner.reportCallDone(c)
698
+	c.done <- c
699
+}
700
+
701
+// Runs a fixture call synchronously.  The fixture will still be run in a
702
+// goroutine like all suite methods, but this method will not return
703
+// while the fixture goroutine is not done, because the fixture must be
704
+// run in a desired order.
705
+func (runner *suiteRunner) runFixture(method *methodType, testName string, logb *logger) *C {
706
+	if method != nil {
707
+		c := runner.runFunc(method, fixtureKd, testName, logb, func(c *C) {
708
+			c.ResetTimer()
709
+			c.StartTimer()
710
+			defer c.StopTimer()
711
+			c.method.Call([]reflect.Value{reflect.ValueOf(c)})
712
+		})
713
+		return c
714
+	}
715
+	return nil
716
+}
717
+
718
+// Run the fixture method with runFixture(), but panic with a fixturePanic{}
719
+// in case the fixture method panics.  This makes it easier to track the
720
+// fixture panic together with other call panics within forkTest().
721
+func (runner *suiteRunner) runFixtureWithPanic(method *methodType, testName string, logb *logger, skipped *bool) *C {
722
+	if skipped != nil && *skipped {
723
+		return nil
724
+	}
725
+	c := runner.runFixture(method, testName, logb)
726
+	if c != nil && c.status != succeededSt {
727
+		if skipped != nil {
728
+			*skipped = c.status == skippedSt
729
+		}
730
+		panic(&fixturePanic{c.status, method})
731
+	}
732
+	return c
733
+}
734
+
735
+type fixturePanic struct {
736
+	status funcStatus
737
+	method *methodType
738
+}
739
+
740
+// Run the suite test method, together with the test-specific fixture,
741
+// asynchronously.
742
+func (runner *suiteRunner) forkTest(method *methodType) *C {
743
+	testName := method.String()
744
+	return runner.forkCall(method, testKd, testName, nil, func(c *C) {
745
+		var skipped bool
746
+		defer runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, &skipped)
747
+		defer c.StopTimer()
748
+		benchN := 1
749
+		for {
750
+			runner.runFixtureWithPanic(runner.setUpTest, testName, c.logb, &skipped)
751
+			mt := c.method.Type()
752
+			if mt.NumIn() != 1 || mt.In(0) != reflect.TypeOf(c) {
753
+				// Rather than a plain panic, provide a more helpful message when
754
+				// the argument type is incorrect.
755
+				c.status = panickedSt
756
+				c.logArgPanic(c.method, "*check.C")
757
+				return
758
+			}
759
+			if strings.HasPrefix(c.method.Info.Name, "Test") {
760
+				c.ResetTimer()
761
+				c.StartTimer()
762
+				c.method.Call([]reflect.Value{reflect.ValueOf(c)})
763
+				return
764
+			}
765
+			if !strings.HasPrefix(c.method.Info.Name, "Benchmark") {
766
+				panic("unexpected method prefix: " + c.method.Info.Name)
767
+			}
768
+
769
+			runtime.GC()
770
+			c.N = benchN
771
+			c.ResetTimer()
772
+			c.StartTimer()
773
+			c.method.Call([]reflect.Value{reflect.ValueOf(c)})
774
+			c.StopTimer()
775
+			if c.status != succeededSt || c.duration >= c.benchTime || benchN >= 1e9 {
776
+				return
777
+			}
778
+			perOpN := int(1e9)
779
+			if c.nsPerOp() != 0 {
780
+				perOpN = int(c.benchTime.Nanoseconds() / c.nsPerOp())
781
+			}
782
+
783
+			// Logic taken from the stock testing package:
784
+			// - Run more iterations than we think we'll need for a second (1.5x).
785
+			// - Don't grow too fast in case we had timing errors previously.
786
+			// - Be sure to run at least one more than last time.
787
+			benchN = max(min(perOpN+perOpN/2, 100*benchN), benchN+1)
788
+			benchN = roundUp(benchN)
789
+
790
+			skipped = true // Don't run the deferred one if this panics.
791
+			runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, nil)
792
+			skipped = false
793
+		}
794
+	})
795
+}
796
+
797
+// Same as forkTest(), but wait for the test to finish before returning.
798
+func (runner *suiteRunner) runTest(method *methodType) *C {
799
+	c := runner.forkTest(method)
800
+	<-c.done
801
+	return c
802
+}
803
+
804
+// Helper to mark tests as skipped or missed.  A bit heavy for what
805
+// it does, but it enables homogeneous handling of tracking, including
806
+// nice verbose output.
807
+func (runner *suiteRunner) skipTests(status funcStatus, methods []*methodType) {
808
+	for _, method := range methods {
809
+		runner.runFunc(method, testKd, "", nil, func(c *C) {
810
+			c.status = status
811
+		})
812
+	}
813
+}
814
+
815
+// Verify if the fixture arguments are *check.C.  In case of errors,
816
+// log the error as a panic in the fixture method call, and return false.
817
+func (runner *suiteRunner) checkFixtureArgs() bool {
818
+	succeeded := true
819
+	argType := reflect.TypeOf(&C{})
820
+	for _, method := range []*methodType{runner.setUpSuite, runner.tearDownSuite, runner.setUpTest, runner.tearDownTest} {
821
+		if method != nil {
822
+			mt := method.Type()
823
+			if mt.NumIn() != 1 || mt.In(0) != argType {
824
+				succeeded = false
825
+				runner.runFunc(method, fixtureKd, "", nil, func(c *C) {
826
+					c.logArgPanic(method, "*check.C")
827
+					c.status = panickedSt
828
+				})
829
+			}
830
+		}
831
+	}
832
+	return succeeded
833
+}
834
+
835
+func (runner *suiteRunner) reportCallStarted(c *C) {
836
+	runner.output.WriteCallStarted("START", c)
837
+}
838
+
839
+func (runner *suiteRunner) reportCallDone(c *C) {
840
+	runner.tracker.callDone(c)
841
+	switch c.status {
842
+	case succeededSt:
843
+		if c.mustFail {
844
+			runner.output.WriteCallSuccess("FAIL EXPECTED", c)
845
+		} else {
846
+			runner.output.WriteCallSuccess("PASS", c)
847
+		}
848
+	case skippedSt:
849
+		runner.output.WriteCallSuccess("SKIP", c)
850
+	case failedSt:
851
+		runner.output.WriteCallProblem("FAIL", c)
852
+	case panickedSt:
853
+		runner.output.WriteCallProblem("PANIC", c)
854
+	case fixturePanickedSt:
855
+		// That's a testKd call reporting that its fixture
856
+		// has panicked. The fixture call which caused the
857
+		// panic itself was tracked above. We'll report to
858
+		// aid debugging.
859
+		runner.output.WriteCallProblem("PANIC", c)
860
+	case missedSt:
861
+		runner.output.WriteCallSuccess("MISS", c)
862
+	}
863
+}
864
+
865
+// -----------------------------------------------------------------------
866
+// Output writer manages atomic output writing according to settings.
867
+
868
+type outputWriter struct {
869
+	m                    sync.Mutex
870
+	writer               io.Writer
871
+	wroteCallProblemLast bool
872
+	Stream               bool
873
+	Verbose              bool
874
+}
875
+
876
+func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter {
877
+	return &outputWriter{writer: writer, Stream: stream, Verbose: verbose}
878
+}
879
+
880
+func (ow *outputWriter) Write(content []byte) (n int, err error) {
881
+	ow.m.Lock()
882
+	n, err = ow.writer.Write(content)
883
+	ow.m.Unlock()
884
+	return
885
+}
886
+
887
+func (ow *outputWriter) WriteCallStarted(label string, c *C) {
888
+	if ow.Stream {
889
+		header := renderCallHeader(label, c, "", "\n")
890
+		ow.m.Lock()
891
+		ow.writer.Write([]byte(header))
892
+		ow.m.Unlock()
893
+	}
894
+}
895
+
896
+func (ow *outputWriter) WriteCallProblem(label string, c *C) {
897
+	var prefix string
898
+	if !ow.Stream {
899
+		prefix = "\n-----------------------------------" +
900
+			"-----------------------------------\n"
901
+	}
902
+	header := renderCallHeader(label, c, prefix, "\n\n")
903
+	ow.m.Lock()
904
+	ow.wroteCallProblemLast = true
905
+	ow.writer.Write([]byte(header))
906
+	if !ow.Stream {
907
+		c.logb.WriteTo(ow.writer)
908
+	}
909
+	ow.m.Unlock()
910
+}
911
+
912
+func (ow *outputWriter) WriteCallSuccess(label string, c *C) {
913
+	if ow.Stream || (ow.Verbose && c.kind == testKd) {
914
+		// TODO Use a buffer here.
915
+		var suffix string
916
+		if c.reason != "" {
917
+			suffix = " (" + c.reason + ")"
918
+		}
919
+		if c.status == succeededSt {
920
+			suffix += "\t" + c.timerString()
921
+		}
922
+		suffix += "\n"
923
+		if ow.Stream {
924
+			suffix += "\n"
925
+		}
926
+		header := renderCallHeader(label, c, "", suffix)
927
+		ow.m.Lock()
928
+		// Resist temptation of using line as prefix above due to race.
929
+		if !ow.Stream && ow.wroteCallProblemLast {
930
+			header = "\n-----------------------------------" +
931
+				"-----------------------------------\n" +
932
+				header
933
+		}
934
+		ow.wroteCallProblemLast = false
935
+		ow.writer.Write([]byte(header))
936
+		ow.m.Unlock()
937
+	}
938
+}
939
+
940
+func renderCallHeader(label string, c *C, prefix, suffix string) string {
941
+	pc := c.method.PC()
942
+	return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc),
943
+		niceFuncName(pc), suffix)
944
+}
0 945
new file mode 100644
... ...
@@ -0,0 +1,207 @@
0
+// This file contains just a few generic helpers which are used by the
1
+// other test files.
2
+
3
+package check_test
4
+
5
+import (
6
+	"flag"
7
+	"fmt"
8
+	"os"
9
+	"regexp"
10
+	"runtime"
11
+	"testing"
12
+	"time"
13
+
14
+	"gopkg.in/check.v1"
15
+)
16
+
17
+// We count the number of suites run at least to get a vague hint that the
18
+// test suite is behaving as it should.  Otherwise a bug introduced at the
19
+// very core of the system could go unperceived.
20
+const suitesRunExpected = 8
21
+
22
+var suitesRun int = 0
23
+
24
+func Test(t *testing.T) {
25
+	check.TestingT(t)
26
+	if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" {
27
+		critical(fmt.Sprintf("Expected %d suites to run rather than %d",
28
+			suitesRunExpected, suitesRun))
29
+	}
30
+}
31
+
32
+// -----------------------------------------------------------------------
33
+// Helper functions.
34
+
35
+// Break down badly.  This is used in test cases which can't yet assume
36
+// that the fundamental bits are working.
37
+func critical(error string) {
38
+	fmt.Fprintln(os.Stderr, "CRITICAL: "+error)
39
+	os.Exit(1)
40
+}
41
+
42
+// Return the file line where it's called.
43
+func getMyLine() int {
44
+	if _, _, line, ok := runtime.Caller(1); ok {
45
+		return line
46
+	}
47
+	return -1
48
+}
49
+
50
+// -----------------------------------------------------------------------
51
+// Helper type implementing a basic io.Writer for testing output.
52
+
53
+// Type implementing the io.Writer interface for analyzing output.
54
+type String struct {
55
+	value string
56
+}
57
+
58
+// The only function required by the io.Writer interface.  Will append
59
+// written data to the String.value string.
60
+func (s *String) Write(p []byte) (n int, err error) {
61
+	s.value += string(p)
62
+	return len(p), nil
63
+}
64
+
65
+// Trivial wrapper to test errors happening on a different file
66
+// than the test itself.
67
+func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) {
68
+	return c.Check(obtained, check.Equals, expected), getMyLine()
69
+}
70
+
71
+// -----------------------------------------------------------------------
72
+// Helper suite for testing basic fail behavior.
73
+
74
+type FailHelper struct {
75
+	testLine int
76
+}
77
+
78
+func (s *FailHelper) TestLogAndFail(c *check.C) {
79
+	s.testLine = getMyLine() - 1
80
+	c.Log("Expected failure!")
81
+	c.Fail()
82
+}
83
+
84
+// -----------------------------------------------------------------------
85
+// Helper suite for testing basic success behavior.
86
+
87
+type SuccessHelper struct{}
88
+
89
+func (s *SuccessHelper) TestLogAndSucceed(c *check.C) {
90
+	c.Log("Expected success!")
91
+}
92
+
93
+// -----------------------------------------------------------------------
94
+// Helper suite for testing ordering and behavior of fixture.
95
+
96
+type FixtureHelper struct {
97
+	calls   []string
98
+	panicOn string
99
+	skip    bool
100
+	skipOnN int
101
+	sleepOn string
102
+	sleep   time.Duration
103
+	bytes   int64
104
+}
105
+
106
+func (s *FixtureHelper) trace(name string, c *check.C) {
107
+	s.calls = append(s.calls, name)
108
+	if name == s.panicOn {
109
+		panic(name)
110
+	}
111
+	if s.sleep > 0 && s.sleepOn == name {
112
+		time.Sleep(s.sleep)
113
+	}
114
+	if s.skip && s.skipOnN == len(s.calls)-1 {
115
+		c.Skip("skipOnN == n")
116
+	}
117
+}
118
+
119
+func (s *FixtureHelper) SetUpSuite(c *check.C) {
120
+	s.trace("SetUpSuite", c)
121
+}
122
+
123
+func (s *FixtureHelper) TearDownSuite(c *check.C) {
124
+	s.trace("TearDownSuite", c)
125
+}
126
+
127
+func (s *FixtureHelper) SetUpTest(c *check.C) {
128
+	s.trace("SetUpTest", c)
129
+}
130
+
131
+func (s *FixtureHelper) TearDownTest(c *check.C) {
132
+	s.trace("TearDownTest", c)
133
+}
134
+
135
+func (s *FixtureHelper) Test1(c *check.C) {
136
+	s.trace("Test1", c)
137
+}
138
+
139
+func (s *FixtureHelper) Test2(c *check.C) {
140
+	s.trace("Test2", c)
141
+}
142
+
143
+func (s *FixtureHelper) Benchmark1(c *check.C) {
144
+	s.trace("Benchmark1", c)
145
+	for i := 0; i < c.N; i++ {
146
+		time.Sleep(s.sleep)
147
+	}
148
+}
149
+
150
+func (s *FixtureHelper) Benchmark2(c *check.C) {
151
+	s.trace("Benchmark2", c)
152
+	c.SetBytes(1024)
153
+	for i := 0; i < c.N; i++ {
154
+		time.Sleep(s.sleep)
155
+	}
156
+}
157
+
158
+func (s *FixtureHelper) Benchmark3(c *check.C) {
159
+	var x []int64
160
+	s.trace("Benchmark3", c)
161
+	for i := 0; i < c.N; i++ {
162
+		time.Sleep(s.sleep)
163
+		x = make([]int64, 5)
164
+		_ = x
165
+	}
166
+}
167
+
168
+// -----------------------------------------------------------------------
169
+// Helper which checks the state of the test and ensures that it matches
170
+// the given expectations.  Depends on c.Errorf() working, so shouldn't
171
+// be used to test this one function.
172
+
173
+type expectedState struct {
174
+	name   string
175
+	result interface{}
176
+	failed bool
177
+	log    string
178
+}
179
+
180
+// Verify the state of the test.  Note that since this also verifies if
181
+// the test is supposed to be in a failed state, no other checks should
182
+// be done in addition to what is being tested.
183
+func checkState(c *check.C, result interface{}, expected *expectedState) {
184
+	failed := c.Failed()
185
+	c.Succeed()
186
+	log := c.GetTestLog()
187
+	matched, matchError := regexp.MatchString("^"+expected.log+"$", log)
188
+	if matchError != nil {
189
+		c.Errorf("Error in matching expression used in testing %s",
190
+			expected.name)
191
+	} else if !matched {
192
+		c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------",
193
+			expected.name, log, expected.log)
194
+	}
195
+	if result != expected.result {
196
+		c.Errorf("%s returned %#v rather than %#v",
197
+			expected.name, result, expected.result)
198
+	}
199
+	if failed != expected.failed {
200
+		if failed {
201
+			c.Errorf("%s has failed when it shouldn't", expected.name)
202
+		} else {
203
+			c.Errorf("%s has not failed when it should", expected.name)
204
+		}
205
+	}
206
+}
0 207
new file mode 100644
... ...
@@ -0,0 +1,458 @@
0
+package check
1
+
2
+import (
3
+	"fmt"
4
+	"reflect"
5
+	"regexp"
6
+)
7
+
8
+// -----------------------------------------------------------------------
9
+// CommentInterface and Commentf helper, to attach extra information to checks.
10
+
11
+type comment struct {
12
+	format string
13
+	args   []interface{}
14
+}
15
+
16
+// Commentf returns an infomational value to use with Assert or Check calls.
17
+// If the checker test fails, the provided arguments will be passed to
18
+// fmt.Sprintf, and will be presented next to the logged failure.
19
+//
20
+// For example:
21
+//
22
+//     c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i))
23
+//
24
+// Note that if the comment is constant, a better option is to
25
+// simply use a normal comment right above or next to the line, as
26
+// it will also get printed with any errors:
27
+//
28
+//     c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123)
29
+//
30
+func Commentf(format string, args ...interface{}) CommentInterface {
31
+	return &comment{format, args}
32
+}
33
+
34
+// CommentInterface must be implemented by types that attach extra
35
+// information to failed checks. See the Commentf function for details.
36
+type CommentInterface interface {
37
+	CheckCommentString() string
38
+}
39
+
40
+func (c *comment) CheckCommentString() string {
41
+	return fmt.Sprintf(c.format, c.args...)
42
+}
43
+
44
+// -----------------------------------------------------------------------
45
+// The Checker interface.
46
+
47
+// The Checker interface must be provided by checkers used with
48
+// the Assert and Check verification methods.
49
+type Checker interface {
50
+	Info() *CheckerInfo
51
+	Check(params []interface{}, names []string) (result bool, error string)
52
+}
53
+
54
+// See the Checker interface.
55
+type CheckerInfo struct {
56
+	Name   string
57
+	Params []string
58
+}
59
+
60
+func (info *CheckerInfo) Info() *CheckerInfo {
61
+	return info
62
+}
63
+
64
+// -----------------------------------------------------------------------
65
+// Not checker logic inverter.
66
+
67
+// The Not checker inverts the logic of the provided checker.  The
68
+// resulting checker will succeed where the original one failed, and
69
+// vice-versa.
70
+//
71
+// For example:
72
+//
73
+//     c.Assert(a, Not(Equals), b)
74
+//
75
+func Not(checker Checker) Checker {
76
+	return &notChecker{checker}
77
+}
78
+
79
+type notChecker struct {
80
+	sub Checker
81
+}
82
+
83
+func (checker *notChecker) Info() *CheckerInfo {
84
+	info := *checker.sub.Info()
85
+	info.Name = "Not(" + info.Name + ")"
86
+	return &info
87
+}
88
+
89
+func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) {
90
+	result, error = checker.sub.Check(params, names)
91
+	result = !result
92
+	return
93
+}
94
+
95
+// -----------------------------------------------------------------------
96
+// IsNil checker.
97
+
98
+type isNilChecker struct {
99
+	*CheckerInfo
100
+}
101
+
102
+// The IsNil checker tests whether the obtained value is nil.
103
+//
104
+// For example:
105
+//
106
+//    c.Assert(err, IsNil)
107
+//
108
+var IsNil Checker = &isNilChecker{
109
+	&CheckerInfo{Name: "IsNil", Params: []string{"value"}},
110
+}
111
+
112
+func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
113
+	return isNil(params[0]), ""
114
+}
115
+
116
+func isNil(obtained interface{}) (result bool) {
117
+	if obtained == nil {
118
+		result = true
119
+	} else {
120
+		switch v := reflect.ValueOf(obtained); v.Kind() {
121
+		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
122
+			return v.IsNil()
123
+		}
124
+	}
125
+	return
126
+}
127
+
128
+// -----------------------------------------------------------------------
129
+// NotNil checker. Alias for Not(IsNil), since it's so common.
130
+
131
+type notNilChecker struct {
132
+	*CheckerInfo
133
+}
134
+
135
+// The NotNil checker verifies that the obtained value is not nil.
136
+//
137
+// For example:
138
+//
139
+//     c.Assert(iface, NotNil)
140
+//
141
+// This is an alias for Not(IsNil), made available since it's a
142
+// fairly common check.
143
+//
144
+var NotNil Checker = &notNilChecker{
145
+	&CheckerInfo{Name: "NotNil", Params: []string{"value"}},
146
+}
147
+
148
+func (checker *notNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
149
+	return !isNil(params[0]), ""
150
+}
151
+
152
+// -----------------------------------------------------------------------
153
+// Equals checker.
154
+
155
+type equalsChecker struct {
156
+	*CheckerInfo
157
+}
158
+
159
+// The Equals checker verifies that the obtained value is equal to
160
+// the expected value, according to usual Go semantics for ==.
161
+//
162
+// For example:
163
+//
164
+//     c.Assert(value, Equals, 42)
165
+//
166
+var Equals Checker = &equalsChecker{
167
+	&CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}},
168
+}
169
+
170
+func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) {
171
+	defer func() {
172
+		if v := recover(); v != nil {
173
+			result = false
174
+			error = fmt.Sprint(v)
175
+		}
176
+	}()
177
+	return params[0] == params[1], ""
178
+}
179
+
180
+// -----------------------------------------------------------------------
181
+// DeepEquals checker.
182
+
183
+type deepEqualsChecker struct {
184
+	*CheckerInfo
185
+}
186
+
187
+// The DeepEquals checker verifies that the obtained value is deep-equal to
188
+// the expected value.  The check will work correctly even when facing
189
+// slices, interfaces, and values of different types (which always fail
190
+// the test).
191
+//
192
+// For example:
193
+//
194
+//     c.Assert(value, DeepEquals, 42)
195
+//     c.Assert(array, DeepEquals, []string{"hi", "there"})
196
+//
197
+var DeepEquals Checker = &deepEqualsChecker{
198
+	&CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}},
199
+}
200
+
201
+func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
202
+	return reflect.DeepEqual(params[0], params[1]), ""
203
+}
204
+
205
+// -----------------------------------------------------------------------
206
+// HasLen checker.
207
+
208
+type hasLenChecker struct {
209
+	*CheckerInfo
210
+}
211
+
212
+// The HasLen checker verifies that the obtained value has the
213
+// provided length. In many cases this is superior to using Equals
214
+// in conjuction with the len function because in case the check
215
+// fails the value itself will be printed, instead of its length,
216
+// providing more details for figuring the problem.
217
+//
218
+// For example:
219
+//
220
+//     c.Assert(list, HasLen, 5)
221
+//
222
+var HasLen Checker = &hasLenChecker{
223
+	&CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}},
224
+}
225
+
226
+func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) {
227
+	n, ok := params[1].(int)
228
+	if !ok {
229
+		return false, "n must be an int"
230
+	}
231
+	value := reflect.ValueOf(params[0])
232
+	switch value.Kind() {
233
+	case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String:
234
+	default:
235
+		return false, "obtained value type has no length"
236
+	}
237
+	return value.Len() == n, ""
238
+}
239
+
240
+// -----------------------------------------------------------------------
241
+// ErrorMatches checker.
242
+
243
+type errorMatchesChecker struct {
244
+	*CheckerInfo
245
+}
246
+
247
+// The ErrorMatches checker verifies that the error value
248
+// is non nil and matches the regular expression provided.
249
+//
250
+// For example:
251
+//
252
+//     c.Assert(err, ErrorMatches, "perm.*denied")
253
+//
254
+var ErrorMatches Checker = errorMatchesChecker{
255
+	&CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}},
256
+}
257
+
258
+func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) {
259
+	if params[0] == nil {
260
+		return false, "Error value is nil"
261
+	}
262
+	err, ok := params[0].(error)
263
+	if !ok {
264
+		return false, "Value is not an error"
265
+	}
266
+	params[0] = err.Error()
267
+	names[0] = "error"
268
+	return matches(params[0], params[1])
269
+}
270
+
271
+// -----------------------------------------------------------------------
272
+// Matches checker.
273
+
274
+type matchesChecker struct {
275
+	*CheckerInfo
276
+}
277
+
278
+// The Matches checker verifies that the string provided as the obtained
279
+// value (or the string resulting from obtained.String()) matches the
280
+// regular expression provided.
281
+//
282
+// For example:
283
+//
284
+//     c.Assert(err, Matches, "perm.*denied")
285
+//
286
+var Matches Checker = &matchesChecker{
287
+	&CheckerInfo{Name: "Matches", Params: []string{"value", "regex"}},
288
+}
289
+
290
+func (checker *matchesChecker) Check(params []interface{}, names []string) (result bool, error string) {
291
+	return matches(params[0], params[1])
292
+}
293
+
294
+func matches(value, regex interface{}) (result bool, error string) {
295
+	reStr, ok := regex.(string)
296
+	if !ok {
297
+		return false, "Regex must be a string"
298
+	}
299
+	valueStr, valueIsStr := value.(string)
300
+	if !valueIsStr {
301
+		if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr {
302
+			valueStr, valueIsStr = valueWithStr.String(), true
303
+		}
304
+	}
305
+	if valueIsStr {
306
+		matches, err := regexp.MatchString("^"+reStr+"$", valueStr)
307
+		if err != nil {
308
+			return false, "Can't compile regex: " + err.Error()
309
+		}
310
+		return matches, ""
311
+	}
312
+	return false, "Obtained value is not a string and has no .String()"
313
+}
314
+
315
+// -----------------------------------------------------------------------
316
+// Panics checker.
317
+
318
+type panicsChecker struct {
319
+	*CheckerInfo
320
+}
321
+
322
+// The Panics checker verifies that calling the provided zero-argument
323
+// function will cause a panic which is deep-equal to the provided value.
324
+//
325
+// For example:
326
+//
327
+//     c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}).
328
+//
329
+//
330
+var Panics Checker = &panicsChecker{
331
+	&CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}},
332
+}
333
+
334
+func (checker *panicsChecker) Check(params []interface{}, names []string) (result bool, error string) {
335
+	f := reflect.ValueOf(params[0])
336
+	if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
337
+		return false, "Function must take zero arguments"
338
+	}
339
+	defer func() {
340
+		// If the function has not panicked, then don't do the check.
341
+		if error != "" {
342
+			return
343
+		}
344
+		params[0] = recover()
345
+		names[0] = "panic"
346
+		result = reflect.DeepEqual(params[0], params[1])
347
+	}()
348
+	f.Call(nil)
349
+	return false, "Function has not panicked"
350
+}
351
+
352
+type panicMatchesChecker struct {
353
+	*CheckerInfo
354
+}
355
+
356
+// The PanicMatches checker verifies that calling the provided zero-argument
357
+// function will cause a panic with an error value matching
358
+// the regular expression provided.
359
+//
360
+// For example:
361
+//
362
+//     c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`).
363
+//
364
+//
365
+var PanicMatches Checker = &panicMatchesChecker{
366
+	&CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}},
367
+}
368
+
369
+func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) {
370
+	f := reflect.ValueOf(params[0])
371
+	if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
372
+		return false, "Function must take zero arguments"
373
+	}
374
+	defer func() {
375
+		// If the function has not panicked, then don't do the check.
376
+		if errmsg != "" {
377
+			return
378
+		}
379
+		obtained := recover()
380
+		names[0] = "panic"
381
+		if e, ok := obtained.(error); ok {
382
+			params[0] = e.Error()
383
+		} else if _, ok := obtained.(string); ok {
384
+			params[0] = obtained
385
+		} else {
386
+			errmsg = "Panic value is not a string or an error"
387
+			return
388
+		}
389
+		result, errmsg = matches(params[0], params[1])
390
+	}()
391
+	f.Call(nil)
392
+	return false, "Function has not panicked"
393
+}
394
+
395
+// -----------------------------------------------------------------------
396
+// FitsTypeOf checker.
397
+
398
+type fitsTypeChecker struct {
399
+	*CheckerInfo
400
+}
401
+
402
+// The FitsTypeOf checker verifies that the obtained value is
403
+// assignable to a variable with the same type as the provided
404
+// sample value.
405
+//
406
+// For example:
407
+//
408
+//     c.Assert(value, FitsTypeOf, int64(0))
409
+//     c.Assert(value, FitsTypeOf, os.Error(nil))
410
+//
411
+var FitsTypeOf Checker = &fitsTypeChecker{
412
+	&CheckerInfo{Name: "FitsTypeOf", Params: []string{"obtained", "sample"}},
413
+}
414
+
415
+func (checker *fitsTypeChecker) Check(params []interface{}, names []string) (result bool, error string) {
416
+	obtained := reflect.ValueOf(params[0])
417
+	sample := reflect.ValueOf(params[1])
418
+	if !obtained.IsValid() {
419
+		return false, ""
420
+	}
421
+	if !sample.IsValid() {
422
+		return false, "Invalid sample value"
423
+	}
424
+	return obtained.Type().AssignableTo(sample.Type()), ""
425
+}
426
+
427
+// -----------------------------------------------------------------------
428
+// Implements checker.
429
+
430
+type implementsChecker struct {
431
+	*CheckerInfo
432
+}
433
+
434
+// The Implements checker verifies that the obtained value
435
+// implements the interface specified via a pointer to an interface
436
+// variable.
437
+//
438
+// For example:
439
+//
440
+//     var e os.Error
441
+//     c.Assert(err, Implements, &e)
442
+//
443
+var Implements Checker = &implementsChecker{
444
+	&CheckerInfo{Name: "Implements", Params: []string{"obtained", "ifaceptr"}},
445
+}
446
+
447
+func (checker *implementsChecker) Check(params []interface{}, names []string) (result bool, error string) {
448
+	obtained := reflect.ValueOf(params[0])
449
+	ifaceptr := reflect.ValueOf(params[1])
450
+	if !obtained.IsValid() {
451
+		return false, ""
452
+	}
453
+	if !ifaceptr.IsValid() || ifaceptr.Kind() != reflect.Ptr || ifaceptr.Elem().Kind() != reflect.Interface {
454
+		return false, "ifaceptr should be a pointer to an interface variable"
455
+	}
456
+	return obtained.Type().Implements(ifaceptr.Elem().Type()), ""
457
+}
0 458
new file mode 100644
... ...
@@ -0,0 +1,272 @@
0
+package check_test
1
+
2
+import (
3
+	"errors"
4
+	"gopkg.in/check.v1"
5
+	"reflect"
6
+	"runtime"
7
+)
8
+
9
+type CheckersS struct{}
10
+
11
+var _ = check.Suite(&CheckersS{})
12
+
13
+func testInfo(c *check.C, checker check.Checker, name string, paramNames []string) {
14
+	info := checker.Info()
15
+	if info.Name != name {
16
+		c.Fatalf("Got name %s, expected %s", info.Name, name)
17
+	}
18
+	if !reflect.DeepEqual(info.Params, paramNames) {
19
+		c.Fatalf("Got param names %#v, expected %#v", info.Params, paramNames)
20
+	}
21
+}
22
+
23
+func testCheck(c *check.C, checker check.Checker, result bool, error string, params ...interface{}) ([]interface{}, []string) {
24
+	info := checker.Info()
25
+	if len(params) != len(info.Params) {
26
+		c.Fatalf("unexpected param count in test; expected %d got %d", len(info.Params), len(params))
27
+	}
28
+	names := append([]string{}, info.Params...)
29
+	result_, error_ := checker.Check(params, names)
30
+	if result_ != result || error_ != error {
31
+		c.Fatalf("%s.Check(%#v) returned (%#v, %#v) rather than (%#v, %#v)",
32
+			info.Name, params, result_, error_, result, error)
33
+	}
34
+	return params, names
35
+}
36
+
37
+func (s *CheckersS) TestComment(c *check.C) {
38
+	bug := check.Commentf("a %d bc", 42)
39
+	comment := bug.CheckCommentString()
40
+	if comment != "a 42 bc" {
41
+		c.Fatalf("Commentf returned %#v", comment)
42
+	}
43
+}
44
+
45
+func (s *CheckersS) TestIsNil(c *check.C) {
46
+	testInfo(c, check.IsNil, "IsNil", []string{"value"})
47
+
48
+	testCheck(c, check.IsNil, true, "", nil)
49
+	testCheck(c, check.IsNil, false, "", "a")
50
+
51
+	testCheck(c, check.IsNil, true, "", (chan int)(nil))
52
+	testCheck(c, check.IsNil, false, "", make(chan int))
53
+	testCheck(c, check.IsNil, true, "", (error)(nil))
54
+	testCheck(c, check.IsNil, false, "", errors.New(""))
55
+	testCheck(c, check.IsNil, true, "", ([]int)(nil))
56
+	testCheck(c, check.IsNil, false, "", make([]int, 1))
57
+	testCheck(c, check.IsNil, false, "", int(0))
58
+}
59
+
60
+func (s *CheckersS) TestNotNil(c *check.C) {
61
+	testInfo(c, check.NotNil, "NotNil", []string{"value"})
62
+
63
+	testCheck(c, check.NotNil, false, "", nil)
64
+	testCheck(c, check.NotNil, true, "", "a")
65
+
66
+	testCheck(c, check.NotNil, false, "", (chan int)(nil))
67
+	testCheck(c, check.NotNil, true, "", make(chan int))
68
+	testCheck(c, check.NotNil, false, "", (error)(nil))
69
+	testCheck(c, check.NotNil, true, "", errors.New(""))
70
+	testCheck(c, check.NotNil, false, "", ([]int)(nil))
71
+	testCheck(c, check.NotNil, true, "", make([]int, 1))
72
+}
73
+
74
+func (s *CheckersS) TestNot(c *check.C) {
75
+	testInfo(c, check.Not(check.IsNil), "Not(IsNil)", []string{"value"})
76
+
77
+	testCheck(c, check.Not(check.IsNil), false, "", nil)
78
+	testCheck(c, check.Not(check.IsNil), true, "", "a")
79
+}
80
+
81
+type simpleStruct struct {
82
+	i int
83
+}
84
+
85
+func (s *CheckersS) TestEquals(c *check.C) {
86
+	testInfo(c, check.Equals, "Equals", []string{"obtained", "expected"})
87
+
88
+	// The simplest.
89
+	testCheck(c, check.Equals, true, "", 42, 42)
90
+	testCheck(c, check.Equals, false, "", 42, 43)
91
+
92
+	// Different native types.
93
+	testCheck(c, check.Equals, false, "", int32(42), int64(42))
94
+
95
+	// With nil.
96
+	testCheck(c, check.Equals, false, "", 42, nil)
97
+
98
+	// Slices
99
+	testCheck(c, check.Equals, false, "runtime error: comparing uncomparable type []uint8", []byte{1, 2}, []byte{1, 2})
100
+
101
+	// Struct values
102
+	testCheck(c, check.Equals, true, "", simpleStruct{1}, simpleStruct{1})
103
+	testCheck(c, check.Equals, false, "", simpleStruct{1}, simpleStruct{2})
104
+
105
+	// Struct pointers
106
+	testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{1})
107
+	testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{2})
108
+}
109
+
110
+func (s *CheckersS) TestDeepEquals(c *check.C) {
111
+	testInfo(c, check.DeepEquals, "DeepEquals", []string{"obtained", "expected"})
112
+
113
+	// The simplest.
114
+	testCheck(c, check.DeepEquals, true, "", 42, 42)
115
+	testCheck(c, check.DeepEquals, false, "", 42, 43)
116
+
117
+	// Different native types.
118
+	testCheck(c, check.DeepEquals, false, "", int32(42), int64(42))
119
+
120
+	// With nil.
121
+	testCheck(c, check.DeepEquals, false, "", 42, nil)
122
+
123
+	// Slices
124
+	testCheck(c, check.DeepEquals, true, "", []byte{1, 2}, []byte{1, 2})
125
+	testCheck(c, check.DeepEquals, false, "", []byte{1, 2}, []byte{1, 3})
126
+
127
+	// Struct values
128
+	testCheck(c, check.DeepEquals, true, "", simpleStruct{1}, simpleStruct{1})
129
+	testCheck(c, check.DeepEquals, false, "", simpleStruct{1}, simpleStruct{2})
130
+
131
+	// Struct pointers
132
+	testCheck(c, check.DeepEquals, true, "", &simpleStruct{1}, &simpleStruct{1})
133
+	testCheck(c, check.DeepEquals, false, "", &simpleStruct{1}, &simpleStruct{2})
134
+}
135
+
136
+func (s *CheckersS) TestHasLen(c *check.C) {
137
+	testInfo(c, check.HasLen, "HasLen", []string{"obtained", "n"})
138
+
139
+	testCheck(c, check.HasLen, true, "", "abcd", 4)
140
+	testCheck(c, check.HasLen, true, "", []int{1, 2}, 2)
141
+	testCheck(c, check.HasLen, false, "", []int{1, 2}, 3)
142
+
143
+	testCheck(c, check.HasLen, false, "n must be an int", []int{1, 2}, "2")
144
+	testCheck(c, check.HasLen, false, "obtained value type has no length", nil, 2)
145
+}
146
+
147
+func (s *CheckersS) TestErrorMatches(c *check.C) {
148
+	testInfo(c, check.ErrorMatches, "ErrorMatches", []string{"value", "regex"})
149
+
150
+	testCheck(c, check.ErrorMatches, false, "Error value is nil", nil, "some error")
151
+	testCheck(c, check.ErrorMatches, false, "Value is not an error", 1, "some error")
152
+	testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "some error")
153
+	testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "so.*or")
154
+
155
+	// Verify params mutation
156
+	params, names := testCheck(c, check.ErrorMatches, false, "", errors.New("some error"), "other error")
157
+	c.Assert(params[0], check.Equals, "some error")
158
+	c.Assert(names[0], check.Equals, "error")
159
+}
160
+
161
+func (s *CheckersS) TestMatches(c *check.C) {
162
+	testInfo(c, check.Matches, "Matches", []string{"value", "regex"})
163
+
164
+	// Simple matching
165
+	testCheck(c, check.Matches, true, "", "abc", "abc")
166
+	testCheck(c, check.Matches, true, "", "abc", "a.c")
167
+
168
+	// Must match fully
169
+	testCheck(c, check.Matches, false, "", "abc", "ab")
170
+	testCheck(c, check.Matches, false, "", "abc", "bc")
171
+
172
+	// String()-enabled values accepted
173
+	testCheck(c, check.Matches, true, "", reflect.ValueOf("abc"), "a.c")
174
+	testCheck(c, check.Matches, false, "", reflect.ValueOf("abc"), "a.d")
175
+
176
+	// Some error conditions.
177
+	testCheck(c, check.Matches, false, "Obtained value is not a string and has no .String()", 1, "a.c")
178
+	testCheck(c, check.Matches, false, "Can't compile regex: error parsing regexp: missing closing ]: `[c$`", "abc", "a[c")
179
+}
180
+
181
+func (s *CheckersS) TestPanics(c *check.C) {
182
+	testInfo(c, check.Panics, "Panics", []string{"function", "expected"})
183
+
184
+	// Some errors.
185
+	testCheck(c, check.Panics, false, "Function has not panicked", func() bool { return false }, "BOOM")
186
+	testCheck(c, check.Panics, false, "Function must take zero arguments", 1, "BOOM")
187
+
188
+	// Plain strings.
189
+	testCheck(c, check.Panics, true, "", func() { panic("BOOM") }, "BOOM")
190
+	testCheck(c, check.Panics, false, "", func() { panic("KABOOM") }, "BOOM")
191
+	testCheck(c, check.Panics, true, "", func() bool { panic("BOOM") }, "BOOM")
192
+
193
+	// Error values.
194
+	testCheck(c, check.Panics, true, "", func() { panic(errors.New("BOOM")) }, errors.New("BOOM"))
195
+	testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
196
+
197
+	type deep struct{ i int }
198
+	// Deep value
199
+	testCheck(c, check.Panics, true, "", func() { panic(&deep{99}) }, &deep{99})
200
+
201
+	// Verify params/names mutation
202
+	params, names := testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
203
+	c.Assert(params[0], check.ErrorMatches, "KABOOM")
204
+	c.Assert(names[0], check.Equals, "panic")
205
+
206
+	// Verify a nil panic
207
+	testCheck(c, check.Panics, true, "", func() { panic(nil) }, nil)
208
+	testCheck(c, check.Panics, false, "", func() { panic(nil) }, "NOPE")
209
+}
210
+
211
+func (s *CheckersS) TestPanicMatches(c *check.C) {
212
+	testInfo(c, check.PanicMatches, "PanicMatches", []string{"function", "expected"})
213
+
214
+	// Error matching.
215
+	testCheck(c, check.PanicMatches, true, "", func() { panic(errors.New("BOOM")) }, "BO.M")
216
+	testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BO.M")
217
+
218
+	// Some errors.
219
+	testCheck(c, check.PanicMatches, false, "Function has not panicked", func() bool { return false }, "BOOM")
220
+	testCheck(c, check.PanicMatches, false, "Function must take zero arguments", 1, "BOOM")
221
+
222
+	// Plain strings.
223
+	testCheck(c, check.PanicMatches, true, "", func() { panic("BOOM") }, "BO.M")
224
+	testCheck(c, check.PanicMatches, false, "", func() { panic("KABOOM") }, "BOOM")
225
+	testCheck(c, check.PanicMatches, true, "", func() bool { panic("BOOM") }, "BO.M")
226
+
227
+	// Verify params/names mutation
228
+	params, names := testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BOOM")
229
+	c.Assert(params[0], check.Equals, "KABOOM")
230
+	c.Assert(names[0], check.Equals, "panic")
231
+
232
+	// Verify a nil panic
233
+	testCheck(c, check.PanicMatches, false, "Panic value is not a string or an error", func() { panic(nil) }, "")
234
+}
235
+
236
+func (s *CheckersS) TestFitsTypeOf(c *check.C) {
237
+	testInfo(c, check.FitsTypeOf, "FitsTypeOf", []string{"obtained", "sample"})
238
+
239
+	// Basic types
240
+	testCheck(c, check.FitsTypeOf, true, "", 1, 0)
241
+	testCheck(c, check.FitsTypeOf, false, "", 1, int64(0))
242
+
243
+	// Aliases
244
+	testCheck(c, check.FitsTypeOf, false, "", 1, errors.New(""))
245
+	testCheck(c, check.FitsTypeOf, false, "", "error", errors.New(""))
246
+	testCheck(c, check.FitsTypeOf, true, "", errors.New("error"), errors.New(""))
247
+
248
+	// Structures
249
+	testCheck(c, check.FitsTypeOf, false, "", 1, simpleStruct{})
250
+	testCheck(c, check.FitsTypeOf, false, "", simpleStruct{42}, &simpleStruct{})
251
+	testCheck(c, check.FitsTypeOf, true, "", simpleStruct{42}, simpleStruct{})
252
+	testCheck(c, check.FitsTypeOf, true, "", &simpleStruct{42}, &simpleStruct{})
253
+
254
+	// Some bad values
255
+	testCheck(c, check.FitsTypeOf, false, "Invalid sample value", 1, interface{}(nil))
256
+	testCheck(c, check.FitsTypeOf, false, "", interface{}(nil), 0)
257
+}
258
+
259
+func (s *CheckersS) TestImplements(c *check.C) {
260
+	testInfo(c, check.Implements, "Implements", []string{"obtained", "ifaceptr"})
261
+
262
+	var e error
263
+	var re runtime.Error
264
+	testCheck(c, check.Implements, true, "", errors.New(""), &e)
265
+	testCheck(c, check.Implements, false, "", errors.New(""), &re)
266
+
267
+	// Some bad values
268
+	testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, errors.New(""))
269
+	testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, interface{}(nil))
270
+	testCheck(c, check.Implements, false, "", interface{}(nil), &e)
271
+}
0 272
new file mode 100644
... ...
@@ -0,0 +1,9 @@
0
+package check
1
+
2
+func PrintLine(filename string, line int) (string, error) {
3
+	return printLine(filename, line)
4
+}
5
+
6
+func Indent(s, with string) string {
7
+	return indent(s, with)
8
+}
0 9
new file mode 100644
... ...
@@ -0,0 +1,484 @@
0
+// Tests for the behavior of the test fixture system.
1
+
2
+package check_test
3
+
4
+import (
5
+	. "gopkg.in/check.v1"
6
+)
7
+
8
+// -----------------------------------------------------------------------
9
+// Fixture test suite.
10
+
11
+type FixtureS struct{}
12
+
13
+var fixtureS = Suite(&FixtureS{})
14
+
15
+func (s *FixtureS) TestCountSuite(c *C) {
16
+	suitesRun += 1
17
+}
18
+
19
+// -----------------------------------------------------------------------
20
+// Basic fixture ordering verification.
21
+
22
+func (s *FixtureS) TestOrder(c *C) {
23
+	helper := FixtureHelper{}
24
+	Run(&helper, nil)
25
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
26
+	c.Check(helper.calls[1], Equals, "SetUpTest")
27
+	c.Check(helper.calls[2], Equals, "Test1")
28
+	c.Check(helper.calls[3], Equals, "TearDownTest")
29
+	c.Check(helper.calls[4], Equals, "SetUpTest")
30
+	c.Check(helper.calls[5], Equals, "Test2")
31
+	c.Check(helper.calls[6], Equals, "TearDownTest")
32
+	c.Check(helper.calls[7], Equals, "TearDownSuite")
33
+	c.Check(len(helper.calls), Equals, 8)
34
+}
35
+
36
+// -----------------------------------------------------------------------
37
+// Check the behavior when panics occur within tests and fixtures.
38
+
39
+func (s *FixtureS) TestPanicOnTest(c *C) {
40
+	helper := FixtureHelper{panicOn: "Test1"}
41
+	output := String{}
42
+	Run(&helper, &RunConf{Output: &output})
43
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
44
+	c.Check(helper.calls[1], Equals, "SetUpTest")
45
+	c.Check(helper.calls[2], Equals, "Test1")
46
+	c.Check(helper.calls[3], Equals, "TearDownTest")
47
+	c.Check(helper.calls[4], Equals, "SetUpTest")
48
+	c.Check(helper.calls[5], Equals, "Test2")
49
+	c.Check(helper.calls[6], Equals, "TearDownTest")
50
+	c.Check(helper.calls[7], Equals, "TearDownSuite")
51
+	c.Check(len(helper.calls), Equals, 8)
52
+
53
+	expected := "^\n-+\n" +
54
+		"PANIC: check_test\\.go:[0-9]+: FixtureHelper.Test1\n\n" +
55
+		"\\.\\.\\. Panic: Test1 \\(PC=[xA-F0-9]+\\)\n\n" +
56
+		".+:[0-9]+\n" +
57
+		"  in (go)?panic\n" +
58
+		".*check_test.go:[0-9]+\n" +
59
+		"  in FixtureHelper.trace\n" +
60
+		".*check_test.go:[0-9]+\n" +
61
+		"  in FixtureHelper.Test1\n" +
62
+		"(.|\n)*$"
63
+
64
+	c.Check(output.value, Matches, expected)
65
+}
66
+
67
+func (s *FixtureS) TestPanicOnSetUpTest(c *C) {
68
+	helper := FixtureHelper{panicOn: "SetUpTest"}
69
+	output := String{}
70
+	Run(&helper, &RunConf{Output: &output})
71
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
72
+	c.Check(helper.calls[1], Equals, "SetUpTest")
73
+	c.Check(helper.calls[2], Equals, "TearDownTest")
74
+	c.Check(helper.calls[3], Equals, "TearDownSuite")
75
+	c.Check(len(helper.calls), Equals, 4)
76
+
77
+	expected := "^\n-+\n" +
78
+		"PANIC: check_test\\.go:[0-9]+: " +
79
+		"FixtureHelper\\.SetUpTest\n\n" +
80
+		"\\.\\.\\. Panic: SetUpTest \\(PC=[xA-F0-9]+\\)\n\n" +
81
+		".+:[0-9]+\n" +
82
+		"  in (go)?panic\n" +
83
+		".*check_test.go:[0-9]+\n" +
84
+		"  in FixtureHelper.trace\n" +
85
+		".*check_test.go:[0-9]+\n" +
86
+		"  in FixtureHelper.SetUpTest\n" +
87
+		"(.|\n)*" +
88
+		"\n-+\n" +
89
+		"PANIC: check_test\\.go:[0-9]+: " +
90
+		"FixtureHelper\\.Test1\n\n" +
91
+		"\\.\\.\\. Panic: Fixture has panicked " +
92
+		"\\(see related PANIC\\)\n$"
93
+
94
+	c.Check(output.value, Matches, expected)
95
+}
96
+
97
+func (s *FixtureS) TestPanicOnTearDownTest(c *C) {
98
+	helper := FixtureHelper{panicOn: "TearDownTest"}
99
+	output := String{}
100
+	Run(&helper, &RunConf{Output: &output})
101
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
102
+	c.Check(helper.calls[1], Equals, "SetUpTest")
103
+	c.Check(helper.calls[2], Equals, "Test1")
104
+	c.Check(helper.calls[3], Equals, "TearDownTest")
105
+	c.Check(helper.calls[4], Equals, "TearDownSuite")
106
+	c.Check(len(helper.calls), Equals, 5)
107
+
108
+	expected := "^\n-+\n" +
109
+		"PANIC: check_test\\.go:[0-9]+: " +
110
+		"FixtureHelper.TearDownTest\n\n" +
111
+		"\\.\\.\\. Panic: TearDownTest \\(PC=[xA-F0-9]+\\)\n\n" +
112
+		".+:[0-9]+\n" +
113
+		"  in (go)?panic\n" +
114
+		".*check_test.go:[0-9]+\n" +
115
+		"  in FixtureHelper.trace\n" +
116
+		".*check_test.go:[0-9]+\n" +
117
+		"  in FixtureHelper.TearDownTest\n" +
118
+		"(.|\n)*" +
119
+		"\n-+\n" +
120
+		"PANIC: check_test\\.go:[0-9]+: " +
121
+		"FixtureHelper\\.Test1\n\n" +
122
+		"\\.\\.\\. Panic: Fixture has panicked " +
123
+		"\\(see related PANIC\\)\n$"
124
+
125
+	c.Check(output.value, Matches, expected)
126
+}
127
+
128
+func (s *FixtureS) TestPanicOnSetUpSuite(c *C) {
129
+	helper := FixtureHelper{panicOn: "SetUpSuite"}
130
+	output := String{}
131
+	Run(&helper, &RunConf{Output: &output})
132
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
133
+	c.Check(helper.calls[1], Equals, "TearDownSuite")
134
+	c.Check(len(helper.calls), Equals, 2)
135
+
136
+	expected := "^\n-+\n" +
137
+		"PANIC: check_test\\.go:[0-9]+: " +
138
+		"FixtureHelper.SetUpSuite\n\n" +
139
+		"\\.\\.\\. Panic: SetUpSuite \\(PC=[xA-F0-9]+\\)\n\n" +
140
+		".+:[0-9]+\n" +
141
+		"  in (go)?panic\n" +
142
+		".*check_test.go:[0-9]+\n" +
143
+		"  in FixtureHelper.trace\n" +
144
+		".*check_test.go:[0-9]+\n" +
145
+		"  in FixtureHelper.SetUpSuite\n" +
146
+		"(.|\n)*$"
147
+
148
+	c.Check(output.value, Matches, expected)
149
+}
150
+
151
+func (s *FixtureS) TestPanicOnTearDownSuite(c *C) {
152
+	helper := FixtureHelper{panicOn: "TearDownSuite"}
153
+	output := String{}
154
+	Run(&helper, &RunConf{Output: &output})
155
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
156
+	c.Check(helper.calls[1], Equals, "SetUpTest")
157
+	c.Check(helper.calls[2], Equals, "Test1")
158
+	c.Check(helper.calls[3], Equals, "TearDownTest")
159
+	c.Check(helper.calls[4], Equals, "SetUpTest")
160
+	c.Check(helper.calls[5], Equals, "Test2")
161
+	c.Check(helper.calls[6], Equals, "TearDownTest")
162
+	c.Check(helper.calls[7], Equals, "TearDownSuite")
163
+	c.Check(len(helper.calls), Equals, 8)
164
+
165
+	expected := "^\n-+\n" +
166
+		"PANIC: check_test\\.go:[0-9]+: " +
167
+		"FixtureHelper.TearDownSuite\n\n" +
168
+		"\\.\\.\\. Panic: TearDownSuite \\(PC=[xA-F0-9]+\\)\n\n" +
169
+		".+:[0-9]+\n" +
170
+		"  in (go)?panic\n" +
171
+		".*check_test.go:[0-9]+\n" +
172
+		"  in FixtureHelper.trace\n" +
173
+		".*check_test.go:[0-9]+\n" +
174
+		"  in FixtureHelper.TearDownSuite\n" +
175
+		"(.|\n)*$"
176
+
177
+	c.Check(output.value, Matches, expected)
178
+}
179
+
180
+// -----------------------------------------------------------------------
181
+// A wrong argument on a test or fixture will produce a nice error.
182
+
183
+func (s *FixtureS) TestPanicOnWrongTestArg(c *C) {
184
+	helper := WrongTestArgHelper{}
185
+	output := String{}
186
+	Run(&helper, &RunConf{Output: &output})
187
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
188
+	c.Check(helper.calls[1], Equals, "SetUpTest")
189
+	c.Check(helper.calls[2], Equals, "TearDownTest")
190
+	c.Check(helper.calls[3], Equals, "SetUpTest")
191
+	c.Check(helper.calls[4], Equals, "Test2")
192
+	c.Check(helper.calls[5], Equals, "TearDownTest")
193
+	c.Check(helper.calls[6], Equals, "TearDownSuite")
194
+	c.Check(len(helper.calls), Equals, 7)
195
+
196
+	expected := "^\n-+\n" +
197
+		"PANIC: fixture_test\\.go:[0-9]+: " +
198
+		"WrongTestArgHelper\\.Test1\n\n" +
199
+		"\\.\\.\\. Panic: WrongTestArgHelper\\.Test1 argument " +
200
+		"should be \\*check\\.C\n"
201
+
202
+	c.Check(output.value, Matches, expected)
203
+}
204
+
205
+func (s *FixtureS) TestPanicOnWrongSetUpTestArg(c *C) {
206
+	helper := WrongSetUpTestArgHelper{}
207
+	output := String{}
208
+	Run(&helper, &RunConf{Output: &output})
209
+	c.Check(len(helper.calls), Equals, 0)
210
+
211
+	expected :=
212
+		"^\n-+\n" +
213
+			"PANIC: fixture_test\\.go:[0-9]+: " +
214
+			"WrongSetUpTestArgHelper\\.SetUpTest\n\n" +
215
+			"\\.\\.\\. Panic: WrongSetUpTestArgHelper\\.SetUpTest argument " +
216
+			"should be \\*check\\.C\n"
217
+
218
+	c.Check(output.value, Matches, expected)
219
+}
220
+
221
+func (s *FixtureS) TestPanicOnWrongSetUpSuiteArg(c *C) {
222
+	helper := WrongSetUpSuiteArgHelper{}
223
+	output := String{}
224
+	Run(&helper, &RunConf{Output: &output})
225
+	c.Check(len(helper.calls), Equals, 0)
226
+
227
+	expected :=
228
+		"^\n-+\n" +
229
+			"PANIC: fixture_test\\.go:[0-9]+: " +
230
+			"WrongSetUpSuiteArgHelper\\.SetUpSuite\n\n" +
231
+			"\\.\\.\\. Panic: WrongSetUpSuiteArgHelper\\.SetUpSuite argument " +
232
+			"should be \\*check\\.C\n"
233
+
234
+	c.Check(output.value, Matches, expected)
235
+}
236
+
237
+// -----------------------------------------------------------------------
238
+// Nice errors also when tests or fixture have wrong arg count.
239
+
240
+func (s *FixtureS) TestPanicOnWrongTestArgCount(c *C) {
241
+	helper := WrongTestArgCountHelper{}
242
+	output := String{}
243
+	Run(&helper, &RunConf{Output: &output})
244
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
245
+	c.Check(helper.calls[1], Equals, "SetUpTest")
246
+	c.Check(helper.calls[2], Equals, "TearDownTest")
247
+	c.Check(helper.calls[3], Equals, "SetUpTest")
248
+	c.Check(helper.calls[4], Equals, "Test2")
249
+	c.Check(helper.calls[5], Equals, "TearDownTest")
250
+	c.Check(helper.calls[6], Equals, "TearDownSuite")
251
+	c.Check(len(helper.calls), Equals, 7)
252
+
253
+	expected := "^\n-+\n" +
254
+		"PANIC: fixture_test\\.go:[0-9]+: " +
255
+		"WrongTestArgCountHelper\\.Test1\n\n" +
256
+		"\\.\\.\\. Panic: WrongTestArgCountHelper\\.Test1 argument " +
257
+		"should be \\*check\\.C\n"
258
+
259
+	c.Check(output.value, Matches, expected)
260
+}
261
+
262
+func (s *FixtureS) TestPanicOnWrongSetUpTestArgCount(c *C) {
263
+	helper := WrongSetUpTestArgCountHelper{}
264
+	output := String{}
265
+	Run(&helper, &RunConf{Output: &output})
266
+	c.Check(len(helper.calls), Equals, 0)
267
+
268
+	expected :=
269
+		"^\n-+\n" +
270
+			"PANIC: fixture_test\\.go:[0-9]+: " +
271
+			"WrongSetUpTestArgCountHelper\\.SetUpTest\n\n" +
272
+			"\\.\\.\\. Panic: WrongSetUpTestArgCountHelper\\.SetUpTest argument " +
273
+			"should be \\*check\\.C\n"
274
+
275
+	c.Check(output.value, Matches, expected)
276
+}
277
+
278
+func (s *FixtureS) TestPanicOnWrongSetUpSuiteArgCount(c *C) {
279
+	helper := WrongSetUpSuiteArgCountHelper{}
280
+	output := String{}
281
+	Run(&helper, &RunConf{Output: &output})
282
+	c.Check(len(helper.calls), Equals, 0)
283
+
284
+	expected :=
285
+		"^\n-+\n" +
286
+			"PANIC: fixture_test\\.go:[0-9]+: " +
287
+			"WrongSetUpSuiteArgCountHelper\\.SetUpSuite\n\n" +
288
+			"\\.\\.\\. Panic: WrongSetUpSuiteArgCountHelper" +
289
+			"\\.SetUpSuite argument should be \\*check\\.C\n"
290
+
291
+	c.Check(output.value, Matches, expected)
292
+}
293
+
294
+// -----------------------------------------------------------------------
295
+// Helper test suites with wrong function arguments.
296
+
297
+type WrongTestArgHelper struct {
298
+	FixtureHelper
299
+}
300
+
301
+func (s *WrongTestArgHelper) Test1(t int) {
302
+}
303
+
304
+type WrongSetUpTestArgHelper struct {
305
+	FixtureHelper
306
+}
307
+
308
+func (s *WrongSetUpTestArgHelper) SetUpTest(t int) {
309
+}
310
+
311
+type WrongSetUpSuiteArgHelper struct {
312
+	FixtureHelper
313
+}
314
+
315
+func (s *WrongSetUpSuiteArgHelper) SetUpSuite(t int) {
316
+}
317
+
318
+type WrongTestArgCountHelper struct {
319
+	FixtureHelper
320
+}
321
+
322
+func (s *WrongTestArgCountHelper) Test1(c *C, i int) {
323
+}
324
+
325
+type WrongSetUpTestArgCountHelper struct {
326
+	FixtureHelper
327
+}
328
+
329
+func (s *WrongSetUpTestArgCountHelper) SetUpTest(c *C, i int) {
330
+}
331
+
332
+type WrongSetUpSuiteArgCountHelper struct {
333
+	FixtureHelper
334
+}
335
+
336
+func (s *WrongSetUpSuiteArgCountHelper) SetUpSuite(c *C, i int) {
337
+}
338
+
339
+// -----------------------------------------------------------------------
340
+// Ensure fixture doesn't run without tests.
341
+
342
+type NoTestsHelper struct {
343
+	hasRun bool
344
+}
345
+
346
+func (s *NoTestsHelper) SetUpSuite(c *C) {
347
+	s.hasRun = true
348
+}
349
+
350
+func (s *NoTestsHelper) TearDownSuite(c *C) {
351
+	s.hasRun = true
352
+}
353
+
354
+func (s *FixtureS) TestFixtureDoesntRunWithoutTests(c *C) {
355
+	helper := NoTestsHelper{}
356
+	output := String{}
357
+	Run(&helper, &RunConf{Output: &output})
358
+	c.Check(helper.hasRun, Equals, false)
359
+}
360
+
361
+// -----------------------------------------------------------------------
362
+// Verify that checks and assertions work correctly inside the fixture.
363
+
364
+type FixtureCheckHelper struct {
365
+	fail      string
366
+	completed bool
367
+}
368
+
369
+func (s *FixtureCheckHelper) SetUpSuite(c *C) {
370
+	switch s.fail {
371
+	case "SetUpSuiteAssert":
372
+		c.Assert(false, Equals, true)
373
+	case "SetUpSuiteCheck":
374
+		c.Check(false, Equals, true)
375
+	}
376
+	s.completed = true
377
+}
378
+
379
+func (s *FixtureCheckHelper) SetUpTest(c *C) {
380
+	switch s.fail {
381
+	case "SetUpTestAssert":
382
+		c.Assert(false, Equals, true)
383
+	case "SetUpTestCheck":
384
+		c.Check(false, Equals, true)
385
+	}
386
+	s.completed = true
387
+}
388
+
389
+func (s *FixtureCheckHelper) Test(c *C) {
390
+	// Do nothing.
391
+}
392
+
393
+func (s *FixtureS) TestSetUpSuiteCheck(c *C) {
394
+	helper := FixtureCheckHelper{fail: "SetUpSuiteCheck"}
395
+	output := String{}
396
+	Run(&helper, &RunConf{Output: &output})
397
+	c.Assert(output.value, Matches,
398
+		"\n---+\n"+
399
+			"FAIL: fixture_test\\.go:[0-9]+: "+
400
+			"FixtureCheckHelper\\.SetUpSuite\n\n"+
401
+			"fixture_test\\.go:[0-9]+:\n"+
402
+			"    c\\.Check\\(false, Equals, true\\)\n"+
403
+			"\\.+ obtained bool = false\n"+
404
+			"\\.+ expected bool = true\n\n")
405
+	c.Assert(helper.completed, Equals, true)
406
+}
407
+
408
+func (s *FixtureS) TestSetUpSuiteAssert(c *C) {
409
+	helper := FixtureCheckHelper{fail: "SetUpSuiteAssert"}
410
+	output := String{}
411
+	Run(&helper, &RunConf{Output: &output})
412
+	c.Assert(output.value, Matches,
413
+		"\n---+\n"+
414
+			"FAIL: fixture_test\\.go:[0-9]+: "+
415
+			"FixtureCheckHelper\\.SetUpSuite\n\n"+
416
+			"fixture_test\\.go:[0-9]+:\n"+
417
+			"    c\\.Assert\\(false, Equals, true\\)\n"+
418
+			"\\.+ obtained bool = false\n"+
419
+			"\\.+ expected bool = true\n\n")
420
+	c.Assert(helper.completed, Equals, false)
421
+}
422
+
423
+// -----------------------------------------------------------------------
424
+// Verify that logging within SetUpTest() persists within the test log itself.
425
+
426
+type FixtureLogHelper struct {
427
+	c *C
428
+}
429
+
430
+func (s *FixtureLogHelper) SetUpTest(c *C) {
431
+	s.c = c
432
+	c.Log("1")
433
+}
434
+
435
+func (s *FixtureLogHelper) Test(c *C) {
436
+	c.Log("2")
437
+	s.c.Log("3")
438
+	c.Log("4")
439
+	c.Fail()
440
+}
441
+
442
+func (s *FixtureLogHelper) TearDownTest(c *C) {
443
+	s.c.Log("5")
444
+}
445
+
446
+func (s *FixtureS) TestFixtureLogging(c *C) {
447
+	helper := FixtureLogHelper{}
448
+	output := String{}
449
+	Run(&helper, &RunConf{Output: &output})
450
+	c.Assert(output.value, Matches,
451
+		"\n---+\n"+
452
+			"FAIL: fixture_test\\.go:[0-9]+: "+
453
+			"FixtureLogHelper\\.Test\n\n"+
454
+			"1\n2\n3\n4\n5\n")
455
+}
456
+
457
+// -----------------------------------------------------------------------
458
+// Skip() within fixture methods.
459
+
460
+func (s *FixtureS) TestSkipSuite(c *C) {
461
+	helper := FixtureHelper{skip: true, skipOnN: 0}
462
+	output := String{}
463
+	result := Run(&helper, &RunConf{Output: &output})
464
+	c.Assert(output.value, Equals, "")
465
+	c.Assert(helper.calls[0], Equals, "SetUpSuite")
466
+	c.Assert(helper.calls[1], Equals, "TearDownSuite")
467
+	c.Assert(len(helper.calls), Equals, 2)
468
+	c.Assert(result.Skipped, Equals, 2)
469
+}
470
+
471
+func (s *FixtureS) TestSkipTest(c *C) {
472
+	helper := FixtureHelper{skip: true, skipOnN: 1}
473
+	output := String{}
474
+	result := Run(&helper, &RunConf{Output: &output})
475
+	c.Assert(helper.calls[0], Equals, "SetUpSuite")
476
+	c.Assert(helper.calls[1], Equals, "SetUpTest")
477
+	c.Assert(helper.calls[2], Equals, "SetUpTest")
478
+	c.Assert(helper.calls[3], Equals, "Test2")
479
+	c.Assert(helper.calls[4], Equals, "TearDownTest")
480
+	c.Assert(helper.calls[5], Equals, "TearDownSuite")
481
+	c.Assert(len(helper.calls), Equals, 6)
482
+	c.Assert(result.Skipped, Equals, 1)
483
+}
0 484
new file mode 100644
... ...
@@ -0,0 +1,335 @@
0
+// These tests check that the foundations of gocheck are working properly.
1
+// They already assume that fundamental failing is working already, though,
2
+// since this was tested in bootstrap_test.go. Even then, some care may
3
+// still have to be taken when using external functions, since they should
4
+// of course not rely on functionality tested here.
5
+
6
+package check_test
7
+
8
+import (
9
+	"fmt"
10
+	"gopkg.in/check.v1"
11
+	"log"
12
+	"os"
13
+	"regexp"
14
+	"strings"
15
+)
16
+
17
+// -----------------------------------------------------------------------
18
+// Foundation test suite.
19
+
20
+type FoundationS struct{}
21
+
22
+var foundationS = check.Suite(&FoundationS{})
23
+
24
+func (s *FoundationS) TestCountSuite(c *check.C) {
25
+	suitesRun += 1
26
+}
27
+
28
+func (s *FoundationS) TestErrorf(c *check.C) {
29
+	// Do not use checkState() here.  It depends on Errorf() working.
30
+	expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+
31
+		"    c.Errorf(\"Error %%v!\", \"message\")\n"+
32
+		"... Error: Error message!\n\n",
33
+		getMyLine()+1)
34
+	c.Errorf("Error %v!", "message")
35
+	failed := c.Failed()
36
+	c.Succeed()
37
+	if log := c.GetTestLog(); log != expectedLog {
38
+		c.Logf("Errorf() logged %#v rather than %#v", log, expectedLog)
39
+		c.Fail()
40
+	}
41
+	if !failed {
42
+		c.Logf("Errorf() didn't put the test in a failed state")
43
+		c.Fail()
44
+	}
45
+}
46
+
47
+func (s *FoundationS) TestError(c *check.C) {
48
+	expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+
49
+		"    c\\.Error\\(\"Error \", \"message!\"\\)\n"+
50
+		"\\.\\.\\. Error: Error message!\n\n",
51
+		getMyLine()+1)
52
+	c.Error("Error ", "message!")
53
+	checkState(c, nil,
54
+		&expectedState{
55
+			name:   "Error(`Error `, `message!`)",
56
+			failed: true,
57
+			log:    expectedLog,
58
+		})
59
+}
60
+
61
+func (s *FoundationS) TestFailNow(c *check.C) {
62
+	defer (func() {
63
+		if !c.Failed() {
64
+			c.Error("FailNow() didn't fail the test")
65
+		} else {
66
+			c.Succeed()
67
+			if c.GetTestLog() != "" {
68
+				c.Error("Something got logged:\n" + c.GetTestLog())
69
+			}
70
+		}
71
+	})()
72
+
73
+	c.FailNow()
74
+	c.Log("FailNow() didn't stop the test")
75
+}
76
+
77
+func (s *FoundationS) TestSucceedNow(c *check.C) {
78
+	defer (func() {
79
+		if c.Failed() {
80
+			c.Error("SucceedNow() didn't succeed the test")
81
+		}
82
+		if c.GetTestLog() != "" {
83
+			c.Error("Something got logged:\n" + c.GetTestLog())
84
+		}
85
+	})()
86
+
87
+	c.Fail()
88
+	c.SucceedNow()
89
+	c.Log("SucceedNow() didn't stop the test")
90
+}
91
+
92
+func (s *FoundationS) TestFailureHeader(c *check.C) {
93
+	output := String{}
94
+	failHelper := FailHelper{}
95
+	check.Run(&failHelper, &check.RunConf{Output: &output})
96
+	header := fmt.Sprintf(""+
97
+		"\n-----------------------------------"+
98
+		"-----------------------------------\n"+
99
+		"FAIL: check_test.go:%d: FailHelper.TestLogAndFail\n",
100
+		failHelper.testLine)
101
+	if strings.Index(output.value, header) == -1 {
102
+		c.Errorf(""+
103
+			"Failure didn't print a proper header.\n"+
104
+			"... Got:\n%s... Expected something with:\n%s",
105
+			output.value, header)
106
+	}
107
+}
108
+
109
+func (s *FoundationS) TestFatal(c *check.C) {
110
+	var line int
111
+	defer (func() {
112
+		if !c.Failed() {
113
+			c.Error("Fatal() didn't fail the test")
114
+		} else {
115
+			c.Succeed()
116
+			expected := fmt.Sprintf("foundation_test.go:%d:\n"+
117
+				"    c.Fatal(\"Die \", \"now!\")\n"+
118
+				"... Error: Die now!\n\n",
119
+				line)
120
+			if c.GetTestLog() != expected {
121
+				c.Error("Incorrect log:", c.GetTestLog())
122
+			}
123
+		}
124
+	})()
125
+
126
+	line = getMyLine() + 1
127
+	c.Fatal("Die ", "now!")
128
+	c.Log("Fatal() didn't stop the test")
129
+}
130
+
131
+func (s *FoundationS) TestFatalf(c *check.C) {
132
+	var line int
133
+	defer (func() {
134
+		if !c.Failed() {
135
+			c.Error("Fatalf() didn't fail the test")
136
+		} else {
137
+			c.Succeed()
138
+			expected := fmt.Sprintf("foundation_test.go:%d:\n"+
139
+				"    c.Fatalf(\"Die %%s!\", \"now\")\n"+
140
+				"... Error: Die now!\n\n",
141
+				line)
142
+			if c.GetTestLog() != expected {
143
+				c.Error("Incorrect log:", c.GetTestLog())
144
+			}
145
+		}
146
+	})()
147
+
148
+	line = getMyLine() + 1
149
+	c.Fatalf("Die %s!", "now")
150
+	c.Log("Fatalf() didn't stop the test")
151
+}
152
+
153
+func (s *FoundationS) TestCallerLoggingInsideTest(c *check.C) {
154
+	log := fmt.Sprintf(""+
155
+		"foundation_test.go:%d:\n"+
156
+		"    result := c.Check\\(10, check.Equals, 20\\)\n"+
157
+		"\\.\\.\\. obtained int = 10\n"+
158
+		"\\.\\.\\. expected int = 20\n\n",
159
+		getMyLine()+1)
160
+	result := c.Check(10, check.Equals, 20)
161
+	checkState(c, result,
162
+		&expectedState{
163
+			name:   "Check(10, Equals, 20)",
164
+			result: false,
165
+			failed: true,
166
+			log:    log,
167
+		})
168
+}
169
+
170
+func (s *FoundationS) TestCallerLoggingInDifferentFile(c *check.C) {
171
+	result, line := checkEqualWrapper(c, 10, 20)
172
+	testLine := getMyLine() - 1
173
+	log := fmt.Sprintf(""+
174
+		"foundation_test.go:%d:\n"+
175
+		"    result, line := checkEqualWrapper\\(c, 10, 20\\)\n"+
176
+		"check_test.go:%d:\n"+
177
+		"    return c.Check\\(obtained, check.Equals, expected\\), getMyLine\\(\\)\n"+
178
+		"\\.\\.\\. obtained int = 10\n"+
179
+		"\\.\\.\\. expected int = 20\n\n",
180
+		testLine, line)
181
+	checkState(c, result,
182
+		&expectedState{
183
+			name:   "Check(10, Equals, 20)",
184
+			result: false,
185
+			failed: true,
186
+			log:    log,
187
+		})
188
+}
189
+
190
+// -----------------------------------------------------------------------
191
+// ExpectFailure() inverts the logic of failure.
192
+
193
+type ExpectFailureSucceedHelper struct{}
194
+
195
+func (s *ExpectFailureSucceedHelper) TestSucceed(c *check.C) {
196
+	c.ExpectFailure("It booms!")
197
+	c.Error("Boom!")
198
+}
199
+
200
+type ExpectFailureFailHelper struct{}
201
+
202
+func (s *ExpectFailureFailHelper) TestFail(c *check.C) {
203
+	c.ExpectFailure("Bug #XYZ")
204
+}
205
+
206
+func (s *FoundationS) TestExpectFailureFail(c *check.C) {
207
+	helper := ExpectFailureFailHelper{}
208
+	output := String{}
209
+	result := check.Run(&helper, &check.RunConf{Output: &output})
210
+
211
+	expected := "" +
212
+		"^\n-+\n" +
213
+		"FAIL: foundation_test\\.go:[0-9]+:" +
214
+		" ExpectFailureFailHelper\\.TestFail\n\n" +
215
+		"\\.\\.\\. Error: Test succeeded, but was expected to fail\n" +
216
+		"\\.\\.\\. Reason: Bug #XYZ\n$"
217
+
218
+	matched, err := regexp.MatchString(expected, output.value)
219
+	if err != nil {
220
+		c.Error("Bad expression: ", expected)
221
+	} else if !matched {
222
+		c.Error("ExpectFailure() didn't log properly:\n", output.value)
223
+	}
224
+
225
+	c.Assert(result.ExpectedFailures, check.Equals, 0)
226
+}
227
+
228
+func (s *FoundationS) TestExpectFailureSucceed(c *check.C) {
229
+	helper := ExpectFailureSucceedHelper{}
230
+	output := String{}
231
+	result := check.Run(&helper, &check.RunConf{Output: &output})
232
+
233
+	c.Assert(output.value, check.Equals, "")
234
+	c.Assert(result.ExpectedFailures, check.Equals, 1)
235
+}
236
+
237
+func (s *FoundationS) TestExpectFailureSucceedVerbose(c *check.C) {
238
+	helper := ExpectFailureSucceedHelper{}
239
+	output := String{}
240
+	result := check.Run(&helper, &check.RunConf{Output: &output, Verbose: true})
241
+
242
+	expected := "" +
243
+		"FAIL EXPECTED: foundation_test\\.go:[0-9]+:" +
244
+		" ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\t *[.0-9]+s\n"
245
+
246
+	matched, err := regexp.MatchString(expected, output.value)
247
+	if err != nil {
248
+		c.Error("Bad expression: ", expected)
249
+	} else if !matched {
250
+		c.Error("ExpectFailure() didn't log properly:\n", output.value)
251
+	}
252
+
253
+	c.Assert(result.ExpectedFailures, check.Equals, 1)
254
+}
255
+
256
+// -----------------------------------------------------------------------
257
+// Skip() allows stopping a test without positive/negative results.
258
+
259
+type SkipTestHelper struct{}
260
+
261
+func (s *SkipTestHelper) TestFail(c *check.C) {
262
+	c.Skip("Wrong platform or whatever")
263
+	c.Error("Boom!")
264
+}
265
+
266
+func (s *FoundationS) TestSkip(c *check.C) {
267
+	helper := SkipTestHelper{}
268
+	output := String{}
269
+	check.Run(&helper, &check.RunConf{Output: &output})
270
+
271
+	if output.value != "" {
272
+		c.Error("Skip() logged something:\n", output.value)
273
+	}
274
+}
275
+
276
+func (s *FoundationS) TestSkipVerbose(c *check.C) {
277
+	helper := SkipTestHelper{}
278
+	output := String{}
279
+	check.Run(&helper, &check.RunConf{Output: &output, Verbose: true})
280
+
281
+	expected := "SKIP: foundation_test\\.go:[0-9]+: SkipTestHelper\\.TestFail" +
282
+		" \\(Wrong platform or whatever\\)"
283
+	matched, err := regexp.MatchString(expected, output.value)
284
+	if err != nil {
285
+		c.Error("Bad expression: ", expected)
286
+	} else if !matched {
287
+		c.Error("Skip() didn't log properly:\n", output.value)
288
+	}
289
+}
290
+
291
+// -----------------------------------------------------------------------
292
+// Check minimum *log.Logger interface provided by *check.C.
293
+
294
+type minLogger interface {
295
+	Output(calldepth int, s string) error
296
+}
297
+
298
+func (s *BootstrapS) TestMinLogger(c *check.C) {
299
+	var logger minLogger
300
+	logger = log.New(os.Stderr, "", 0)
301
+	logger = c
302
+	logger.Output(0, "Hello there")
303
+	expected := `\[LOG\] [0-9]+:[0-9][0-9]\.[0-9][0-9][0-9] +Hello there\n`
304
+	output := c.GetTestLog()
305
+	c.Assert(output, check.Matches, expected)
306
+}
307
+
308
+// -----------------------------------------------------------------------
309
+// Ensure that suites with embedded types are working fine, including the
310
+// the workaround for issue 906.
311
+
312
+type EmbeddedInternalS struct {
313
+	called bool
314
+}
315
+
316
+type EmbeddedS struct {
317
+	EmbeddedInternalS
318
+}
319
+
320
+var embeddedS = check.Suite(&EmbeddedS{})
321
+
322
+func (s *EmbeddedS) TestCountSuite(c *check.C) {
323
+	suitesRun += 1
324
+}
325
+
326
+func (s *EmbeddedInternalS) TestMethod(c *check.C) {
327
+	c.Error("TestMethod() of the embedded type was called!?")
328
+}
329
+
330
+func (s *EmbeddedS) TestMethod(c *check.C) {
331
+	// http://code.google.com/p/go/issues/detail?id=906
332
+	c.Check(s.called, check.Equals, false) // Go issue 906 is affecting the runner?
333
+	s.called = true
334
+}
0 335
new file mode 100644
... ...
@@ -0,0 +1,231 @@
0
+package check
1
+
2
+import (
3
+	"fmt"
4
+	"strings"
5
+	"time"
6
+)
7
+
8
+// TestName returns the current test name in the form "SuiteName.TestName"
9
+func (c *C) TestName() string {
10
+	return c.testName
11
+}
12
+
13
+// -----------------------------------------------------------------------
14
+// Basic succeeding/failing logic.
15
+
16
+// Failed returns whether the currently running test has already failed.
17
+func (c *C) Failed() bool {
18
+	return c.status == failedSt
19
+}
20
+
21
+// Fail marks the currently running test as failed.
22
+//
23
+// Something ought to have been previously logged so the developer can tell
24
+// what went wrong. The higher level helper functions will fail the test
25
+// and do the logging properly.
26
+func (c *C) Fail() {
27
+	c.status = failedSt
28
+}
29
+
30
+// FailNow marks the currently running test as failed and stops running it.
31
+// Something ought to have been previously logged so the developer can tell
32
+// what went wrong. The higher level helper functions will fail the test
33
+// and do the logging properly.
34
+func (c *C) FailNow() {
35
+	c.Fail()
36
+	c.stopNow()
37
+}
38
+
39
+// Succeed marks the currently running test as succeeded, undoing any
40
+// previous failures.
41
+func (c *C) Succeed() {
42
+	c.status = succeededSt
43
+}
44
+
45
+// SucceedNow marks the currently running test as succeeded, undoing any
46
+// previous failures, and stops running the test.
47
+func (c *C) SucceedNow() {
48
+	c.Succeed()
49
+	c.stopNow()
50
+}
51
+
52
+// ExpectFailure informs that the running test is knowingly broken for
53
+// the provided reason. If the test does not fail, an error will be reported
54
+// to raise attention to this fact. This method is useful to temporarily
55
+// disable tests which cover well known problems until a better time to
56
+// fix the problem is found, without forgetting about the fact that a
57
+// failure still exists.
58
+func (c *C) ExpectFailure(reason string) {
59
+	if reason == "" {
60
+		panic("Missing reason why the test is expected to fail")
61
+	}
62
+	c.mustFail = true
63
+	c.reason = reason
64
+}
65
+
66
+// Skip skips the running test for the provided reason. If run from within
67
+// SetUpTest, the individual test being set up will be skipped, and if run
68
+// from within SetUpSuite, the whole suite is skipped.
69
+func (c *C) Skip(reason string) {
70
+	if reason == "" {
71
+		panic("Missing reason why the test is being skipped")
72
+	}
73
+	c.reason = reason
74
+	c.status = skippedSt
75
+	c.stopNow()
76
+}
77
+
78
+// -----------------------------------------------------------------------
79
+// Basic logging.
80
+
81
+// GetTestLog returns the current test error output.
82
+func (c *C) GetTestLog() string {
83
+	return c.logb.String()
84
+}
85
+
86
+// Log logs some information into the test error output.
87
+// The provided arguments are assembled together into a string with fmt.Sprint.
88
+func (c *C) Log(args ...interface{}) {
89
+	c.log(args...)
90
+}
91
+
92
+// Log logs some information into the test error output.
93
+// The provided arguments are assembled together into a string with fmt.Sprintf.
94
+func (c *C) Logf(format string, args ...interface{}) {
95
+	c.logf(format, args...)
96
+}
97
+
98
+// Output enables *C to be used as a logger in functions that require only
99
+// the minimum interface of *log.Logger.
100
+func (c *C) Output(calldepth int, s string) error {
101
+	d := time.Now().Sub(c.startTime)
102
+	msec := d / time.Millisecond
103
+	sec := d / time.Second
104
+	min := d / time.Minute
105
+
106
+	c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s)
107
+	return nil
108
+}
109
+
110
+// Error logs an error into the test error output and marks the test as failed.
111
+// The provided arguments are assembled together into a string with fmt.Sprint.
112
+func (c *C) Error(args ...interface{}) {
113
+	c.logCaller(1)
114
+	c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
115
+	c.logNewLine()
116
+	c.Fail()
117
+}
118
+
119
+// Errorf logs an error into the test error output and marks the test as failed.
120
+// The provided arguments are assembled together into a string with fmt.Sprintf.
121
+func (c *C) Errorf(format string, args ...interface{}) {
122
+	c.logCaller(1)
123
+	c.logString(fmt.Sprintf("Error: "+format, args...))
124
+	c.logNewLine()
125
+	c.Fail()
126
+}
127
+
128
+// Fatal logs an error into the test error output, marks the test as failed, and
129
+// stops the test execution. The provided arguments are assembled together into
130
+// a string with fmt.Sprint.
131
+func (c *C) Fatal(args ...interface{}) {
132
+	c.logCaller(1)
133
+	c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
134
+	c.logNewLine()
135
+	c.FailNow()
136
+}
137
+
138
+// Fatlaf logs an error into the test error output, marks the test as failed, and
139
+// stops the test execution. The provided arguments are assembled together into
140
+// a string with fmt.Sprintf.
141
+func (c *C) Fatalf(format string, args ...interface{}) {
142
+	c.logCaller(1)
143
+	c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...)))
144
+	c.logNewLine()
145
+	c.FailNow()
146
+}
147
+
148
+// -----------------------------------------------------------------------
149
+// Generic checks and assertions based on checkers.
150
+
151
+// Check verifies if the first value matches the expected value according
152
+// to the provided checker. If they do not match, an error is logged, the
153
+// test is marked as failed, and the test execution continues.
154
+//
155
+// Some checkers may not need the expected argument (e.g. IsNil).
156
+//
157
+// Extra arguments provided to the function are logged next to the reported
158
+// problem when the matching fails.
159
+func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool {
160
+	return c.internalCheck("Check", obtained, checker, args...)
161
+}
162
+
163
+// Assert ensures that the first value matches the expected value according
164
+// to the provided checker. If they do not match, an error is logged, the
165
+// test is marked as failed, and the test execution stops.
166
+//
167
+// Some checkers may not need the expected argument (e.g. IsNil).
168
+//
169
+// Extra arguments provided to the function are logged next to the reported
170
+// problem when the matching fails.
171
+func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) {
172
+	if !c.internalCheck("Assert", obtained, checker, args...) {
173
+		c.stopNow()
174
+	}
175
+}
176
+
177
+func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool {
178
+	if checker == nil {
179
+		c.logCaller(2)
180
+		c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName))
181
+		c.logString("Oops.. you've provided a nil checker!")
182
+		c.logNewLine()
183
+		c.Fail()
184
+		return false
185
+	}
186
+
187
+	// If the last argument is a bug info, extract it out.
188
+	var comment CommentInterface
189
+	if len(args) > 0 {
190
+		if c, ok := args[len(args)-1].(CommentInterface); ok {
191
+			comment = c
192
+			args = args[:len(args)-1]
193
+		}
194
+	}
195
+
196
+	params := append([]interface{}{obtained}, args...)
197
+	info := checker.Info()
198
+
199
+	if len(params) != len(info.Params) {
200
+		names := append([]string{info.Params[0], info.Name}, info.Params[1:]...)
201
+		c.logCaller(2)
202
+		c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", ")))
203
+		c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1))
204
+		c.logNewLine()
205
+		c.Fail()
206
+		return false
207
+	}
208
+
209
+	// Copy since it may be mutated by Check.
210
+	names := append([]string{}, info.Params...)
211
+
212
+	// Do the actual check.
213
+	result, error := checker.Check(params, names)
214
+	if !result || error != "" {
215
+		c.logCaller(2)
216
+		for i := 0; i != len(params); i++ {
217
+			c.logValue(names[i], params[i])
218
+		}
219
+		if comment != nil {
220
+			c.logString(comment.CheckCommentString())
221
+		}
222
+		if error != "" {
223
+			c.logString(error)
224
+		}
225
+		c.logNewLine()
226
+		c.Fail()
227
+		return false
228
+	}
229
+	return true
230
+}
0 231
new file mode 100644
... ...
@@ -0,0 +1,519 @@
0
+// These tests verify the inner workings of the helper methods associated
1
+// with check.T.
2
+
3
+package check_test
4
+
5
+import (
6
+	"gopkg.in/check.v1"
7
+	"os"
8
+	"reflect"
9
+	"runtime"
10
+	"sync"
11
+)
12
+
13
+var helpersS = check.Suite(&HelpersS{})
14
+
15
+type HelpersS struct{}
16
+
17
+func (s *HelpersS) TestCountSuite(c *check.C) {
18
+	suitesRun += 1
19
+}
20
+
21
+// -----------------------------------------------------------------------
22
+// Fake checker and bug info to verify the behavior of Assert() and Check().
23
+
24
+type MyChecker struct {
25
+	info   *check.CheckerInfo
26
+	params []interface{}
27
+	names  []string
28
+	result bool
29
+	error  string
30
+}
31
+
32
+func (checker *MyChecker) Info() *check.CheckerInfo {
33
+	if checker.info == nil {
34
+		return &check.CheckerInfo{Name: "MyChecker", Params: []string{"myobtained", "myexpected"}}
35
+	}
36
+	return checker.info
37
+}
38
+
39
+func (checker *MyChecker) Check(params []interface{}, names []string) (bool, string) {
40
+	rparams := checker.params
41
+	rnames := checker.names
42
+	checker.params = append([]interface{}{}, params...)
43
+	checker.names = append([]string{}, names...)
44
+	if rparams != nil {
45
+		copy(params, rparams)
46
+	}
47
+	if rnames != nil {
48
+		copy(names, rnames)
49
+	}
50
+	return checker.result, checker.error
51
+}
52
+
53
+type myCommentType string
54
+
55
+func (c myCommentType) CheckCommentString() string {
56
+	return string(c)
57
+}
58
+
59
+func myComment(s string) myCommentType {
60
+	return myCommentType(s)
61
+}
62
+
63
+// -----------------------------------------------------------------------
64
+// Ensure a real checker actually works fine.
65
+
66
+func (s *HelpersS) TestCheckerInterface(c *check.C) {
67
+	testHelperSuccess(c, "Check(1, Equals, 1)", true, func() interface{} {
68
+		return c.Check(1, check.Equals, 1)
69
+	})
70
+}
71
+
72
+// -----------------------------------------------------------------------
73
+// Tests for Check(), mostly the same as for Assert() following these.
74
+
75
+func (s *HelpersS) TestCheckSucceedWithExpected(c *check.C) {
76
+	checker := &MyChecker{result: true}
77
+	testHelperSuccess(c, "Check(1, checker, 2)", true, func() interface{} {
78
+		return c.Check(1, checker, 2)
79
+	})
80
+	if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) {
81
+		c.Fatalf("Bad params for check: %#v", checker.params)
82
+	}
83
+}
84
+
85
+func (s *HelpersS) TestCheckSucceedWithoutExpected(c *check.C) {
86
+	checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
87
+	testHelperSuccess(c, "Check(1, checker)", true, func() interface{} {
88
+		return c.Check(1, checker)
89
+	})
90
+	if !reflect.DeepEqual(checker.params, []interface{}{1}) {
91
+		c.Fatalf("Bad params for check: %#v", checker.params)
92
+	}
93
+}
94
+
95
+func (s *HelpersS) TestCheckFailWithExpected(c *check.C) {
96
+	checker := &MyChecker{result: false}
97
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
98
+		"    return c\\.Check\\(1, checker, 2\\)\n" +
99
+		"\\.+ myobtained int = 1\n" +
100
+		"\\.+ myexpected int = 2\n\n"
101
+	testHelperFailure(c, "Check(1, checker, 2)", false, false, log,
102
+		func() interface{} {
103
+			return c.Check(1, checker, 2)
104
+		})
105
+}
106
+
107
+func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *check.C) {
108
+	checker := &MyChecker{result: false}
109
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
110
+		"    return c\\.Check\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
111
+		"\\.+ myobtained int = 1\n" +
112
+		"\\.+ myexpected int = 2\n" +
113
+		"\\.+ Hello world!\n\n"
114
+	testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
115
+		func() interface{} {
116
+			return c.Check(1, checker, 2, myComment("Hello world!"))
117
+		})
118
+}
119
+
120
+func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *check.C) {
121
+	checker := &MyChecker{result: false}
122
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
123
+		"    // Nice leading comment\\.\n" +
124
+		"    return c\\.Check\\(1, checker, 2\\) // Hello there\n" +
125
+		"\\.+ myobtained int = 1\n" +
126
+		"\\.+ myexpected int = 2\n\n"
127
+	testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
128
+		func() interface{} {
129
+			// Nice leading comment.
130
+			return c.Check(1, checker, 2) // Hello there
131
+		})
132
+}
133
+
134
+func (s *HelpersS) TestCheckFailWithoutExpected(c *check.C) {
135
+	checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
136
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
137
+		"    return c\\.Check\\(1, checker\\)\n" +
138
+		"\\.+ myvalue int = 1\n\n"
139
+	testHelperFailure(c, "Check(1, checker)", false, false, log,
140
+		func() interface{} {
141
+			return c.Check(1, checker)
142
+		})
143
+}
144
+
145
+func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *check.C) {
146
+	checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
147
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
148
+		"    return c\\.Check\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
149
+		"\\.+ myvalue int = 1\n" +
150
+		"\\.+ Hello world!\n\n"
151
+	testHelperFailure(c, "Check(1, checker, msg)", false, false, log,
152
+		func() interface{} {
153
+			return c.Check(1, checker, myComment("Hello world!"))
154
+		})
155
+}
156
+
157
+func (s *HelpersS) TestCheckWithMissingExpected(c *check.C) {
158
+	checker := &MyChecker{result: true}
159
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
160
+		"    return c\\.Check\\(1, checker\\)\n" +
161
+		"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
162
+		"\\.+ Wrong number of parameters for MyChecker: " +
163
+		"want 3, got 2\n\n"
164
+	testHelperFailure(c, "Check(1, checker, !?)", false, false, log,
165
+		func() interface{} {
166
+			return c.Check(1, checker)
167
+		})
168
+}
169
+
170
+func (s *HelpersS) TestCheckWithTooManyExpected(c *check.C) {
171
+	checker := &MyChecker{result: true}
172
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
173
+		"    return c\\.Check\\(1, checker, 2, 3\\)\n" +
174
+		"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
175
+		"\\.+ Wrong number of parameters for MyChecker: " +
176
+		"want 3, got 4\n\n"
177
+	testHelperFailure(c, "Check(1, checker, 2, 3)", false, false, log,
178
+		func() interface{} {
179
+			return c.Check(1, checker, 2, 3)
180
+		})
181
+}
182
+
183
+func (s *HelpersS) TestCheckWithError(c *check.C) {
184
+	checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
185
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
186
+		"    return c\\.Check\\(1, checker, 2\\)\n" +
187
+		"\\.+ myobtained int = 1\n" +
188
+		"\\.+ myexpected int = 2\n" +
189
+		"\\.+ Some not so cool data provided!\n\n"
190
+	testHelperFailure(c, "Check(1, checker, 2)", false, false, log,
191
+		func() interface{} {
192
+			return c.Check(1, checker, 2)
193
+		})
194
+}
195
+
196
+func (s *HelpersS) TestCheckWithNilChecker(c *check.C) {
197
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
198
+		"    return c\\.Check\\(1, nil\\)\n" +
199
+		"\\.+ Check\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
200
+		"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
201
+	testHelperFailure(c, "Check(obtained, nil)", false, false, log,
202
+		func() interface{} {
203
+			return c.Check(1, nil)
204
+		})
205
+}
206
+
207
+func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *check.C) {
208
+	checker := &MyChecker{result: false, params: []interface{}{3, 4}, names: []string{"newobtained", "newexpected"}}
209
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
210
+		"    return c\\.Check\\(1, checker, 2\\)\n" +
211
+		"\\.+ newobtained int = 3\n" +
212
+		"\\.+ newexpected int = 4\n\n"
213
+	testHelperFailure(c, "Check(1, checker, 2) with mutation", false, false, log,
214
+		func() interface{} {
215
+			return c.Check(1, checker, 2)
216
+		})
217
+}
218
+
219
+// -----------------------------------------------------------------------
220
+// Tests for Assert(), mostly the same as for Check() above.
221
+
222
+func (s *HelpersS) TestAssertSucceedWithExpected(c *check.C) {
223
+	checker := &MyChecker{result: true}
224
+	testHelperSuccess(c, "Assert(1, checker, 2)", nil, func() interface{} {
225
+		c.Assert(1, checker, 2)
226
+		return nil
227
+	})
228
+	if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) {
229
+		c.Fatalf("Bad params for check: %#v", checker.params)
230
+	}
231
+}
232
+
233
+func (s *HelpersS) TestAssertSucceedWithoutExpected(c *check.C) {
234
+	checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
235
+	testHelperSuccess(c, "Assert(1, checker)", nil, func() interface{} {
236
+		c.Assert(1, checker)
237
+		return nil
238
+	})
239
+	if !reflect.DeepEqual(checker.params, []interface{}{1}) {
240
+		c.Fatalf("Bad params for check: %#v", checker.params)
241
+	}
242
+}
243
+
244
+func (s *HelpersS) TestAssertFailWithExpected(c *check.C) {
245
+	checker := &MyChecker{result: false}
246
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
247
+		"    c\\.Assert\\(1, checker, 2\\)\n" +
248
+		"\\.+ myobtained int = 1\n" +
249
+		"\\.+ myexpected int = 2\n\n"
250
+	testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log,
251
+		func() interface{} {
252
+			c.Assert(1, checker, 2)
253
+			return nil
254
+		})
255
+}
256
+
257
+func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *check.C) {
258
+	checker := &MyChecker{result: false}
259
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
260
+		"    c\\.Assert\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
261
+		"\\.+ myobtained int = 1\n" +
262
+		"\\.+ myexpected int = 2\n" +
263
+		"\\.+ Hello world!\n\n"
264
+	testHelperFailure(c, "Assert(1, checker, 2, msg)", nil, true, log,
265
+		func() interface{} {
266
+			c.Assert(1, checker, 2, myComment("Hello world!"))
267
+			return nil
268
+		})
269
+}
270
+
271
+func (s *HelpersS) TestAssertFailWithoutExpected(c *check.C) {
272
+	checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
273
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
274
+		"    c\\.Assert\\(1, checker\\)\n" +
275
+		"\\.+ myvalue int = 1\n\n"
276
+	testHelperFailure(c, "Assert(1, checker)", nil, true, log,
277
+		func() interface{} {
278
+			c.Assert(1, checker)
279
+			return nil
280
+		})
281
+}
282
+
283
+func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *check.C) {
284
+	checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
285
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
286
+		"    c\\.Assert\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
287
+		"\\.+ myvalue int = 1\n" +
288
+		"\\.+ Hello world!\n\n"
289
+	testHelperFailure(c, "Assert(1, checker, msg)", nil, true, log,
290
+		func() interface{} {
291
+			c.Assert(1, checker, myComment("Hello world!"))
292
+			return nil
293
+		})
294
+}
295
+
296
+func (s *HelpersS) TestAssertWithMissingExpected(c *check.C) {
297
+	checker := &MyChecker{result: true}
298
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
299
+		"    c\\.Assert\\(1, checker\\)\n" +
300
+		"\\.+ Assert\\(myobtained, MyChecker, myexpected\\):\n" +
301
+		"\\.+ Wrong number of parameters for MyChecker: " +
302
+		"want 3, got 2\n\n"
303
+	testHelperFailure(c, "Assert(1, checker, !?)", nil, true, log,
304
+		func() interface{} {
305
+			c.Assert(1, checker)
306
+			return nil
307
+		})
308
+}
309
+
310
+func (s *HelpersS) TestAssertWithError(c *check.C) {
311
+	checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
312
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
313
+		"    c\\.Assert\\(1, checker, 2\\)\n" +
314
+		"\\.+ myobtained int = 1\n" +
315
+		"\\.+ myexpected int = 2\n" +
316
+		"\\.+ Some not so cool data provided!\n\n"
317
+	testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log,
318
+		func() interface{} {
319
+			c.Assert(1, checker, 2)
320
+			return nil
321
+		})
322
+}
323
+
324
+func (s *HelpersS) TestAssertWithNilChecker(c *check.C) {
325
+	log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
326
+		"    c\\.Assert\\(1, nil\\)\n" +
327
+		"\\.+ Assert\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
328
+		"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
329
+	testHelperFailure(c, "Assert(obtained, nil)", nil, true, log,
330
+		func() interface{} {
331
+			c.Assert(1, nil)
332
+			return nil
333
+		})
334
+}
335
+
336
+// -----------------------------------------------------------------------
337
+// Ensure that values logged work properly in some interesting cases.
338
+
339
+func (s *HelpersS) TestValueLoggingWithArrays(c *check.C) {
340
+	checker := &MyChecker{result: false}
341
+	log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
342
+		"    return c\\.Check\\(\\[\\]byte{1, 2}, checker, \\[\\]byte{1, 3}\\)\n" +
343
+		"\\.+ myobtained \\[\\]uint8 = \\[\\]byte{0x1, 0x2}\n" +
344
+		"\\.+ myexpected \\[\\]uint8 = \\[\\]byte{0x1, 0x3}\n\n"
345
+	testHelperFailure(c, "Check([]byte{1}, chk, []byte{3})", false, false, log,
346
+		func() interface{} {
347
+			return c.Check([]byte{1, 2}, checker, []byte{1, 3})
348
+		})
349
+}
350
+
351
+func (s *HelpersS) TestValueLoggingWithMultiLine(c *check.C) {
352
+	checker := &MyChecker{result: false}
353
+	log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
354
+		"    return c\\.Check\\(\"a\\\\nb\\\\n\", checker, \"a\\\\nb\\\\nc\"\\)\n" +
355
+		"\\.+ myobtained string = \"\" \\+\n" +
356
+		"\\.+     \"a\\\\n\" \\+\n" +
357
+		"\\.+     \"b\\\\n\"\n" +
358
+		"\\.+ myexpected string = \"\" \\+\n" +
359
+		"\\.+     \"a\\\\n\" \\+\n" +
360
+		"\\.+     \"b\\\\n\" \\+\n" +
361
+		"\\.+     \"c\"\n\n"
362
+	testHelperFailure(c, `Check("a\nb\n", chk, "a\nb\nc")`, false, false, log,
363
+		func() interface{} {
364
+			return c.Check("a\nb\n", checker, "a\nb\nc")
365
+		})
366
+}
367
+
368
+func (s *HelpersS) TestValueLoggingWithMultiLineException(c *check.C) {
369
+	// If the newline is at the end of the string, don't log as multi-line.
370
+	checker := &MyChecker{result: false}
371
+	log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
372
+		"    return c\\.Check\\(\"a b\\\\n\", checker, \"a\\\\nb\"\\)\n" +
373
+		"\\.+ myobtained string = \"a b\\\\n\"\n" +
374
+		"\\.+ myexpected string = \"\" \\+\n" +
375
+		"\\.+     \"a\\\\n\" \\+\n" +
376
+		"\\.+     \"b\"\n\n"
377
+	testHelperFailure(c, `Check("a b\n", chk, "a\nb")`, false, false, log,
378
+		func() interface{} {
379
+			return c.Check("a b\n", checker, "a\nb")
380
+		})
381
+}
382
+
383
+// -----------------------------------------------------------------------
384
+// MakeDir() tests.
385
+
386
+type MkDirHelper struct {
387
+	path1  string
388
+	path2  string
389
+	isDir1 bool
390
+	isDir2 bool
391
+	isDir3 bool
392
+	isDir4 bool
393
+}
394
+
395
+func (s *MkDirHelper) SetUpSuite(c *check.C) {
396
+	s.path1 = c.MkDir()
397
+	s.isDir1 = isDir(s.path1)
398
+}
399
+
400
+func (s *MkDirHelper) Test(c *check.C) {
401
+	s.path2 = c.MkDir()
402
+	s.isDir2 = isDir(s.path2)
403
+}
404
+
405
+func (s *MkDirHelper) TearDownSuite(c *check.C) {
406
+	s.isDir3 = isDir(s.path1)
407
+	s.isDir4 = isDir(s.path2)
408
+}
409
+
410
+func (s *HelpersS) TestMkDir(c *check.C) {
411
+	helper := MkDirHelper{}
412
+	output := String{}
413
+	check.Run(&helper, &check.RunConf{Output: &output})
414
+	c.Assert(output.value, check.Equals, "")
415
+	c.Check(helper.isDir1, check.Equals, true)
416
+	c.Check(helper.isDir2, check.Equals, true)
417
+	c.Check(helper.isDir3, check.Equals, true)
418
+	c.Check(helper.isDir4, check.Equals, true)
419
+	c.Check(helper.path1, check.Not(check.Equals),
420
+		helper.path2)
421
+	c.Check(isDir(helper.path1), check.Equals, false)
422
+	c.Check(isDir(helper.path2), check.Equals, false)
423
+}
424
+
425
+func isDir(path string) bool {
426
+	if stat, err := os.Stat(path); err == nil {
427
+		return stat.IsDir()
428
+	}
429
+	return false
430
+}
431
+
432
+// Concurrent logging should not corrupt the underling buffer.
433
+// Use go test -race to detect the race in this test.
434
+func (s *HelpersS) TestConcurrentLogging(c *check.C) {
435
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU()))
436
+	var start, stop sync.WaitGroup
437
+	start.Add(1)
438
+	for i, n := 0, runtime.NumCPU()*2; i < n; i++ {
439
+		stop.Add(1)
440
+		go func(i int) {
441
+			start.Wait()
442
+			for j := 0; j < 30; j++ {
443
+				c.Logf("Worker %d: line %d", i, j)
444
+			}
445
+			stop.Done()
446
+		}(i)
447
+	}
448
+	start.Done()
449
+	stop.Wait()
450
+}
451
+
452
+// -----------------------------------------------------------------------
453
+// Test the TestName function
454
+
455
+type TestNameHelper struct {
456
+	name1 string
457
+	name2 string
458
+	name3 string
459
+	name4 string
460
+	name5 string
461
+}
462
+
463
+func (s *TestNameHelper) SetUpSuite(c *check.C)    { s.name1 = c.TestName() }
464
+func (s *TestNameHelper) SetUpTest(c *check.C)     { s.name2 = c.TestName() }
465
+func (s *TestNameHelper) Test(c *check.C)          { s.name3 = c.TestName() }
466
+func (s *TestNameHelper) TearDownTest(c *check.C)  { s.name4 = c.TestName() }
467
+func (s *TestNameHelper) TearDownSuite(c *check.C) { s.name5 = c.TestName() }
468
+
469
+func (s *HelpersS) TestTestName(c *check.C) {
470
+	helper := TestNameHelper{}
471
+	output := String{}
472
+	check.Run(&helper, &check.RunConf{Output: &output})
473
+	c.Check(helper.name1, check.Equals, "")
474
+	c.Check(helper.name2, check.Equals, "TestNameHelper.Test")
475
+	c.Check(helper.name3, check.Equals, "TestNameHelper.Test")
476
+	c.Check(helper.name4, check.Equals, "TestNameHelper.Test")
477
+	c.Check(helper.name5, check.Equals, "")
478
+}
479
+
480
+// -----------------------------------------------------------------------
481
+// A couple of helper functions to test helper functions. :-)
482
+
483
+func testHelperSuccess(c *check.C, name string, expectedResult interface{}, closure func() interface{}) {
484
+	var result interface{}
485
+	defer (func() {
486
+		if err := recover(); err != nil {
487
+			panic(err)
488
+		}
489
+		checkState(c, result,
490
+			&expectedState{
491
+				name:   name,
492
+				result: expectedResult,
493
+				failed: false,
494
+				log:    "",
495
+			})
496
+	})()
497
+	result = closure()
498
+}
499
+
500
+func testHelperFailure(c *check.C, name string, expectedResult interface{}, shouldStop bool, log string, closure func() interface{}) {
501
+	var result interface{}
502
+	defer (func() {
503
+		if err := recover(); err != nil {
504
+			panic(err)
505
+		}
506
+		checkState(c, result,
507
+			&expectedState{
508
+				name:   name,
509
+				result: expectedResult,
510
+				failed: true,
511
+				log:    log,
512
+			})
513
+	})()
514
+	result = closure()
515
+	if shouldStop {
516
+		c.Logf("%s didn't stop when it should", name)
517
+	}
518
+}
0 519
new file mode 100644
... ...
@@ -0,0 +1,168 @@
0
+package check
1
+
2
+import (
3
+	"bytes"
4
+	"go/ast"
5
+	"go/parser"
6
+	"go/printer"
7
+	"go/token"
8
+	"os"
9
+)
10
+
11
+func indent(s, with string) (r string) {
12
+	eol := true
13
+	for i := 0; i != len(s); i++ {
14
+		c := s[i]
15
+		switch {
16
+		case eol && c == '\n' || c == '\r':
17
+		case c == '\n' || c == '\r':
18
+			eol = true
19
+		case eol:
20
+			eol = false
21
+			s = s[:i] + with + s[i:]
22
+			i += len(with)
23
+		}
24
+	}
25
+	return s
26
+}
27
+
28
+func printLine(filename string, line int) (string, error) {
29
+	fset := token.NewFileSet()
30
+	file, err := os.Open(filename)
31
+	if err != nil {
32
+		return "", err
33
+	}
34
+	fnode, err := parser.ParseFile(fset, filename, file, parser.ParseComments)
35
+	if err != nil {
36
+		return "", err
37
+	}
38
+	config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: 4}
39
+	lp := &linePrinter{fset: fset, fnode: fnode, line: line, config: config}
40
+	ast.Walk(lp, fnode)
41
+	result := lp.output.Bytes()
42
+	// Comments leave \n at the end.
43
+	n := len(result)
44
+	for n > 0 && result[n-1] == '\n' {
45
+		n--
46
+	}
47
+	return string(result[:n]), nil
48
+}
49
+
50
+type linePrinter struct {
51
+	config *printer.Config
52
+	fset   *token.FileSet
53
+	fnode  *ast.File
54
+	line   int
55
+	output bytes.Buffer
56
+	stmt   ast.Stmt
57
+}
58
+
59
+func (lp *linePrinter) emit() bool {
60
+	if lp.stmt != nil {
61
+		lp.trim(lp.stmt)
62
+		lp.printWithComments(lp.stmt)
63
+		lp.stmt = nil
64
+		return true
65
+	}
66
+	return false
67
+}
68
+
69
+func (lp *linePrinter) printWithComments(n ast.Node) {
70
+	nfirst := lp.fset.Position(n.Pos()).Line
71
+	nlast := lp.fset.Position(n.End()).Line
72
+	for _, g := range lp.fnode.Comments {
73
+		cfirst := lp.fset.Position(g.Pos()).Line
74
+		clast := lp.fset.Position(g.End()).Line
75
+		if clast == nfirst-1 && lp.fset.Position(n.Pos()).Column == lp.fset.Position(g.Pos()).Column {
76
+			for _, c := range g.List {
77
+				lp.output.WriteString(c.Text)
78
+				lp.output.WriteByte('\n')
79
+			}
80
+		}
81
+		if cfirst >= nfirst && cfirst <= nlast && n.End() <= g.List[0].Slash {
82
+			// The printer will not include the comment if it starts past
83
+			// the node itself. Trick it into printing by overlapping the
84
+			// slash with the end of the statement.
85
+			g.List[0].Slash = n.End() - 1
86
+		}
87
+	}
88
+	node := &printer.CommentedNode{n, lp.fnode.Comments}
89
+	lp.config.Fprint(&lp.output, lp.fset, node)
90
+}
91
+
92
+func (lp *linePrinter) Visit(n ast.Node) (w ast.Visitor) {
93
+	if n == nil {
94
+		if lp.output.Len() == 0 {
95
+			lp.emit()
96
+		}
97
+		return nil
98
+	}
99
+	first := lp.fset.Position(n.Pos()).Line
100
+	last := lp.fset.Position(n.End()).Line
101
+	if first <= lp.line && last >= lp.line {
102
+		// Print the innermost statement containing the line.
103
+		if stmt, ok := n.(ast.Stmt); ok {
104
+			if _, ok := n.(*ast.BlockStmt); !ok {
105
+				lp.stmt = stmt
106
+			}
107
+		}
108
+		if first == lp.line && lp.emit() {
109
+			return nil
110
+		}
111
+		return lp
112
+	}
113
+	return nil
114
+}
115
+
116
+func (lp *linePrinter) trim(n ast.Node) bool {
117
+	stmt, ok := n.(ast.Stmt)
118
+	if !ok {
119
+		return true
120
+	}
121
+	line := lp.fset.Position(n.Pos()).Line
122
+	if line != lp.line {
123
+		return false
124
+	}
125
+	switch stmt := stmt.(type) {
126
+	case *ast.IfStmt:
127
+		stmt.Body = lp.trimBlock(stmt.Body)
128
+	case *ast.SwitchStmt:
129
+		stmt.Body = lp.trimBlock(stmt.Body)
130
+	case *ast.TypeSwitchStmt:
131
+		stmt.Body = lp.trimBlock(stmt.Body)
132
+	case *ast.CaseClause:
133
+		stmt.Body = lp.trimList(stmt.Body)
134
+	case *ast.CommClause:
135
+		stmt.Body = lp.trimList(stmt.Body)
136
+	case *ast.BlockStmt:
137
+		stmt.List = lp.trimList(stmt.List)
138
+	}
139
+	return true
140
+}
141
+
142
+func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt {
143
+	if !lp.trim(stmt) {
144
+		return lp.emptyBlock(stmt)
145
+	}
146
+	stmt.Rbrace = stmt.Lbrace
147
+	return stmt
148
+}
149
+
150
+func (lp *linePrinter) trimList(stmts []ast.Stmt) []ast.Stmt {
151
+	for i := 0; i != len(stmts); i++ {
152
+		if !lp.trim(stmts[i]) {
153
+			stmts[i] = lp.emptyStmt(stmts[i])
154
+			break
155
+		}
156
+	}
157
+	return stmts
158
+}
159
+
160
+func (lp *linePrinter) emptyStmt(n ast.Node) *ast.ExprStmt {
161
+	return &ast.ExprStmt{&ast.Ellipsis{n.Pos(), nil}}
162
+}
163
+
164
+func (lp *linePrinter) emptyBlock(n ast.Node) *ast.BlockStmt {
165
+	p := n.Pos()
166
+	return &ast.BlockStmt{p, []ast.Stmt{lp.emptyStmt(n)}, p}
167
+}
0 168
new file mode 100644
... ...
@@ -0,0 +1,104 @@
0
+package check_test
1
+
2
+import (
3
+    .   "gopkg.in/check.v1"
4
+)
5
+
6
+var _ = Suite(&PrinterS{})
7
+
8
+type PrinterS struct{}
9
+
10
+func (s *PrinterS) TestCountSuite(c *C) {
11
+    suitesRun += 1
12
+}
13
+
14
+var printTestFuncLine int
15
+
16
+func init() {
17
+    printTestFuncLine = getMyLine() + 3
18
+}
19
+
20
+func printTestFunc() {
21
+    println(1)           // Comment1
22
+    if 2 == 2 {          // Comment2
23
+        println(3)       // Comment3
24
+    }
25
+    switch 5 {
26
+    case 6: println(6)   // Comment6
27
+        println(7)
28
+    }
29
+    switch interface{}(9).(type) {// Comment9
30
+    case int: println(10)
31
+        println(11)
32
+    }
33
+    select {
34
+    case <-(chan bool)(nil): println(14)
35
+        println(15)
36
+    default: println(16)
37
+        println(17)
38
+    }
39
+    println(19,
40
+        20)
41
+    _ = func() { println(21)
42
+        println(22)
43
+    }
44
+    println(24, func() {
45
+        println(25)
46
+    })
47
+    // Leading comment
48
+    // with multiple lines.
49
+    println(29)  // Comment29
50
+}
51
+
52
+var printLineTests = []struct {
53
+    line   int
54
+    output string
55
+}{
56
+    {1, "println(1) // Comment1"},
57
+    {2, "if 2 == 2 { // Comment2\n    ...\n}"},
58
+    {3, "println(3) // Comment3"},
59
+    {5, "switch 5 {\n...\n}"},
60
+    {6, "case 6:\n    println(6) // Comment6\n    ..."},
61
+    {7, "println(7)"},
62
+    {9, "switch interface{}(9).(type) { // Comment9\n...\n}"},
63
+    {10, "case int:\n    println(10)\n    ..."},
64
+    {14, "case <-(chan bool)(nil):\n    println(14)\n    ..."},
65
+    {15, "println(15)"},
66
+    {16, "default:\n    println(16)\n    ..."},
67
+    {17, "println(17)"},
68
+    {19, "println(19,\n    20)"},
69
+    {20, "println(19,\n    20)"},
70
+    {21, "_ = func() {\n    println(21)\n    println(22)\n}"},
71
+    {22, "println(22)"},
72
+    {24, "println(24, func() {\n    println(25)\n})"},
73
+    {25, "println(25)"},
74
+    {26, "println(24, func() {\n    println(25)\n})"},
75
+    {29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"},
76
+}
77
+
78
+func (s *PrinterS) TestPrintLine(c *C) {
79
+    for _, test := range printLineTests {
80
+        output, err := PrintLine("printer_test.go", printTestFuncLine+test.line)
81
+        c.Assert(err, IsNil)
82
+        c.Assert(output, Equals, test.output)
83
+    }
84
+}
85
+
86
+var indentTests = []struct {
87
+    in, out string
88
+}{
89
+    {"", ""},
90
+    {"\n", "\n"},
91
+    {"a", ">>>a"},
92
+    {"a\n", ">>>a\n"},
93
+    {"a\nb", ">>>a\n>>>b"},
94
+    {" ", ">>> "},
95
+}
96
+
97
+func (s *PrinterS) TestIndent(c *C) {
98
+    for _, test := range indentTests {
99
+        out := Indent(test.in, ">>>")
100
+        c.Assert(out, Equals, test.out)
101
+    }
102
+
103
+}
0 104
new file mode 100644
... ...
@@ -0,0 +1,175 @@
0
+package check
1
+
2
+import (
3
+	"bufio"
4
+	"flag"
5
+	"fmt"
6
+	"os"
7
+	"testing"
8
+	"time"
9
+)
10
+
11
+// -----------------------------------------------------------------------
12
+// Test suite registry.
13
+
14
+var allSuites []interface{}
15
+
16
+// Suite registers the given value as a test suite to be run. Any methods
17
+// starting with the Test prefix in the given value will be considered as
18
+// a test method.
19
+func Suite(suite interface{}) interface{} {
20
+	allSuites = append(allSuites, suite)
21
+	return suite
22
+}
23
+
24
+// -----------------------------------------------------------------------
25
+// Public running interface.
26
+
27
+var (
28
+	oldFilterFlag  = flag.String("gocheck.f", "", "Regular expression selecting which tests and/or suites to run")
29
+	oldVerboseFlag = flag.Bool("gocheck.v", false, "Verbose mode")
30
+	oldStreamFlag  = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)")
31
+	oldBenchFlag   = flag.Bool("gocheck.b", false, "Run benchmarks")
32
+	oldBenchTime   = flag.Duration("gocheck.btime", 1*time.Second, "approximate run time for each benchmark")
33
+	oldListFlag    = flag.Bool("gocheck.list", false, "List the names of all tests that will be run")
34
+	oldWorkFlag    = flag.Bool("gocheck.work", false, "Display and do not remove the test working directory")
35
+
36
+	newFilterFlag  = flag.String("check.f", "", "Regular expression selecting which tests and/or suites to run")
37
+	newVerboseFlag = flag.Bool("check.v", false, "Verbose mode")
38
+	newStreamFlag  = flag.Bool("check.vv", false, "Super verbose mode (disables output caching)")
39
+	newBenchFlag   = flag.Bool("check.b", false, "Run benchmarks")
40
+	newBenchTime   = flag.Duration("check.btime", 1*time.Second, "approximate run time for each benchmark")
41
+	newBenchMem    = flag.Bool("check.bmem", false, "Report memory benchmarks")
42
+	newListFlag    = flag.Bool("check.list", false, "List the names of all tests that will be run")
43
+	newWorkFlag    = flag.Bool("check.work", false, "Display and do not remove the test working directory")
44
+)
45
+
46
+// TestingT runs all test suites registered with the Suite function,
47
+// printing results to stdout, and reporting any failures back to
48
+// the "testing" package.
49
+func TestingT(testingT *testing.T) {
50
+	benchTime := *newBenchTime
51
+	if benchTime == 1*time.Second {
52
+		benchTime = *oldBenchTime
53
+	}
54
+	conf := &RunConf{
55
+		Filter:        *oldFilterFlag + *newFilterFlag,
56
+		Verbose:       *oldVerboseFlag || *newVerboseFlag,
57
+		Stream:        *oldStreamFlag || *newStreamFlag,
58
+		Benchmark:     *oldBenchFlag || *newBenchFlag,
59
+		BenchmarkTime: benchTime,
60
+		BenchmarkMem:  *newBenchMem,
61
+		KeepWorkDir:   *oldWorkFlag || *newWorkFlag,
62
+	}
63
+	if *oldListFlag || *newListFlag {
64
+		w := bufio.NewWriter(os.Stdout)
65
+		for _, name := range ListAll(conf) {
66
+			fmt.Fprintln(w, name)
67
+		}
68
+		w.Flush()
69
+		return
70
+	}
71
+	result := RunAll(conf)
72
+	println(result.String())
73
+	if !result.Passed() {
74
+		testingT.Fail()
75
+	}
76
+}
77
+
78
+// RunAll runs all test suites registered with the Suite function, using the
79
+// provided run configuration.
80
+func RunAll(runConf *RunConf) *Result {
81
+	result := Result{}
82
+	for _, suite := range allSuites {
83
+		result.Add(Run(suite, runConf))
84
+	}
85
+	return &result
86
+}
87
+
88
+// Run runs the provided test suite using the provided run configuration.
89
+func Run(suite interface{}, runConf *RunConf) *Result {
90
+	runner := newSuiteRunner(suite, runConf)
91
+	return runner.run()
92
+}
93
+
94
+// ListAll returns the names of all the test functions registered with the
95
+// Suite function that will be run with the provided run configuration.
96
+func ListAll(runConf *RunConf) []string {
97
+	var names []string
98
+	for _, suite := range allSuites {
99
+		names = append(names, List(suite, runConf)...)
100
+	}
101
+	return names
102
+}
103
+
104
+// List returns the names of the test functions in the given
105
+// suite that will be run with the provided run configuration.
106
+func List(suite interface{}, runConf *RunConf) []string {
107
+	var names []string
108
+	runner := newSuiteRunner(suite, runConf)
109
+	for _, t := range runner.tests {
110
+		names = append(names, t.String())
111
+	}
112
+	return names
113
+}
114
+
115
+// -----------------------------------------------------------------------
116
+// Result methods.
117
+
118
+func (r *Result) Add(other *Result) {
119
+	r.Succeeded += other.Succeeded
120
+	r.Skipped += other.Skipped
121
+	r.Failed += other.Failed
122
+	r.Panicked += other.Panicked
123
+	r.FixturePanicked += other.FixturePanicked
124
+	r.ExpectedFailures += other.ExpectedFailures
125
+	r.Missed += other.Missed
126
+	if r.WorkDir != "" && other.WorkDir != "" {
127
+		r.WorkDir += ":" + other.WorkDir
128
+	} else if other.WorkDir != "" {
129
+		r.WorkDir = other.WorkDir
130
+	}
131
+}
132
+
133
+func (r *Result) Passed() bool {
134
+	return (r.Failed == 0 && r.Panicked == 0 &&
135
+		r.FixturePanicked == 0 && r.Missed == 0 &&
136
+		r.RunError == nil)
137
+}
138
+
139
+func (r *Result) String() string {
140
+	if r.RunError != nil {
141
+		return "ERROR: " + r.RunError.Error()
142
+	}
143
+
144
+	var value string
145
+	if r.Failed == 0 && r.Panicked == 0 && r.FixturePanicked == 0 &&
146
+		r.Missed == 0 {
147
+		value = "OK: "
148
+	} else {
149
+		value = "OOPS: "
150
+	}
151
+	value += fmt.Sprintf("%d passed", r.Succeeded)
152
+	if r.Skipped != 0 {
153
+		value += fmt.Sprintf(", %d skipped", r.Skipped)
154
+	}
155
+	if r.ExpectedFailures != 0 {
156
+		value += fmt.Sprintf(", %d expected failures", r.ExpectedFailures)
157
+	}
158
+	if r.Failed != 0 {
159
+		value += fmt.Sprintf(", %d FAILED", r.Failed)
160
+	}
161
+	if r.Panicked != 0 {
162
+		value += fmt.Sprintf(", %d PANICKED", r.Panicked)
163
+	}
164
+	if r.FixturePanicked != 0 {
165
+		value += fmt.Sprintf(", %d FIXTURE-PANICKED", r.FixturePanicked)
166
+	}
167
+	if r.Missed != 0 {
168
+		value += fmt.Sprintf(", %d MISSED", r.Missed)
169
+	}
170
+	if r.WorkDir != "" {
171
+		value += "\nWORK=" + r.WorkDir
172
+	}
173
+	return value
174
+}
0 175
new file mode 100644
... ...
@@ -0,0 +1,419 @@
0
+// These tests verify the test running logic.
1
+
2
+package check_test
3
+
4
+import (
5
+	"errors"
6
+	. "gopkg.in/check.v1"
7
+	"os"
8
+	"sync"
9
+)
10
+
11
+var runnerS = Suite(&RunS{})
12
+
13
+type RunS struct{}
14
+
15
+func (s *RunS) TestCountSuite(c *C) {
16
+	suitesRun += 1
17
+}
18
+
19
+// -----------------------------------------------------------------------
20
+// Tests ensuring result counting works properly.
21
+
22
+func (s *RunS) TestSuccess(c *C) {
23
+	output := String{}
24
+	result := Run(&SuccessHelper{}, &RunConf{Output: &output})
25
+	c.Check(result.Succeeded, Equals, 1)
26
+	c.Check(result.Failed, Equals, 0)
27
+	c.Check(result.Skipped, Equals, 0)
28
+	c.Check(result.Panicked, Equals, 0)
29
+	c.Check(result.FixturePanicked, Equals, 0)
30
+	c.Check(result.Missed, Equals, 0)
31
+	c.Check(result.RunError, IsNil)
32
+}
33
+
34
+func (s *RunS) TestFailure(c *C) {
35
+	output := String{}
36
+	result := Run(&FailHelper{}, &RunConf{Output: &output})
37
+	c.Check(result.Succeeded, Equals, 0)
38
+	c.Check(result.Failed, Equals, 1)
39
+	c.Check(result.Skipped, Equals, 0)
40
+	c.Check(result.Panicked, Equals, 0)
41
+	c.Check(result.FixturePanicked, Equals, 0)
42
+	c.Check(result.Missed, Equals, 0)
43
+	c.Check(result.RunError, IsNil)
44
+}
45
+
46
+func (s *RunS) TestFixture(c *C) {
47
+	output := String{}
48
+	result := Run(&FixtureHelper{}, &RunConf{Output: &output})
49
+	c.Check(result.Succeeded, Equals, 2)
50
+	c.Check(result.Failed, Equals, 0)
51
+	c.Check(result.Skipped, Equals, 0)
52
+	c.Check(result.Panicked, Equals, 0)
53
+	c.Check(result.FixturePanicked, Equals, 0)
54
+	c.Check(result.Missed, Equals, 0)
55
+	c.Check(result.RunError, IsNil)
56
+}
57
+
58
+func (s *RunS) TestPanicOnTest(c *C) {
59
+	output := String{}
60
+	helper := &FixtureHelper{panicOn: "Test1"}
61
+	result := Run(helper, &RunConf{Output: &output})
62
+	c.Check(result.Succeeded, Equals, 1)
63
+	c.Check(result.Failed, Equals, 0)
64
+	c.Check(result.Skipped, Equals, 0)
65
+	c.Check(result.Panicked, Equals, 1)
66
+	c.Check(result.FixturePanicked, Equals, 0)
67
+	c.Check(result.Missed, Equals, 0)
68
+	c.Check(result.RunError, IsNil)
69
+}
70
+
71
+func (s *RunS) TestPanicOnSetUpTest(c *C) {
72
+	output := String{}
73
+	helper := &FixtureHelper{panicOn: "SetUpTest"}
74
+	result := Run(helper, &RunConf{Output: &output})
75
+	c.Check(result.Succeeded, Equals, 0)
76
+	c.Check(result.Failed, Equals, 0)
77
+	c.Check(result.Skipped, Equals, 0)
78
+	c.Check(result.Panicked, Equals, 0)
79
+	c.Check(result.FixturePanicked, Equals, 1)
80
+	c.Check(result.Missed, Equals, 2)
81
+	c.Check(result.RunError, IsNil)
82
+}
83
+
84
+func (s *RunS) TestPanicOnSetUpSuite(c *C) {
85
+	output := String{}
86
+	helper := &FixtureHelper{panicOn: "SetUpSuite"}
87
+	result := Run(helper, &RunConf{Output: &output})
88
+	c.Check(result.Succeeded, Equals, 0)
89
+	c.Check(result.Failed, Equals, 0)
90
+	c.Check(result.Skipped, Equals, 0)
91
+	c.Check(result.Panicked, Equals, 0)
92
+	c.Check(result.FixturePanicked, Equals, 1)
93
+	c.Check(result.Missed, Equals, 2)
94
+	c.Check(result.RunError, IsNil)
95
+}
96
+
97
+// -----------------------------------------------------------------------
98
+// Check result aggregation.
99
+
100
+func (s *RunS) TestAdd(c *C) {
101
+	result := &Result{
102
+		Succeeded:        1,
103
+		Skipped:          2,
104
+		Failed:           3,
105
+		Panicked:         4,
106
+		FixturePanicked:  5,
107
+		Missed:           6,
108
+		ExpectedFailures: 7,
109
+	}
110
+	result.Add(&Result{
111
+		Succeeded:        10,
112
+		Skipped:          20,
113
+		Failed:           30,
114
+		Panicked:         40,
115
+		FixturePanicked:  50,
116
+		Missed:           60,
117
+		ExpectedFailures: 70,
118
+	})
119
+	c.Check(result.Succeeded, Equals, 11)
120
+	c.Check(result.Skipped, Equals, 22)
121
+	c.Check(result.Failed, Equals, 33)
122
+	c.Check(result.Panicked, Equals, 44)
123
+	c.Check(result.FixturePanicked, Equals, 55)
124
+	c.Check(result.Missed, Equals, 66)
125
+	c.Check(result.ExpectedFailures, Equals, 77)
126
+	c.Check(result.RunError, IsNil)
127
+}
128
+
129
+// -----------------------------------------------------------------------
130
+// Check the Passed() method.
131
+
132
+func (s *RunS) TestPassed(c *C) {
133
+	c.Assert((&Result{}).Passed(), Equals, true)
134
+	c.Assert((&Result{Succeeded: 1}).Passed(), Equals, true)
135
+	c.Assert((&Result{Skipped: 1}).Passed(), Equals, true)
136
+	c.Assert((&Result{Failed: 1}).Passed(), Equals, false)
137
+	c.Assert((&Result{Panicked: 1}).Passed(), Equals, false)
138
+	c.Assert((&Result{FixturePanicked: 1}).Passed(), Equals, false)
139
+	c.Assert((&Result{Missed: 1}).Passed(), Equals, false)
140
+	c.Assert((&Result{RunError: errors.New("!")}).Passed(), Equals, false)
141
+}
142
+
143
+// -----------------------------------------------------------------------
144
+// Check that result printing is working correctly.
145
+
146
+func (s *RunS) TestPrintSuccess(c *C) {
147
+	result := &Result{Succeeded: 5}
148
+	c.Check(result.String(), Equals, "OK: 5 passed")
149
+}
150
+
151
+func (s *RunS) TestPrintFailure(c *C) {
152
+	result := &Result{Failed: 5}
153
+	c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FAILED")
154
+}
155
+
156
+func (s *RunS) TestPrintSkipped(c *C) {
157
+	result := &Result{Skipped: 5}
158
+	c.Check(result.String(), Equals, "OK: 0 passed, 5 skipped")
159
+}
160
+
161
+func (s *RunS) TestPrintExpectedFailures(c *C) {
162
+	result := &Result{ExpectedFailures: 5}
163
+	c.Check(result.String(), Equals, "OK: 0 passed, 5 expected failures")
164
+}
165
+
166
+func (s *RunS) TestPrintPanicked(c *C) {
167
+	result := &Result{Panicked: 5}
168
+	c.Check(result.String(), Equals, "OOPS: 0 passed, 5 PANICKED")
169
+}
170
+
171
+func (s *RunS) TestPrintFixturePanicked(c *C) {
172
+	result := &Result{FixturePanicked: 5}
173
+	c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FIXTURE-PANICKED")
174
+}
175
+
176
+func (s *RunS) TestPrintMissed(c *C) {
177
+	result := &Result{Missed: 5}
178
+	c.Check(result.String(), Equals, "OOPS: 0 passed, 5 MISSED")
179
+}
180
+
181
+func (s *RunS) TestPrintAll(c *C) {
182
+	result := &Result{Succeeded: 1, Skipped: 2, ExpectedFailures: 3,
183
+		Panicked: 4, FixturePanicked: 5, Missed: 6}
184
+	c.Check(result.String(), Equals,
185
+		"OOPS: 1 passed, 2 skipped, 3 expected failures, 4 PANICKED, "+
186
+			"5 FIXTURE-PANICKED, 6 MISSED")
187
+}
188
+
189
+func (s *RunS) TestPrintRunError(c *C) {
190
+	result := &Result{Succeeded: 1, Failed: 1,
191
+		RunError: errors.New("Kaboom!")}
192
+	c.Check(result.String(), Equals, "ERROR: Kaboom!")
193
+}
194
+
195
+// -----------------------------------------------------------------------
196
+// Verify that the method pattern flag works correctly.
197
+
198
+func (s *RunS) TestFilterTestName(c *C) {
199
+	helper := FixtureHelper{}
200
+	output := String{}
201
+	runConf := RunConf{Output: &output, Filter: "Test[91]"}
202
+	Run(&helper, &runConf)
203
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
204
+	c.Check(helper.calls[1], Equals, "SetUpTest")
205
+	c.Check(helper.calls[2], Equals, "Test1")
206
+	c.Check(helper.calls[3], Equals, "TearDownTest")
207
+	c.Check(helper.calls[4], Equals, "TearDownSuite")
208
+	c.Check(len(helper.calls), Equals, 5)
209
+}
210
+
211
+func (s *RunS) TestFilterTestNameWithAll(c *C) {
212
+	helper := FixtureHelper{}
213
+	output := String{}
214
+	runConf := RunConf{Output: &output, Filter: ".*"}
215
+	Run(&helper, &runConf)
216
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
217
+	c.Check(helper.calls[1], Equals, "SetUpTest")
218
+	c.Check(helper.calls[2], Equals, "Test1")
219
+	c.Check(helper.calls[3], Equals, "TearDownTest")
220
+	c.Check(helper.calls[4], Equals, "SetUpTest")
221
+	c.Check(helper.calls[5], Equals, "Test2")
222
+	c.Check(helper.calls[6], Equals, "TearDownTest")
223
+	c.Check(helper.calls[7], Equals, "TearDownSuite")
224
+	c.Check(len(helper.calls), Equals, 8)
225
+}
226
+
227
+func (s *RunS) TestFilterSuiteName(c *C) {
228
+	helper := FixtureHelper{}
229
+	output := String{}
230
+	runConf := RunConf{Output: &output, Filter: "FixtureHelper"}
231
+	Run(&helper, &runConf)
232
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
233
+	c.Check(helper.calls[1], Equals, "SetUpTest")
234
+	c.Check(helper.calls[2], Equals, "Test1")
235
+	c.Check(helper.calls[3], Equals, "TearDownTest")
236
+	c.Check(helper.calls[4], Equals, "SetUpTest")
237
+	c.Check(helper.calls[5], Equals, "Test2")
238
+	c.Check(helper.calls[6], Equals, "TearDownTest")
239
+	c.Check(helper.calls[7], Equals, "TearDownSuite")
240
+	c.Check(len(helper.calls), Equals, 8)
241
+}
242
+
243
+func (s *RunS) TestFilterSuiteNameAndTestName(c *C) {
244
+	helper := FixtureHelper{}
245
+	output := String{}
246
+	runConf := RunConf{Output: &output, Filter: "FixtureHelper\\.Test2"}
247
+	Run(&helper, &runConf)
248
+	c.Check(helper.calls[0], Equals, "SetUpSuite")
249
+	c.Check(helper.calls[1], Equals, "SetUpTest")
250
+	c.Check(helper.calls[2], Equals, "Test2")
251
+	c.Check(helper.calls[3], Equals, "TearDownTest")
252
+	c.Check(helper.calls[4], Equals, "TearDownSuite")
253
+	c.Check(len(helper.calls), Equals, 5)
254
+}
255
+
256
+func (s *RunS) TestFilterAllOut(c *C) {
257
+	helper := FixtureHelper{}
258
+	output := String{}
259
+	runConf := RunConf{Output: &output, Filter: "NotFound"}
260
+	Run(&helper, &runConf)
261
+	c.Check(len(helper.calls), Equals, 0)
262
+}
263
+
264
+func (s *RunS) TestRequirePartialMatch(c *C) {
265
+	helper := FixtureHelper{}
266
+	output := String{}
267
+	runConf := RunConf{Output: &output, Filter: "est"}
268
+	Run(&helper, &runConf)
269
+	c.Check(len(helper.calls), Equals, 8)
270
+}
271
+
272
+func (s *RunS) TestFilterError(c *C) {
273
+	helper := FixtureHelper{}
274
+	output := String{}
275
+	runConf := RunConf{Output: &output, Filter: "]["}
276
+	result := Run(&helper, &runConf)
277
+	c.Check(result.String(), Equals,
278
+		"ERROR: Bad filter expression: error parsing regexp: missing closing ]: `[`")
279
+	c.Check(len(helper.calls), Equals, 0)
280
+}
281
+
282
+// -----------------------------------------------------------------------
283
+// Verify that List works correctly.
284
+
285
+func (s *RunS) TestListFiltered(c *C) {
286
+	names := List(&FixtureHelper{}, &RunConf{Filter: "1"})
287
+	c.Assert(names, DeepEquals, []string{
288
+		"FixtureHelper.Test1",
289
+	})
290
+}
291
+
292
+func (s *RunS) TestList(c *C) {
293
+	names := List(&FixtureHelper{}, &RunConf{})
294
+	c.Assert(names, DeepEquals, []string{
295
+		"FixtureHelper.Test1",
296
+		"FixtureHelper.Test2",
297
+	})
298
+}
299
+
300
+// -----------------------------------------------------------------------
301
+// Verify that verbose mode prints tests which pass as well.
302
+
303
+func (s *RunS) TestVerboseMode(c *C) {
304
+	helper := FixtureHelper{}
305
+	output := String{}
306
+	runConf := RunConf{Output: &output, Verbose: true}
307
+	Run(&helper, &runConf)
308
+
309
+	expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t *[.0-9]+s\n" +
310
+		"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
311
+
312
+	c.Assert(output.value, Matches, expected)
313
+}
314
+
315
+func (s *RunS) TestVerboseModeWithFailBeforePass(c *C) {
316
+	helper := FixtureHelper{panicOn: "Test1"}
317
+	output := String{}
318
+	runConf := RunConf{Output: &output, Verbose: true}
319
+	Run(&helper, &runConf)
320
+
321
+	expected := "(?s).*PANIC.*\n-+\n" + // Should have an extra line.
322
+		"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
323
+
324
+	c.Assert(output.value, Matches, expected)
325
+}
326
+
327
+// -----------------------------------------------------------------------
328
+// Verify the stream output mode.  In this mode there's no output caching.
329
+
330
+type StreamHelper struct {
331
+	l2 sync.Mutex
332
+	l3 sync.Mutex
333
+}
334
+
335
+func (s *StreamHelper) SetUpSuite(c *C) {
336
+	c.Log("0")
337
+}
338
+
339
+func (s *StreamHelper) Test1(c *C) {
340
+	c.Log("1")
341
+	s.l2.Lock()
342
+	s.l3.Lock()
343
+	go func() {
344
+		s.l2.Lock() // Wait for "2".
345
+		c.Log("3")
346
+		s.l3.Unlock()
347
+	}()
348
+}
349
+
350
+func (s *StreamHelper) Test2(c *C) {
351
+	c.Log("2")
352
+	s.l2.Unlock()
353
+	s.l3.Lock() // Wait for "3".
354
+	c.Fail()
355
+	c.Log("4")
356
+}
357
+
358
+func (s *RunS) TestStreamMode(c *C) {
359
+	helper := &StreamHelper{}
360
+	output := String{}
361
+	runConf := RunConf{Output: &output, Stream: true}
362
+	Run(helper, &runConf)
363
+
364
+	expected := "START: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n0\n" +
365
+		"PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\t *[.0-9]+s\n\n" +
366
+		"START: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n1\n" +
367
+		"PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\t *[.0-9]+s\n\n" +
368
+		"START: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n2\n3\n4\n" +
369
+		"FAIL: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n\n"
370
+
371
+	c.Assert(output.value, Matches, expected)
372
+}
373
+
374
+type StreamMissHelper struct{}
375
+
376
+func (s *StreamMissHelper) SetUpSuite(c *C) {
377
+	c.Log("0")
378
+	c.Fail()
379
+}
380
+
381
+func (s *StreamMissHelper) Test1(c *C) {
382
+	c.Log("1")
383
+}
384
+
385
+func (s *RunS) TestStreamModeWithMiss(c *C) {
386
+	helper := &StreamMissHelper{}
387
+	output := String{}
388
+	runConf := RunConf{Output: &output, Stream: true}
389
+	Run(helper, &runConf)
390
+
391
+	expected := "START: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n0\n" +
392
+		"FAIL: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n\n" +
393
+		"START: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n" +
394
+		"MISS: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n\n"
395
+
396
+	c.Assert(output.value, Matches, expected)
397
+}
398
+
399
+// -----------------------------------------------------------------------
400
+// Verify that that the keep work dir request indeed does so.
401
+
402
+type WorkDirSuite struct {}
403
+
404
+func (s *WorkDirSuite) Test(c *C) {
405
+	c.MkDir()
406
+}
407
+
408
+func (s *RunS) TestKeepWorkDir(c *C) {
409
+	output := String{}
410
+	runConf := RunConf{Output: &output, Verbose: true, KeepWorkDir: true}
411
+	result := Run(&WorkDirSuite{}, &runConf)
412
+
413
+	c.Assert(result.String(), Matches, ".*\nWORK=" + result.WorkDir)
414
+
415
+	stat, err := os.Stat(result.WorkDir)
416
+	c.Assert(err, IsNil)
417
+	c.Assert(stat.IsDir(), Equals, true)
418
+}