func expectationMatches(exp *InternalExpectation, args []interface{}) bool {
	matchers := exp.ArgMatchers
	if len(args) != len(matchers) {
		panic("expectationMatches: len(args)")
	}
	for i, matcher := range matchers {
		if err := matcher.Matches(args[i]); err != nil {
			return false
		}
	}
	return true
}
expectationMatches checks the matchers for the expectation against the
supplied arguments.
package oglemock
import (
	"errors"
	"fmt"
	"log"
	"math"
	"reflect"
	"sync"
)
type PartialExpecation func(...interface{}) Expectation
type Controller interface {
	ExpectCall(
		o MockObject,
		methodName string,
		fileName string,
		lineNumber int) PartialExpecation
	Finish()
	HandleMethodCall(
		o MockObject,
		methodName string,
		fileName string,
		lineNumber int,
		args []interface{}) []interface{}
}
type methodMap map[string][]*InternalExpectation
type objectMap map[uintptr]methodMap
func NewController(reporter ErrorReporter) Controller {
	return &controllerImpl{reporter, sync.RWMutex{}, objectMap{}}
}
type controllerImpl struct {
	reporter ErrorReporter
	mutex                sync.RWMutex
	expectationsByObject objectMap  
}
func (c *controllerImpl) getExpectationsLocked(
	o MockObject,
	methodName string) []*InternalExpectation {
	id := o.Oglemock_Id()
	expectationsByMethod, ok := c.expectationsByObject[id]
	if !ok {
		expectationsByMethod = methodMap{}
		c.expectationsByObject[id] = expectationsByMethod
	}
	result, ok := expectationsByMethod[methodName]
	if !ok {
		return []*InternalExpectation{}
	}
	return result
}
func (c *controllerImpl) addExpectationLocked(
	o MockObject,
	methodName string,
	exp *InternalExpectation) {
	existing := c.getExpectationsLocked(o, methodName)
	id := o.Oglemock_Id()
	c.expectationsByObject[id][methodName] = append(existing, exp)
}
func (c *controllerImpl) ExpectCall(
	o MockObject,
	methodName string,
	fileName string,
	lineNumber int) PartialExpecation {
	ov := reflect.ValueOf(o)
	method := ov.MethodByName(methodName)
	if method.Kind() == reflect.Invalid {
		c.reporter.ReportFatalError(
			fileName,
			lineNumber,
			errors.New("Unknown method: "+methodName))
		return nil
	}
	partialAlreadyCalled := false  
	return func(args ...interface{}) Expectation {
		c.mutex.Lock()
		defer c.mutex.Unlock()
		if partialAlreadyCalled {
			c.reporter.ReportFatalError(
				fileName,
				lineNumber,
				errors.New("Partial expectation called more than once."))
			return nil
		}
		partialAlreadyCalled = true
		if len(args) != method.Type().NumIn() {
			c.reporter.ReportFatalError(
				fileName,
				lineNumber,
				errors.New(
					fmt.Sprintf(
						"Expectation for %s given wrong number of arguments: "+
							"expected %d, got %d.",
						methodName,
						method.Type().NumIn(),
						len(args))))
			return nil
		}
		exp := InternalNewExpectation(
			c.reporter,
			method.Type(),
			args,
			fileName,
			lineNumber)
		c.addExpectationLocked(o, methodName, exp)
		return exp
	}
}
func (c *controllerImpl) Finish() {
	c.mutex.Lock()
	defer c.mutex.Unlock()
	for _, expectationsByMethod := range c.expectationsByObject {
		for methodName, expectations := range expectationsByMethod {
			for _, exp := range expectations {
				exp.mutex.Lock()
				defer exp.mutex.Unlock()
				minCardinality, _ := computeCardinalityLocked(exp)
				if exp.NumMatches < minCardinality {
					c.reporter.ReportError(
						exp.FileName,
						exp.LineNumber,
						errors.New(
							fmt.Sprintf(
								"Unsatisfied expectation; expected %s to be called "+
									"at least %d times; called %d times.",
								methodName,
								minCardinality,
								exp.NumMatches)))
				}
			}
		}
	}
}