1// Copyright 2020 Google LLC
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// +build go1.14
16
17package gomock_test
18
19import (
20	"testing"
21
22	"github.com/golang/mock/gomock"
23)
24
25func (e *ErrorReporter) Cleanup(f func()) {
26	e.t.Helper()
27	e.t.Cleanup(f)
28}
29
30func TestMultipleDefers(t *testing.T) {
31	reporter := NewErrorReporter(t)
32	reporter.Cleanup(func() {
33		reporter.assertPass("No errors for multiple calls to Finish")
34	})
35	ctrl := gomock.NewController(reporter)
36	ctrl.Finish()
37}
38
39// Equivalent to the TestNoRecordedCallsForAReceiver, but without explicitly
40// calling Finish.
41func TestDeferNotNeededFail(t *testing.T) {
42	reporter := NewErrorReporter(t)
43	subject := new(Subject)
44	var ctrl *gomock.Controller
45	reporter.Cleanup(func() {
46		reporter.assertFatal(func() {
47			ctrl.Call(subject, "NotRecordedMethod", "argument")
48		}, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver")
49	})
50	ctrl = gomock.NewController(reporter)
51}
52
53func TestDeferNotNeededPass(t *testing.T) {
54	reporter := NewErrorReporter(t)
55	subject := new(Subject)
56	var ctrl *gomock.Controller
57	reporter.Cleanup(func() {
58		reporter.assertPass("Expected method call made.")
59	})
60	ctrl = gomock.NewController(reporter)
61	ctrl.RecordCall(subject, "FooMethod", "argument")
62	ctrl.Call(subject, "FooMethod", "argument")
63}
64
65func TestOrderedCallsInCorrect(t *testing.T) {
66	reporter := NewErrorReporter(t)
67	subjectOne := new(Subject)
68	subjectTwo := new(Subject)
69	var ctrl *gomock.Controller
70	reporter.Cleanup(func() {
71		reporter.assertFatal(func() {
72			gomock.InOrder(
73				ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
74				ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
75				ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
76			)
77			ctrl.Call(subjectOne, "FooMethod", "1")
78			// FooMethod(2) should be called before BarMethod(3)
79			ctrl.Call(subjectTwo, "BarMethod", "3")
80		}, "Unexpected call to", "Subject.BarMethod([3])", "doesn't have a prerequisite call satisfied")
81	})
82	ctrl = gomock.NewController(reporter)
83}
84
85// Test that calls that are prerequisites to other calls but have maxCalls >
86// minCalls are removed from the expected call set.
87func TestOrderedCallsWithPreReqMaxUnbounded(t *testing.T) {
88	reporter := NewErrorReporter(t)
89	subjectOne := new(Subject)
90	subjectTwo := new(Subject)
91	var ctrl *gomock.Controller
92	reporter.Cleanup(func() {
93		reporter.assertFatal(func() {
94			// Initially we should be able to call FooMethod("1") as many times as we
95			// want.
96			ctrl.Call(subjectOne, "FooMethod", "1")
97			ctrl.Call(subjectOne, "FooMethod", "1")
98
99			// But calling something that has it as a prerequite should remove it from
100			// the expected call set. This allows tests to ensure that FooMethod("1") is
101			// *not* called after FooMethod("2").
102			ctrl.Call(subjectTwo, "FooMethod", "2")
103
104			ctrl.Call(subjectOne, "FooMethod", "1")
105		})
106	})
107	ctrl = gomock.NewController(reporter)
108}
109
110func TestCallAfterLoopPanic(t *testing.T) {
111	reporter := NewErrorReporter(t)
112	subject := new(Subject)
113	var ctrl *gomock.Controller
114	reporter.Cleanup(func() {
115		firstCall := ctrl.RecordCall(subject, "FooMethod", "1")
116		secondCall := ctrl.RecordCall(subject, "FooMethod", "2")
117		thirdCall := ctrl.RecordCall(subject, "FooMethod", "3")
118
119		gomock.InOrder(firstCall, secondCall, thirdCall)
120
121		defer func() {
122			err := recover()
123			if err == nil {
124				t.Error("Call.After creation of dependency loop did not panic.")
125			}
126		}()
127
128		// This should panic due to dependency loop.
129		firstCall.After(thirdCall)
130	})
131	ctrl = gomock.NewController(reporter)
132}
133