launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/testing/checkers/bool.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package checkers
     5  
     6  import (
     7  	"fmt"
     8  	"reflect"
     9  
    10  	gc "launchpad.net/gocheck"
    11  )
    12  
    13  type isTrueChecker struct {
    14  	*gc.CheckerInfo
    15  }
    16  
    17  // IsTrue checks whether a value has an underlying
    18  // boolean type and is true.
    19  var IsTrue gc.Checker = &isTrueChecker{
    20  	&gc.CheckerInfo{Name: "IsTrue", Params: []string{"obtained"}},
    21  }
    22  
    23  // IsTrue checks whether a value has an underlying
    24  // boolean type and is false.
    25  var IsFalse gc.Checker = gc.Not(IsTrue)
    26  
    27  func (checker *isTrueChecker) Check(params []interface{}, names []string) (result bool, error string) {
    28  
    29  	value := reflect.ValueOf(params[0])
    30  
    31  	switch value.Kind() {
    32  	case reflect.Bool:
    33  		return value.Bool(), ""
    34  	}
    35  
    36  	return false, fmt.Sprintf("expected type bool, received type %s", value.Type())
    37  }
    38  
    39  type satisfiesChecker struct {
    40  	*gc.CheckerInfo
    41  }
    42  
    43  // Satisfies checks whether a value causes the argument
    44  // function to return true. The function must be of
    45  // type func(T) bool where the value being checked
    46  // is assignable to T.
    47  var Satisfies gc.Checker = &satisfiesChecker{
    48  	&gc.CheckerInfo{
    49  		Name:   "Satisfies",
    50  		Params: []string{"obtained", "func(T) bool"},
    51  	},
    52  }
    53  
    54  func (checker *satisfiesChecker) Check(params []interface{}, names []string) (result bool, error string) {
    55  	f := reflect.ValueOf(params[1])
    56  	ft := f.Type()
    57  	if ft.Kind() != reflect.Func ||
    58  		ft.NumIn() != 1 ||
    59  		ft.NumOut() != 1 ||
    60  		ft.Out(0) != reflect.TypeOf(true) {
    61  		return false, fmt.Sprintf("expected func(T) bool, got %s", ft)
    62  	}
    63  	v := reflect.ValueOf(params[0])
    64  	if !v.IsValid() {
    65  		if !canBeNil(ft.In(0)) {
    66  			return false, fmt.Sprintf("cannot assign nil to argument %T", ft.In(0))
    67  		}
    68  		v = reflect.Zero(ft.In(0))
    69  	}
    70  	if !v.Type().AssignableTo(ft.In(0)) {
    71  		return false, fmt.Sprintf("wrong argument type %s for %s", v.Type(), ft)
    72  	}
    73  	return f.Call([]reflect.Value{v})[0].Interface().(bool), ""
    74  }
    75  
    76  func canBeNil(t reflect.Type) bool {
    77  	switch t.Kind() {
    78  	case reflect.Chan,
    79  		reflect.Func,
    80  		reflect.Interface,
    81  		reflect.Map,
    82  		reflect.Ptr,
    83  		reflect.Slice:
    84  		return true
    85  	}
    86  	return false
    87  }
    88  
    89  type deepEqualsChecker struct {
    90  	*gc.CheckerInfo
    91  }
    92  
    93  // The DeepEquals checker verifies that the obtained value is deep-equal to
    94  // the expected value.  The check will work correctly even when facing
    95  // slices, interfaces, and values of different types (which always fail
    96  // the test).
    97  //
    98  // For example:
    99  //
   100  //     c.Assert(value, DeepEquals, 42)
   101  //     c.Assert(array, DeepEquals, []string{"hi", "there"})
   102  //
   103  // This checker differs from gocheck.DeepEquals in that
   104  // it will compare a nil slice equal to an empty slice,
   105  // and a nil map equal to an empty map.
   106  var DeepEquals gc.Checker = &deepEqualsChecker{
   107  	&gc.CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}},
   108  }
   109  
   110  func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
   111  	if ok, err := DeepEqual(params[0], params[1]); !ok {
   112  		return false, err.Error()
   113  	}
   114  	return true, ""
   115  }