summaryrefslogtreecommitdiff
path: root/vendor/github.com/golang/mock/gomock/controller_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/golang/mock/gomock/controller_test.go')
-rw-r--r--vendor/github.com/golang/mock/gomock/controller_test.go475
1 files changed, 475 insertions, 0 deletions
diff --git a/vendor/github.com/golang/mock/gomock/controller_test.go b/vendor/github.com/golang/mock/gomock/controller_test.go
new file mode 100644
index 0000000..57f7957
--- /dev/null
+++ b/vendor/github.com/golang/mock/gomock/controller_test.go
@@ -0,0 +1,475 @@
+// 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"
+
+ "github.com/golang/mock/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.Errorf("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()
+}
+
+// recoverUnexpectedFatal can be used as a deferred call in test cases to
+// recover from and display a call to ErrorReporter.Fatalf().
+func (e *ErrorReporter) recoverUnexpectedFatal() {
+ err := recover()
+ if err == nil {
+ // No panic.
+ } else if token, ok := err.(*struct{}); ok && token == &e.fatalToken {
+ // Unexpected fatal error happened.
+ e.t.Error("Got unexpected fatal error(s). All errors up to this point:")
+ e.reportLog()
+ return
+ } else {
+ // Some other panic.
+ panic(err)
+ }
+}
+
+func (e *ErrorReporter) Logf(format string, args ...interface{}) {
+ e.log = append(e.log, fmt.Sprintf(format, args...))
+}
+
+func (e *ErrorReporter) Errorf(format string, args ...interface{}) {
+ e.Logf(format, args...)
+ e.failed = true
+}
+
+func (e *ErrorReporter) Fatalf(format string, args ...interface{}) {
+ e.Logf(format, args...)
+ e.failed = true
+ panic(&e.fatalToken)
+}
+
+// A type purely for use as a receiver in testing the Controller.
+type Subject struct{}
+
+func (s *Subject) FooMethod(arg string) int {
+ return 0
+}
+
+func (s *Subject) BarMethod(arg string) int {
+ return 0
+}
+
+func assertEqual(t *testing.T, expected interface{}, actual interface{}) {
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Expected %+v, but got %+v", expected, actual)
+ }
+}
+
+func createFixtures(t *testing.T) (reporter *ErrorReporter, ctrl *gomock.Controller) {
+ // reporter acts as a testing.T-like object that we pass to the
+ // Controller. We use it to test that the mock considered tests
+ // successful or failed.
+ reporter = NewErrorReporter(t)
+ ctrl = gomock.NewController(reporter)
+ return
+}
+
+func TestNoCalls(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ ctrl.Finish()
+ reporter.assertPass("No calls expected or made.")
+}
+
+func TestExpectedMethodCall(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ subject := new(Subject)
+
+ ctrl.RecordCall(subject, "FooMethod", "argument")
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Finish()
+
+ reporter.assertPass("Expected method call made.")
+}
+
+func TestUnexpectedMethodCall(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ subject := new(Subject)
+
+ reporter.assertFatal(func() {
+ ctrl.Call(subject, "FooMethod", "argument")
+ })
+
+ ctrl.Finish()
+}
+
+func TestRepeatedCall(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ subject := new(Subject)
+
+ ctrl.RecordCall(subject, "FooMethod", "argument").Times(3)
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Call(subject, "FooMethod", "argument")
+ reporter.assertPass("After expected repeated method calls.")
+ reporter.assertFatal(func() {
+ ctrl.Call(subject, "FooMethod", "argument")
+ })
+ ctrl.Finish()
+ reporter.assertFail("After calling one too many times.")
+}
+
+func TestUnexpectedArgCount(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ defer reporter.recoverUnexpectedFatal()
+ subject := new(Subject)
+
+ ctrl.RecordCall(subject, "FooMethod", "argument")
+ reporter.assertFatal(func() {
+ // This call is made with the wrong number of arguments...
+ ctrl.Call(subject, "FooMethod", "argument", "extra_argument")
+ })
+ reporter.assertFatal(func() {
+ // ... so is this.
+ ctrl.Call(subject, "FooMethod")
+ })
+ reporter.assertFatal(func() {
+ // The expected call wasn't made.
+ ctrl.Finish()
+ })
+}
+
+func TestAnyTimes(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ subject := new(Subject)
+
+ ctrl.RecordCall(subject, "FooMethod", "argument").AnyTimes()
+ for i := 0; i < 100; i++ {
+ ctrl.Call(subject, "FooMethod", "argument")
+ }
+ reporter.assertPass("After 100 method calls.")
+ ctrl.Finish()
+}
+
+func TestMinTimes1(t *testing.T) {
+ // It fails if there are no calls
+ reporter, ctrl := createFixtures(t)
+ subject := new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
+ reporter.assertFatal(func() {
+ ctrl.Finish()
+ })
+
+ // It succeeds if there is one call
+ reporter, ctrl = createFixtures(t)
+ subject = new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Finish()
+
+ // It succeeds if there are many calls
+ reporter, ctrl = createFixtures(t)
+ subject = new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
+ for i := 0; i < 100; i++ {
+ ctrl.Call(subject, "FooMethod", "argument")
+ }
+ ctrl.Finish()
+}
+
+func TestMaxTimes1(t *testing.T) {
+ // It succeeds if there are no calls
+ _, ctrl := createFixtures(t)
+ subject := new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
+ ctrl.Finish()
+
+ // It succeeds if there is one call
+ _, ctrl = createFixtures(t)
+ subject = new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Finish()
+
+ //It fails if there are more
+ reporter, ctrl := createFixtures(t)
+ subject = new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1)
+ ctrl.Call(subject, "FooMethod", "argument")
+ reporter.assertFatal(func() {
+ ctrl.Call(subject, "FooMethod", "argument")
+ })
+ ctrl.Finish()
+}
+
+func TestMinMaxTimes(t *testing.T) {
+ // It fails if there are less calls than specified
+ reporter, ctrl := createFixtures(t)
+ subject := new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(2).MaxTimes(2)
+ ctrl.Call(subject, "FooMethod", "argument")
+ reporter.assertFatal(func() {
+ ctrl.Finish()
+ })
+
+ // It fails if there are more calls than specified
+ reporter, ctrl = createFixtures(t)
+ subject = new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(2).MaxTimes(2)
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Call(subject, "FooMethod", "argument")
+ reporter.assertFatal(func() {
+ ctrl.Call(subject, "FooMethod", "argument")
+ })
+
+ // It succeeds if there is just the right number of calls
+ reporter, ctrl = createFixtures(t)
+ subject = new(Subject)
+ ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(2).MinTimes(2)
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Call(subject, "FooMethod", "argument")
+ ctrl.Finish()
+}
+
+func TestDo(t *testing.T) {
+ _, ctrl := createFixtures(t)
+ subject := new(Subject)
+
+ doCalled := false
+ var argument string
+ ctrl.RecordCall(subject, "FooMethod", "argument").Do(
+ func(arg string) {
+ doCalled = true
+ argument = arg
+ })
+ if doCalled {
+ t.Error("Do() callback called too early.")
+ }
+
+ ctrl.Call(subject, "FooMethod", "argument")
+
+ if !doCalled {
+ t.Error("Do() callback not called.")
+ }
+ if "argument" != argument {
+ t.Error("Do callback received wrong argument.")
+ }
+
+ ctrl.Finish()
+}
+
+func TestReturn(t *testing.T) {
+ _, ctrl := createFixtures(t)
+ subject := new(Subject)
+
+ // Unspecified return should produce "zero" result.
+ ctrl.RecordCall(subject, "FooMethod", "zero")
+ ctrl.RecordCall(subject, "FooMethod", "five").Return(5)
+
+ assertEqual(
+ t,
+ []interface{}{0},
+ ctrl.Call(subject, "FooMethod", "zero"))
+
+ assertEqual(
+ t,
+ []interface{}{5},
+ ctrl.Call(subject, "FooMethod", "five"))
+ ctrl.Finish()
+}
+
+func TestUnorderedCalls(t *testing.T) {
+ reporter, ctrl := createFixtures(t)
+ defer reporter.recoverUnexpectedFatal()
+ subjectTwo := new(Subject)
+ subjectOne := new(Subject)
+
+ ctrl.RecordCall(subjectOne, "FooMethod", "1")
+ ctrl.RecordCall(subjectOne, "BarMethod", "2")
+ ctrl.RecordCall(subjectTwo, "FooMethod", "3")
+ ctrl.RecordCall(subjectTwo, "BarMethod", "4")
+
+ // Make the calls in a different order, which should be fine.
+ ctrl.Call(subjectOne, "BarMethod", "2")
+ ctrl.Call(subjectTwo, "FooMethod", "3")
+ ctrl.Call(subjectTwo, "BarMethod", "4")
+ ctrl.Call(subjectOne, "FooMethod", "1")
+
+ reporter.assertPass("After making all calls in different order")
+
+ ctrl.Finish()
+
+ reporter.assertPass("After finish")
+}
+
+func commonTestOrderedCalls(t *testing.T) (reporter *ErrorReporter, ctrl *gomock.Controller, subjectOne, subjectTwo *Subject) {
+ reporter, ctrl = createFixtures(t)
+
+ subjectOne = new(Subject)
+ subjectTwo = new(Subject)
+
+ gomock.InOrder(
+ ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
+ ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
+ ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
+ )
+
+ return
+}
+
+func TestOrderedCallsCorrect(t *testing.T) {
+ reporter, ctrl, subjectOne, subjectTwo := commonTestOrderedCalls(t)
+
+ ctrl.Call(subjectOne, "FooMethod", "1")
+ ctrl.Call(subjectTwo, "FooMethod", "2")
+ ctrl.Call(subjectTwo, "BarMethod", "3")
+
+ ctrl.Finish()
+
+ reporter.assertPass("After finish")
+}
+
+func TestOrderedCallsInCorrect(t *testing.T) {
+ reporter, ctrl, subjectOne, subjectTwo := commonTestOrderedCalls(t)
+
+ ctrl.Call(subjectOne, "FooMethod", "1")
+ reporter.assertFatal(func() {
+ ctrl.Call(subjectTwo, "BarMethod", "3")
+ })
+}
+
+// Test that calls that are prerequites to other calls but have maxCalls >
+// minCalls are removed from the expected call set.
+func TestOrderedCallsWithPreReqMaxUnbounded(t *testing.T) {
+ reporter, ctrl, subjectOne, subjectTwo := commonTestOrderedCalls(t)
+
+ // Initially we should be able to call FooMethod("1") as many times as we
+ // want.
+ ctrl.Call(subjectOne, "FooMethod", "1")
+ ctrl.Call(subjectOne, "FooMethod", "1")
+
+ // But calling something that has it as a prerequite should remove it from
+ // the expected call set. This allows tests to ensure that FooMethod("1") is
+ // *not* called after FooMethod("2").
+ ctrl.Call(subjectTwo, "FooMethod", "2")
+
+ // Therefore this call should fail:
+ reporter.assertFatal(func() {
+ ctrl.Call(subjectOne, "FooMethod", "1")
+ })
+}
+
+func TestCallAfterLoopPanic(t *testing.T) {
+ _, ctrl := createFixtures(t)
+
+ subject := new(Subject)
+
+ firstCall := ctrl.RecordCall(subject, "FooMethod", "1")
+ secondCall := ctrl.RecordCall(subject, "FooMethod", "2")
+ thirdCall := ctrl.RecordCall(subject, "FooMethod", "3")
+
+ gomock.InOrder(firstCall, secondCall, thirdCall)
+
+ defer func() {
+ err := recover()
+ if err == nil {
+ t.Error("Call.After creation of dependency loop did not panic.")
+ }
+ }()
+
+ // This should panic due to dependency loop.
+ firstCall.After(thirdCall)
+}
+
+func TestPanicOverridesExpectationChecks(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ reporter := NewErrorReporter(t)
+
+ reporter.assertFatal(func() {
+ ctrl.RecordCall(new(Subject), "FooMethod", "1")
+ defer ctrl.Finish()
+ reporter.Fatalf("Intentional panic")
+ })
+}
+
+func TestSetArgWithBadType(t *testing.T) {
+ rep, ctrl := createFixtures(t)
+ defer ctrl.Finish()
+
+ s := new(Subject)
+ // This should catch a type error:
+ rep.assertFatal(func() {
+ ctrl.RecordCall(s, "FooMethod", "1").SetArg(0, "blah")
+ })
+ ctrl.Call(s, "FooMethod", "1")
+}
+
+func TestTimes0(t *testing.T) {
+ rep, ctrl := createFixtures(t)
+ defer ctrl.Finish()
+
+ s := new(Subject)
+ ctrl.RecordCall(s, "FooMethod", "arg").Times(0)
+ rep.assertFatal(func() {
+ ctrl.Call(s, "FooMethod", "arg")
+ })
+}