Commit 9957059d authored by Simon Welsh's avatar Simon Welsh

Initial commit

parents
# Object files and binaries from go.
*.[568]
# Library files.
*.a
# Any file prefixed by an underscore.
*/_*
# Vim temporary files.
.*.swp
# The mockgen binary.
mockgen/mockgen
# A binary produced by gotest.
#gomock/[568]\.out
# This is the official list of GoMock authors for copyright purposes.
# This file is distinct from the CONTRIBUTORS files.
# See the latter for an explanation.
# Names should be added to this file as
# Name or Organization <email address>
# The email address is not required for organizations.
# Please keep the list sorted.
Alex Reece <awreece@gmail.com>
Google Inc.
# This is the official list of people who can contribute (and typically
# have contributed) code to the gomock repository.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# The submission process automatically checks to make sure
# that people submitting code are listed in this file (by email address).
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# http://code.google.com/legal/individual-cla-v1.0.html
# http://code.google.com/legal/corporate-cla-v1.0.html
#
# The agreement for individuals can be filled out on the web.
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
# Names should be added to this file like so:
# Name <email address>
#
# An entry with two email addresses specifies that the
# first address should be used in the submit logs and
# that the second address should be recognized as the
# same person when interacting with Rietveld.
# Please keep the list sorted.
Aaron Jacobs <jacobsa@google.com> <aaronjjacobs@gmail.com>
Alex Reece <awreece@gmail.com>
David Symonds <dsymonds@golang.org>
Ryan Barrett <ryanb@google.com>
This diff is collapsed.
GoMock is a mocking framework for the [Go programming language][golang]. It
integrates well with Go's built-in `testing` package, but can be used in other
contexts too.
Installation
------------
Once you have [installed Go][golang-install], run these commands
to install the `gomock` package and the `mockgen` tool:
go install code.google.com/p/gomock/gomock
go install code.google.com/p/gomock/mockgen
Documentation
-------------
After installing, you can use `go doc` to get documentation:
go doc code.google.com/p/gomock/gomock
Alternatively, there is an online reference for the package hosted on GoPkgDoc
[here][gomock-ref].
Running mockgen
---------------
The `mockgen` command is used to generate source code for a mock
class given a Go source file containing interfaces to be mocked.
It supports the following flags:
* `-source`: The file containing interfaces to be mocked. You must
supply this flag.
* `-destination`: A file to which to write the resulting source code. If you
don't set this, the code is printed to standard output.
* `-package`: The package to use for the resulting mock class
source code. If you don't set this, the package name is `mock_` concatenated
with the package of the input file.
* `-imports`: A list of explicit imports that should be used in the resulting
source code, specified as a comma-separated list of elements of the form
`foo=bar/baz`, where `bar/baz` is the package being imported and `foo` is
the identifier to use for the package in the generated source code.
* `-aux_files`: A list of additional files that should be consulted to
resolve e.g. embedded interfaces defined in a different file. This is
specified as a comma-separated list of elements of the form
`foo=bar/baz.go`, where `bar/baz.go` is the source file and `foo` is the
package name of that file used by the -source file.
For an example of the use of `mockgen`, see the `sample/` directory. In simple
cases, you will need only the `-source` flag.
TODO: Brief overview of how to create mock objects and set up expectations, and
an example.
[golang]: http://golang.org/
[golang-install]: http://golang.org/doc/install.html#releases
[gomock-ref]: http://gopkgdoc.appspot.com/pkg/code.google.com/p/gomock/gomock
// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gomock
import (
"fmt"
"reflect"
"strings"
)
// Call represents an expected call to a mock.
type Call struct {
t TestReporter // for triggering test failures on invalid call setup
receiver interface{} // the receiver of the method call
method string // the name of the method
args []Matcher // the args
rets []interface{} // the return values (if any)
preReqs []*Call // prerequisite calls
// Expectations
minCalls, maxCalls int
numCalls int // actual number made
// Actions
doFunc reflect.Value
setArgs map[int]reflect.Value
}
func (c *Call) AnyTimes() *Call {
c.minCalls, c.maxCalls = 0, 1e8 // close enough to infinity
return c
}
// Do declares the action to run when the call is matched.
// It takes an interface{} argument to support n-arity functions.
func (c *Call) Do(f interface{}) *Call {
// TODO: Check arity and types here, rather than dying badly elsewhere.
c.doFunc = reflect.ValueOf(f)
return c
}
func (c *Call) Return(rets ...interface{}) *Call {
mt := c.methodType()
if len(rets) != mt.NumOut() {
c.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d",
c.receiver, c.method, len(rets), mt.NumOut())
}
for i, ret := range rets {
if got, want := reflect.TypeOf(ret), mt.Out(i); got == want {
// Identical types; nothing to do.
} else if got == nil {
// Nil needs special handling.
switch want.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
// ok
default:
c.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable",
i, c.receiver, c.method, want)
}
} else if got.AssignableTo(want) {
// Assignable type relation. Make the assignment now so that the generated code
// can return the values with a type assertion.
v := reflect.New(want).Elem()
v.Set(reflect.ValueOf(ret))
rets[i] = v.Interface()
} else {
c.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v",
i, c.receiver, c.method, got, want)
}
}
c.rets = rets
return c
}
func (c *Call) Times(n int) *Call {
c.minCalls, c.maxCalls = n, n
return c
}
// SetArg declares an action that will set the nth argument's value,
// indirected through a pointer.
func (c *Call) SetArg(n int, value interface{}) *Call {
if c.setArgs == nil {
c.setArgs = make(map[int]reflect.Value)
}
mt := c.methodType()
// TODO: This will break on variadic methods.
// We will need to check those at invocation time.
if n < 0 || n >= mt.NumIn() {
c.t.Fatalf("SetArg(%d, ...) called for a method with %d args", n, mt.NumIn())
}
// Permit setting argument through an interface.
// In the interface case, we don't (nay, can't) check the type here.
at := mt.In(n)
switch at.Kind() {
case reflect.Ptr:
dt := at.Elem()
if vt := reflect.TypeOf(value); !vt.AssignableTo(dt) {
c.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v", n, vt, dt)
}
case reflect.Interface:
// nothing to do
default:
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface type %v", n, at)
}
c.setArgs[n] = reflect.ValueOf(value)
return c
}
// isPreReq returns true if other is a direct or indirect prerequisite to c.
func (c *Call) isPreReq(other *Call) bool {
for _, preReq := range c.preReqs {
if other == preReq || preReq.isPreReq(other) {
return true
}
}
return false
}
// After declares that the call may only match after preReq has been exhausted.
func (c *Call) After(preReq *Call) *Call {
if preReq.isPreReq(c) {
msg := fmt.Sprintf(
"Loop in call order: %v is a prerequisite to %v (possibly indirectly).",
c, preReq,
)
panic(msg)
}
c.preReqs = append(c.preReqs, preReq)
return c
}
// Returns true iff the minimum number of calls have been made.
func (c *Call) satisfied() bool {
return c.numCalls >= c.minCalls
}
// Returns true iff the maximum number of calls have been made.
func (c *Call) exhausted() bool {
return c.numCalls >= c.maxCalls
}
func (c *Call) String() string {
args := make([]string, len(c.args))
for i, arg := range c.args {
args[i] = arg.String()
}
arguments := strings.Join(args, ", ")
return fmt.Sprintf("%T.%v(%s)", c.receiver, c.method, arguments)
}
// Tests if the given call matches the expected call.
func (c *Call) matches(args []interface{}) bool {
if len(args) != len(c.args) {
return false
}
for i, m := range c.args {
if !m.Matches(args[i]) {
return false
}
}
// Check that all prerequisite calls have been satisfied.
for _, preReqCall := range c.preReqs {
if !preReqCall.satisfied() {
return false
}
}
return true
}
// dropPrereqs tells the expected Call to not re-check prerequite calls any
// longer, and to return its current set.
func (c *Call) dropPrereqs() (preReqs []*Call) {
preReqs = c.preReqs
c.preReqs = nil
return
}
func (c *Call) call(args []interface{}) (rets []interface{}, action func()) {
c.numCalls++
// Actions
if c.doFunc.IsValid() {
doArgs := make([]reflect.Value, len(args))
ft := c.doFunc.Type()
for i := 0; i < ft.NumIn(); i++ {
doArgs[i] = reflect.ValueOf(args[i])
}
action = func() { c.doFunc.Call(doArgs) }
}
for n, v := range c.setArgs {
reflect.ValueOf(args[n]).Elem().Set(v)
}
rets = c.rets
if rets == nil {
// Synthesize the zero value for each of the return args' types.
mt := c.methodType()
rets = make([]interface{}, mt.NumOut())
for i := 0; i < mt.NumOut(); i++ {
rets[i] = reflect.Zero(mt.Out(i)).Interface()
}
}
return
}
func (c *Call) methodType() reflect.Type {
recv := reflect.ValueOf(c.receiver)
for i := 0; i < recv.Type().NumMethod(); i++ {
if recv.Type().Method(i).Name == c.method {
return recv.Method(i).Type()
}
}
panic(fmt.Sprintf("gomock: failed finding method %s on %T", c.method, c.receiver))
}
// InOrder declares that the given calls should occur in order.
func InOrder(calls ...*Call) {
for i := 1; i < len(calls); i++ {
calls[i].After(calls[i-1])
}
}
// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gomock
// callSet represents a set of expected calls, indexed by receiver and method
// name.
type callSet map[interface{}]map[string][]*Call
// Add adds a new expected call.
func (cs callSet) Add(call *Call) {
methodMap, ok := cs[call.receiver]
if !ok {
methodMap = make(map[string][]*Call)
cs[call.receiver] = methodMap
}
methodMap[call.method] = append(methodMap[call.method], call)
}
// Remove removes an expected call.
func (cs callSet) Remove(call *Call) {
methodMap, ok := cs[call.receiver]
if !ok {
return
}
sl := methodMap[call.method]
for i, c := range sl {
if c == call {
// quick removal; we don't need to maintain call order
if len(sl) > 1 {
sl[i] = sl[len(sl)-1]
}
methodMap[call.method] = sl[:len(sl)-1]
break
}
}
}
// FindMatch searches for a matching call. Returns nil if no call matched.
func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) *Call {
methodMap, ok := cs[receiver]
if !ok {
return nil
}
calls, ok := methodMap[method]
if !ok {
return nil
}
// Search through the unordered set of calls expected on a method on a
// receiver.
for _, call := range calls {
if call.matches(args) {
return call
}
}
return nil
}
// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// GoMock - a mock framework for Go.
//
// Standard usage:
// (1) Define an interface that you wish to mock.
// type MyInterface interface {
// SomeMethod(x int64, y string)
// }
// (2) Use mockgen to generate a mock from the interface.
// (3) Use the mock in a test:
// func TestMyThing(t *testing.T) {
// mockCtrl := gomock.NewController(t)
// defer mockCtrl.Finish()
//
// mockObj := something.NewMockMyInterface(mockCtrl)
// mockObj.EXPECT().SomeMethod(4, "blah")
// // pass mockObj to a real object and play with it.
// }
//
// By default, expected calls are not enforced to run in any particular order.
// Call order dependency can be enforced by use of InOrder and/or Call.After.
// Call.After can create more varied call order dependencies, but InOrder is
// often more convenient.
//
// The following examples create equivalent call order dependencies.
//
// Example of using Call.After to chain expected call order:
//
// firstCall := mockObj.EXPECT().SomeMethod(1, "first")
// secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
// mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
//
// Example of using InOrder to declare expected call order:
//
// gomock.InOrder(
// mockObj.EXPECT().SomeMethod(1, "first"),
// mockObj.EXPECT().SomeMethod(2, "second"),
// mockObj.EXPECT().SomeMethod(3, "third"),
// )
//
// TODO:
// - Handle different argument/return types (e.g. ..., chan, map, interface).
package gomock
import "sync"
// A TestReporter is something that can be used to report test failures.
// It is satisfied by the standard library's *testing.T.
type TestReporter interface {
Errorf(format string, args ...interface{})
Fatalf(format string, args ...interface{})
}
// A Controller represents the top-level control of a mock ecosystem.
// It defines the scope and lifetime of mock objects, as well as their expectations.
// It is safe to call Controller's methods from multiple goroutines.
type Controller struct {
mu sync.Mutex
t TestReporter
expectedCalls callSet
}
func NewController(t TestReporter) *Controller {
return &Controller{
t: t,
expectedCalls: make(callSet),
}
}
func (ctrl *Controller) RecordCall(receiver interface{}, method string, args ...interface{}) *Call {
// TODO: check arity, types.
margs := make([]Matcher, len(args))
for i, arg := range args {
if m, ok := arg.(Matcher); ok {
margs[i] = m
} else {
margs[i] = Eq(arg)
}
}
ctrl.mu.Lock()
defer ctrl.mu.Unlock()
call := &Call{t: ctrl.t, receiver: receiver, method: method, args: margs, minCalls: 1, maxCalls: 1}
ctrl.expectedCalls.Add(call)
return call
}
func (ctrl *Controller) Call(receiver interface{}, method string, args ...interface{}) []interface{} {
ctrl.mu.Lock()
defer ctrl.mu.Unlock()
expected := ctrl.expectedCalls.FindMatch(receiver, method, args)
if expected == nil {
ctrl.t.Fatalf("no matching expected call: %T.%v(%v)", receiver, method, args)
}
// Two things happen here:
// * the matching call no longer needs to check prerequite calls,
// * and the prerequite calls are no longer expected, so remove them.
preReqCalls := expected.dropPrereqs()
for _, preReqCall := range preReqCalls {
ctrl.expectedCalls.Remove(preReqCall)
}
rets, action := expected.call(args)
if expected.exhausted() {
ctrl.expectedCalls.Remove(expected)
}
// Don't hold the lock while doing the call's action (if any)
// so that actions may execute concurrently.
// We use the deferred Unlock to capture any panics that happen above;
// here we add a deferred Lock to balance it.
ctrl.mu.Unlock()
defer ctrl.mu.Lock()
if action != nil {
action()
}
return rets
}
func (ctrl *Controller) Finish() {
ctrl.mu.Lock()
defer ctrl.mu.Unlock()
// If we're currently panicking, probably because this is a deferred call,
// pass through the panic.
if err := recover(); err != nil {
panic(err)
}
// Check that all remaining expected calls are satisfied.
failures := false
for _, methodMap := range ctrl.expectedCalls {
for _, calls := range methodMap {
for _, call := range calls {
if !call.satisfied() {
ctrl.t.Errorf("missing call(s) to %v", call)
failures = true
}
}
}
}
if failures {
ctrl.t.Fatalf("aborting test due to missing call(s)")
}
}
// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gomock_test
import (
"fmt"
"reflect"
"testing"
"code.google.com/p/gomock/gomock"
)
type ErrorReporter struct {
t *testing.T
log []string
failed bool
fatalToken struct{}
}
func NewErrorReporter(t *testing.T) *ErrorReporter {
return &ErrorReporter{t: t}
}
func (e *ErrorReporter) reportLog() {
for _, entry := range e.log {
e.t.Log(entry)
}
}
func (e *ErrorReporter) assertPass(msg string) {
if e.failed {
e.t.Errorf("Expected pass, but got failure(s): %s", msg)
e.reportLog()
}
}
func (e *ErrorReporter) assertFail(msg string) {
if !e.failed {
e.t.Error("Expected failure, but got pass: %s", msg)
}
}
// Use to check that code triggers a fatal test failure.
func (e *ErrorReporter) assertFatal(fn func()) {
defer func() {
err := recover()
if err == nil {
var actual string
if e.failed {
actual = "non-fatal failure"
} else {
actual = "pass"
}
e.t.Error("Expected fatal failure, but got a", actual)
} else if token, ok := err.(*struct{}); ok && token == &e.fatalToken {
// This is okay - the panic is from Fatalf().
return
} else {
// Some other panic.
panic(err)
}
}()
fn()