...

Source file src/github.com/golang/mock/gomock/matchers.go

Documentation: github.com/golang/mock/gomock

     1  // Copyright 2010 Google Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gomock
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"strings"
    21  )
    22  
    23  // A Matcher is a representation of a class of values.
    24  // It is used to represent the valid or expected arguments to a mocked method.
    25  type Matcher interface {
    26  	// Matches returns whether x is a match.
    27  	Matches(x interface{}) bool
    28  
    29  	// String describes what the matcher matches.
    30  	String() string
    31  }
    32  
    33  // WantFormatter modifies the given Matcher's String() method to the given
    34  // Stringer. This allows for control on how the "Want" is formatted when
    35  // printing .
    36  func WantFormatter(s fmt.Stringer, m Matcher) Matcher {
    37  	type matcher interface {
    38  		Matches(x interface{}) bool
    39  	}
    40  
    41  	return struct {
    42  		matcher
    43  		fmt.Stringer
    44  	}{
    45  		matcher:  m,
    46  		Stringer: s,
    47  	}
    48  }
    49  
    50  // StringerFunc type is an adapter to allow the use of ordinary functions as
    51  // a Stringer. If f is a function with the appropriate signature,
    52  // StringerFunc(f) is a Stringer that calls f.
    53  type StringerFunc func() string
    54  
    55  // String implements fmt.Stringer.
    56  func (f StringerFunc) String() string {
    57  	return f()
    58  }
    59  
    60  // GotFormatter is used to better print failure messages. If a matcher
    61  // implements GotFormatter, it will use the result from Got when printing
    62  // the failure message.
    63  type GotFormatter interface {
    64  	// Got is invoked with the received value. The result is used when
    65  	// printing the failure message.
    66  	Got(got interface{}) string
    67  }
    68  
    69  // GotFormatterFunc type is an adapter to allow the use of ordinary
    70  // functions as a GotFormatter. If f is a function with the appropriate
    71  // signature, GotFormatterFunc(f) is a GotFormatter that calls f.
    72  type GotFormatterFunc func(got interface{}) string
    73  
    74  // Got implements GotFormatter.
    75  func (f GotFormatterFunc) Got(got interface{}) string {
    76  	return f(got)
    77  }
    78  
    79  // GotFormatterAdapter attaches a GotFormatter to a Matcher.
    80  func GotFormatterAdapter(s GotFormatter, m Matcher) Matcher {
    81  	return struct {
    82  		GotFormatter
    83  		Matcher
    84  	}{
    85  		GotFormatter: s,
    86  		Matcher:      m,
    87  	}
    88  }
    89  
    90  type anyMatcher struct{}
    91  
    92  func (anyMatcher) Matches(interface{}) bool {
    93  	return true
    94  }
    95  
    96  func (anyMatcher) String() string {
    97  	return "is anything"
    98  }
    99  
   100  type eqMatcher struct {
   101  	x interface{}
   102  }
   103  
   104  func (e eqMatcher) Matches(x interface{}) bool {
   105  	// In case, some value is nil
   106  	if e.x == nil || x == nil {
   107  		return reflect.DeepEqual(e.x, x)
   108  	}
   109  
   110  	// Check if types assignable and convert them to common type
   111  	x1Val := reflect.ValueOf(e.x)
   112  	x2Val := reflect.ValueOf(x)
   113  
   114  	if x1Val.Type().AssignableTo(x2Val.Type()) {
   115  		x1ValConverted := x1Val.Convert(x2Val.Type())
   116  		return reflect.DeepEqual(x1ValConverted.Interface(), x2Val.Interface())
   117  	}
   118  
   119  	return false
   120  }
   121  
   122  func (e eqMatcher) String() string {
   123  	return fmt.Sprintf("is equal to %v (%T)", e.x, e.x)
   124  }
   125  
   126  type nilMatcher struct{}
   127  
   128  func (nilMatcher) Matches(x interface{}) bool {
   129  	if x == nil {
   130  		return true
   131  	}
   132  
   133  	v := reflect.ValueOf(x)
   134  	switch v.Kind() {
   135  	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map,
   136  		reflect.Ptr, reflect.Slice:
   137  		return v.IsNil()
   138  	}
   139  
   140  	return false
   141  }
   142  
   143  func (nilMatcher) String() string {
   144  	return "is nil"
   145  }
   146  
   147  type notMatcher struct {
   148  	m Matcher
   149  }
   150  
   151  func (n notMatcher) Matches(x interface{}) bool {
   152  	return !n.m.Matches(x)
   153  }
   154  
   155  func (n notMatcher) String() string {
   156  	return "not(" + n.m.String() + ")"
   157  }
   158  
   159  type assignableToTypeOfMatcher struct {
   160  	targetType reflect.Type
   161  }
   162  
   163  func (m assignableToTypeOfMatcher) Matches(x interface{}) bool {
   164  	return reflect.TypeOf(x).AssignableTo(m.targetType)
   165  }
   166  
   167  func (m assignableToTypeOfMatcher) String() string {
   168  	return "is assignable to " + m.targetType.Name()
   169  }
   170  
   171  type allMatcher struct {
   172  	matchers []Matcher
   173  }
   174  
   175  func (am allMatcher) Matches(x interface{}) bool {
   176  	for _, m := range am.matchers {
   177  		if !m.Matches(x) {
   178  			return false
   179  		}
   180  	}
   181  	return true
   182  }
   183  
   184  func (am allMatcher) String() string {
   185  	ss := make([]string, 0, len(am.matchers))
   186  	for _, matcher := range am.matchers {
   187  		ss = append(ss, matcher.String())
   188  	}
   189  	return strings.Join(ss, "; ")
   190  }
   191  
   192  type lenMatcher struct {
   193  	i int
   194  }
   195  
   196  func (m lenMatcher) Matches(x interface{}) bool {
   197  	v := reflect.ValueOf(x)
   198  	switch v.Kind() {
   199  	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
   200  		return v.Len() == m.i
   201  	default:
   202  		return false
   203  	}
   204  }
   205  
   206  func (m lenMatcher) String() string {
   207  	return fmt.Sprintf("has length %d", m.i)
   208  }
   209  
   210  type inAnyOrderMatcher struct {
   211  	x interface{}
   212  }
   213  
   214  func (m inAnyOrderMatcher) Matches(x interface{}) bool {
   215  	given, ok := m.prepareValue(x)
   216  	if !ok {
   217  		return false
   218  	}
   219  	wanted, ok := m.prepareValue(m.x)
   220  	if !ok {
   221  		return false
   222  	}
   223  
   224  	if given.Len() != wanted.Len() {
   225  		return false
   226  	}
   227  
   228  	usedFromGiven := make([]bool, given.Len())
   229  	foundFromWanted := make([]bool, wanted.Len())
   230  	for i := 0; i < wanted.Len(); i++ {
   231  		wantedMatcher := Eq(wanted.Index(i).Interface())
   232  		for j := 0; j < given.Len(); j++ {
   233  			if usedFromGiven[j] {
   234  				continue
   235  			}
   236  			if wantedMatcher.Matches(given.Index(j).Interface()) {
   237  				foundFromWanted[i] = true
   238  				usedFromGiven[j] = true
   239  				break
   240  			}
   241  		}
   242  	}
   243  
   244  	missingFromWanted := 0
   245  	for _, found := range foundFromWanted {
   246  		if !found {
   247  			missingFromWanted++
   248  		}
   249  	}
   250  	extraInGiven := 0
   251  	for _, used := range usedFromGiven {
   252  		if !used {
   253  			extraInGiven++
   254  		}
   255  	}
   256  
   257  	return extraInGiven == 0 && missingFromWanted == 0
   258  }
   259  
   260  func (m inAnyOrderMatcher) prepareValue(x interface{}) (reflect.Value, bool) {
   261  	xValue := reflect.ValueOf(x)
   262  	switch xValue.Kind() {
   263  	case reflect.Slice, reflect.Array:
   264  		return xValue, true
   265  	default:
   266  		return reflect.Value{}, false
   267  	}
   268  }
   269  
   270  func (m inAnyOrderMatcher) String() string {
   271  	return fmt.Sprintf("has the same elements as %v", m.x)
   272  }
   273  
   274  // Constructors
   275  
   276  // All returns a composite Matcher that returns true if and only all of the
   277  // matchers return true.
   278  func All(ms ...Matcher) Matcher { return allMatcher{ms} }
   279  
   280  // Any returns a matcher that always matches.
   281  func Any() Matcher { return anyMatcher{} }
   282  
   283  // Eq returns a matcher that matches on equality.
   284  //
   285  // Example usage:
   286  //   Eq(5).Matches(5) // returns true
   287  //   Eq(5).Matches(4) // returns false
   288  func Eq(x interface{}) Matcher { return eqMatcher{x} }
   289  
   290  // Len returns a matcher that matches on length. This matcher returns false if
   291  // is compared to a type that is not an array, chan, map, slice, or string.
   292  func Len(i int) Matcher {
   293  	return lenMatcher{i}
   294  }
   295  
   296  // Nil returns a matcher that matches if the received value is nil.
   297  //
   298  // Example usage:
   299  //   var x *bytes.Buffer
   300  //   Nil().Matches(x) // returns true
   301  //   x = &bytes.Buffer{}
   302  //   Nil().Matches(x) // returns false
   303  func Nil() Matcher { return nilMatcher{} }
   304  
   305  // Not reverses the results of its given child matcher.
   306  //
   307  // Example usage:
   308  //   Not(Eq(5)).Matches(4) // returns true
   309  //   Not(Eq(5)).Matches(5) // returns false
   310  func Not(x interface{}) Matcher {
   311  	if m, ok := x.(Matcher); ok {
   312  		return notMatcher{m}
   313  	}
   314  	return notMatcher{Eq(x)}
   315  }
   316  
   317  // AssignableToTypeOf is a Matcher that matches if the parameter to the mock
   318  // function is assignable to the type of the parameter to this function.
   319  //
   320  // Example usage:
   321  //   var s fmt.Stringer = &bytes.Buffer{}
   322  //   AssignableToTypeOf(s).Matches(time.Second) // returns true
   323  //   AssignableToTypeOf(s).Matches(99) // returns false
   324  //
   325  //   var ctx = reflect.TypeOf((*context.Context)(nil)).Elem()
   326  //   AssignableToTypeOf(ctx).Matches(context.Background()) // returns true
   327  func AssignableToTypeOf(x interface{}) Matcher {
   328  	if xt, ok := x.(reflect.Type); ok {
   329  		return assignableToTypeOfMatcher{xt}
   330  	}
   331  	return assignableToTypeOfMatcher{reflect.TypeOf(x)}
   332  }
   333  
   334  // InAnyOrder is a Matcher that returns true for collections of the same elements ignoring the order.
   335  //
   336  // Example usage:
   337  //   InAnyOrder([]int{1, 2, 3}).Matches([]int{1, 3, 2}) // returns true
   338  //   InAnyOrder([]int{1, 2, 3}).Matches([]int{1, 2}) // returns false
   339  func InAnyOrder(x interface{}) Matcher {
   340  	return inAnyOrderMatcher{x}
   341  }
   342  

View as plain text