9
// -----------------------------------------------------------------------
10
// CommentInterface and Commentf helper, to attach extra information to checks.
17
// Commentf returns an infomational value to use with Assert or Check calls.
18
// If the checker test fails, the provided arguments will be passed to
19
// fmt.Sprintf, and will be presented next to the logged failure.
23
// c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i))
25
// Note that if the comment is constant, a better option is to
26
// simply use a normal comment right above or next to the line, as
27
// it will also get printed with any errors:
29
// c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123)
31
func Commentf(format string, args ...interface{}) CommentInterface {
32
return &comment{format, args}
35
// CommentInterface must be implemented by types that attach extra
36
// information to failed checks. See the Commentf function for details.
37
type CommentInterface interface {
38
CheckCommentString() string
41
func (c *comment) CheckCommentString() string {
42
return fmt.Sprintf(c.format, c.args...)
45
// -----------------------------------------------------------------------
46
// The Checker interface.
48
// The Checker interface must be provided by checkers used with
49
// the Assert and Check verification methods.
50
type Checker interface {
52
Check(params []interface{}, names []string) (result bool, error string)
55
// See the Checker interface.
56
type CheckerInfo struct {
61
func (info *CheckerInfo) Info() *CheckerInfo {
65
// -----------------------------------------------------------------------
66
// Not checker logic inverter.
68
// The Not checker inverts the logic of the provided checker. The
69
// resulting checker will succeed where the original one failed, and
74
// c.Assert(a, Not(Equals), b)
76
func Not(checker Checker) Checker {
77
return ¬Checker{checker}
80
type notChecker struct {
84
func (checker *notChecker) Info() *CheckerInfo {
85
info := *checker.sub.Info()
86
info.Name = "Not(" + info.Name + ")"
90
func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) {
91
result, error = checker.sub.Check(params, names)
96
// -----------------------------------------------------------------------
99
type isNilChecker struct {
103
// The IsNil checker tests whether the obtained value is nil.
107
// c.Assert(err, IsNil)
109
var IsNil Checker = &isNilChecker{
110
&CheckerInfo{Name: "IsNil", Params: []string{"value"}},
113
func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
114
return isNil(params[0]), ""
117
func isNil(obtained interface{}) (result bool) {
121
switch v := reflect.ValueOf(obtained); v.Kind() {
122
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
129
// -----------------------------------------------------------------------
130
// NotNil checker. Alias for Not(IsNil), since it's so common.
132
type notNilChecker struct {
136
// The NotNil checker verifies that the obtained value is not nil.
140
// c.Assert(iface, NotNil)
142
// This is an alias for Not(IsNil), made available since it's a
143
// fairly common check.
145
var NotNil Checker = ¬NilChecker{
146
&CheckerInfo{Name: "NotNil", Params: []string{"value"}},
149
func (checker *notNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
150
return !isNil(params[0]), ""
153
// -----------------------------------------------------------------------
156
type equalsChecker struct {
160
// The Equals checker verifies that the obtained value is equal to
161
// the expected value, according to usual Go semantics for ==.
165
// c.Assert(value, Equals, 42)
167
var Equals Checker = &equalsChecker{
168
&CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}},
171
func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) {
173
if v := recover(); v != nil {
175
error = fmt.Sprint(v)
178
return params[0] == params[1], ""
181
// -----------------------------------------------------------------------
182
// DeepEquals checker.
184
type deepEqualsChecker struct {
188
// The DeepEquals checker verifies that the obtained value is deep-equal to
189
// the expected value. The check will work correctly even when facing
190
// slices, interfaces, and values of different types (which always fail
195
// c.Assert(value, DeepEquals, 42)
196
// c.Assert(array, DeepEquals, []string{"hi", "there"})
198
var DeepEquals Checker = &deepEqualsChecker{
199
&CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}},
202
func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
203
return reflect.DeepEqual(params[0], params[1]), ""
206
// -----------------------------------------------------------------------
209
type hasLenChecker struct {
213
// The HasLen checker verifies that the obtained value has the
214
// provided length. In many cases this is superior to using Equals
215
// in conjuction with the len function because in case the check
216
// fails the value itself will be printed, instead of its length,
217
// providing more details for figuring the problem.
221
// c.Assert(list, HasLen, 5)
223
var HasLen Checker = &hasLenChecker{
224
&CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}},
227
func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) {
228
n, ok := params[1].(int)
230
return false, "n must be an int"
232
value := reflect.ValueOf(params[0])
233
switch value.Kind() {
234
case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String:
236
return false, "obtained value type has no length"
238
return value.Len() == n, ""
241
// -----------------------------------------------------------------------
242
// ErrorMatches checker.
244
type errorMatchesChecker struct {
248
// The ErrorMatches checker verifies that the error value
249
// is non nil and matches the regular expression provided.
253
// c.Assert(err, ErrorMatches, "perm.*denied")
255
var ErrorMatches Checker = errorMatchesChecker{
256
&CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}},
259
func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) {
260
if params[0] == nil {
261
return false, "Error value is nil"
263
err, ok := params[0].(error)
265
return false, "Value is not an error"
267
params[0] = err.Error()
269
return matches(params[0], params[1])
272
// -----------------------------------------------------------------------
275
type matchesChecker struct {
279
// The Matches checker verifies that the string provided as the obtained
280
// value (or the string resulting from obtained.String()) matches the
281
// regular expression provided.
285
// c.Assert(err, Matches, "perm.*denied")
287
var Matches Checker = &matchesChecker{
288
&CheckerInfo{Name: "Matches", Params: []string{"value", "regex"}},
291
func (checker *matchesChecker) Check(params []interface{}, names []string) (result bool, error string) {
292
return matches(params[0], params[1])
295
func matches(value, regex interface{}) (result bool, error string) {
296
reStr, ok := regex.(string)
298
return false, "Regex must be a string"
300
valueStr, valueIsStr := value.(string)
302
if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr {
303
valueStr, valueIsStr = valueWithStr.String(), true
307
matches, err := regexp.MatchString("^"+reStr+"$", valueStr)
309
return false, "Can't compile regex: " + err.Error()
313
return false, "Obtained value is not a string and has no .String()"
316
// -----------------------------------------------------------------------
319
type panicsChecker struct {
323
// The Panics checker verifies that calling the provided zero-argument
324
// function will cause a panic which is deep-equal to the provided value.
328
// c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}).
331
var Panics Checker = &panicsChecker{
332
&CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}},
335
func (checker *panicsChecker) Check(params []interface{}, names []string) (result bool, error string) {
336
f := reflect.ValueOf(params[0])
337
if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
338
return false, "Function must take zero arguments"
341
// If the function has not panicked, then don't do the check.
345
params[0] = recover()
347
result = reflect.DeepEqual(params[0], params[1])
350
return false, "Function has not panicked"
353
type panicMatchesChecker struct {
357
// The PanicMatches checker verifies that calling the provided zero-argument
358
// function will cause a panic with an error value matching
359
// the regular expression provided.
363
// c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`).
366
var PanicMatches Checker = &panicMatchesChecker{
367
&CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}},
370
func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) {
371
f := reflect.ValueOf(params[0])
372
if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
373
return false, "Function must take zero arguments"
376
// If the function has not panicked, then don't do the check.
380
obtained := recover()
382
if e, ok := obtained.(error); ok {
383
params[0] = e.Error()
384
} else if _, ok := obtained.(string); ok {
387
errmsg = "Panic value is not a string or an error"
390
result, errmsg = matches(params[0], params[1])
393
return false, "Function has not panicked"
396
// -----------------------------------------------------------------------
397
// FitsTypeOf checker.
399
type fitsTypeChecker struct {
403
// The FitsTypeOf checker verifies that the obtained value is
404
// assignable to a variable with the same type as the provided
409
// c.Assert(value, FitsTypeOf, int64(0))
410
// c.Assert(value, FitsTypeOf, os.Error(nil))
412
var FitsTypeOf Checker = &fitsTypeChecker{
413
&CheckerInfo{Name: "FitsTypeOf", Params: []string{"obtained", "sample"}},
416
func (checker *fitsTypeChecker) Check(params []interface{}, names []string) (result bool, error string) {
417
obtained := reflect.ValueOf(params[0])
418
sample := reflect.ValueOf(params[1])
419
if !obtained.IsValid() {
422
if !sample.IsValid() {
423
return false, "Invalid sample value"
425
return obtained.Type().AssignableTo(sample.Type()), ""
428
// -----------------------------------------------------------------------
429
// Implements checker.
431
type implementsChecker struct {
435
// The Implements checker verifies that the obtained value
436
// implements the interface specified via a pointer to an interface
442
// c.Assert(err, Implements, &e)
444
var Implements Checker = &implementsChecker{
445
&CheckerInfo{Name: "Implements", Params: []string{"obtained", "ifaceptr"}},
448
func (checker *implementsChecker) Check(params []interface{}, names []string) (result bool, error string) {
449
obtained := reflect.ValueOf(params[0])
450
ifaceptr := reflect.ValueOf(params[1])
451
if !obtained.IsValid() {
454
if !ifaceptr.IsValid() || ifaceptr.Kind() != reflect.Ptr || ifaceptr.Elem().Kind() != reflect.Interface {
455
return false, "ifaceptr should be a pointer to an interface variable"
457
return obtained.Type().Implements(ifaceptr.Elem().Type()), ""