<commit_before>// Copyright 2015 <NAME>
//
// 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 pegomock

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/petergtz/pegomock/internal/verify"
)

var GlobalFailHandler FailHandler

func RegisterMockFailHandler(handler FailHandler) {
	GlobalFailHandler = handler
}
func RegisterMockTestingT(t *testing.T) {
	RegisterMockFailHandler(BuildTestingTGomegaFailHandler(t))
}

var lastInvocation *invocation
var globalArgMatchers Matchers

func RegisterMatcher(matcher Matcher) {
	globalArgMatchers.append(matcher)
}

type invocation struct {
	genericMock *GenericMock
	MethodName  string
	Params      []Param
	ReturnTypes []reflect.Type
}

type GenericMock struct {
	mockedMethods map[string]*mockedMethod
}

func (genericMock *GenericMock) Invoke(methodName string, params []Param, returnTypes []reflect.Type) ReturnValues {
	lastInvocation = &invocation{
		genericMock: genericMock,
		MethodName:  methodName,
		Params:      params,
		ReturnTypes: returnTypes,
	}
	return genericMock.getOrCreateMockedMethod(methodName).Invoke(params)
}

func (genericMock *GenericMock) stub(methodName string, paramMatchers []Matcher, returnValues ReturnValues) {
	genericMock.stubWithCallback(methodName, paramMatchers, func([]Param) ReturnValues { return returnValues })
}

func (genericMock *GenericMock) stubWithCallback(methodName string, paramMatchers []Matcher, callback func([]Param) ReturnValues) {
	genericMock.getOrCreateMockedMethod(methodName).stub(paramMatchers, callback)
}

func (genericMock *GenericMock) getOrCreateMockedMethod(methodName string) *mockedMethod {
	if _, ok := genericMock.mockedMethods[methodName]; !ok {
		genericMock.mockedMethods[methodName] = &mockedMethod{name: methodName}
	}
	return genericMock.mockedMethods[methodName]
}

func (genericMock *GenericMock) reset(methodName string, paramMatchers []Matcher) {
	genericMock.getOrCreateMockedMethod(methodName).reset(paramMatchers)
}

func (genericMock *GenericMock) Verify(
	inOrderContext *InOrderContext,
	invocationCountMatcher Matcher,
	methodName string,
	params []Param) []MethodInvocation {
	if GlobalFailHandler == nil {
		panic("No GlobalFailHandler set. Please use either RegisterMockFailHandler or RegisterMockTestingT to set a fail handler.")
	}
	defer func() { globalArgMatchers = nil }() // We don't want a panic somewhere during verification screw our global argMatchers

	if len(globalArgMatchers) != 0 {
		verifyArgMatcherUse(globalArgMatchers, params)
	}

	methodInvocations := genericMock.methodInvocations(methodName, params, globalArgMatchers)
	if inOrderContext != nil {
		for _, methodInvocation := range methodInvocations {
			if methodInvocation.orderingInvocationNumber <= inOrderContext.invocationCounter {
				GlobalFailHandler(fmt.Sprintf("Expected function call \"%v\" with params %v before function call \"%v\" with params %v",
					methodName, params, inOrderContext.lastInvokedMethodName, inOrderContext.lastInvokedMethodParams))
			}
			inOrderContext.invocationCounter = methodInvocation.orderingInvocationNumber
			inOrderContext.lastInvokedMethodName = methodName
			inOrderContext.lastInvokedMethodParams = params
		}
	}
	if !invocationCountMatcher.Matches(len(methodInvocations)) {
		if len(globalArgMatchers) == 0 {
			GlobalFailHandler(fmt.Sprintf(
				"Mock invocation count for method \"%s\" with params %v does not match expectation.\n\n\t%v",
				methodName, params, invocationCountMatcher.FailureMessage()))
		} else {
			GlobalFailHandler(fmt.Sprintf(
				"Mock invocation count for method \"%s\" with params %v does not match expectation.\n\n\t%v",
				methodName, globalArgMatchers, invocationCountMatcher.FailureMessage()))
		}
	}
	return methodInvocations
}

func (genericMock *GenericMock) GetInvocationParams(methodInvocations []MethodInvocation) [][]Param {
	if len(methodInvocations) == 0 {
		return nil
	}
	result := make([][]Param, len(methodInvocations[len(methodInvocations)-1].params))
	for i, invocation := range methodInvocations {
		for u, param := range invocation.params {
			if result[u] == nil {
				result[u] = make([]Param, len(methodInvocations))
			}
			result[u][i] = param
		}
	}
	return result
}

func (genericMock *GenericMock) methodInvocations(methodName string, params []Param, matchers []Matcher) []MethodInvocation {
	var invocations []MethodInvocation
	if _, exists := genericMock.mockedMethods[methodName]; exists {
		for _, invocation := range genericMock.mockedMethods[methodName].invocations {
			if (len(matchers) != 0 && Matchers(matchers).Matches(invocation.params)) ||
				(reflect.DeepEqual(params, invocation.params) ||
					(len(params) == 0 && len(invocation.params) == 0)) {
				invocations = append(invocations, invocation)
			}
		}
	}
	return invocations
}

type mockedMethod struct {
	name        string
	invocations []MethodInvocation
	stubbings   Stubbings
}

func (method *mockedMethod) Invoke(params []Param) ReturnValues {
	method.invocations = append(method.invocations, MethodInvocation{params, globalInvocationCounter.nextNumber()})
	stubbing := method.stubbings.find(params)
	if stubbing == nil {
		return ReturnValues{}
	}
	return stubbing.Invoke(params)
}

func (method *mockedMethod) stub(paramMatchers Matchers, callback func([]Param) ReturnValues) {
	stubbing := method.stubbings.findByMatchers(paramMatchers)
	if stubbing == nil {
		stubbing = &Stubbing{paramMatchers: paramMatchers}
		method.stubbings = append(method.stubbings, stubbing)
	}
	stubbing.callbackSequence = append(stubbing.callbackSequence, callback)
}

func (method *mockedMethod) removeLastInvocation() {
	method.invocations = method.invocations[:len(method.invocations)-1]
}

func (method *mockedMethod) reset(paramMatchers Matchers) {
	method.stubbings.removeByMatchers(paramMatchers)
}

type Counter struct {
	count int
}

func (counter *Counter) nextNumber() (nextNumber int) {
	nextNumber = counter.count
	counter.count++
	return
}

var globalInvocationCounter Counter
<commit_msg>Fix in-order-verification when it is the very verification in the test suite<commit_after>// Copyright 2015 <NAME>
//
// 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 pegomock

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/petergtz/pegomock/internal/verify"
)

var GlobalFailHandler FailHandler

func RegisterMockFailHandler(handler FailHandler) {
	GlobalFailHandler = handler
}
func RegisterMockTestingT(t *testing.T) {
	RegisterMockFailHandler(BuildTestingTGomegaFailHandler(t))
}

var lastInvocation *invocation
var globalArgMatchers Matchers

func RegisterMatcher(matcher Matcher) {
	globalArgMatchers.append(matcher)
}

type invocation struct {
	genericMock *GenericMock
	MethodName  string
	Params      []Param
	ReturnTypes []reflect.Type
}

type GenericMock struct {
	mockedMethods map[string]*mockedMethod
}

func (genericMock *GenericMock) Invoke(methodName string, params []Param, returnTypes []reflect.Type) ReturnValues {
	lastInvocation = &invocation{
		genericMock: genericMock,
		MethodName:  methodName,
		Params:      params,
		ReturnTypes: returnTypes,
	}
	return genericMock.getOrCreateMockedMethod(methodName).Invoke(params)
}

func (genericMock *GenericMock) stub(methodName string, paramMatchers []Matcher, returnValues ReturnValues) {
	genericMock.stubWithCallback(methodName, paramMatchers, func([]Param) ReturnValues { return returnValues })
}

func (genericMock *GenericMock) stubWithCallback(methodName string, paramMatchers []Matcher, callback func([]Param) ReturnValues) {
	genericMock.getOrCreateMockedMethod(methodName).stub(paramMatchers, callback)
}

func (genericMock *GenericMock) getOrCreateMockedMethod(methodName string) *mockedMethod {
	if _, ok := genericMock.mockedMethods[methodName]; !ok {
		genericMock.mockedMethods[methodName] = &mockedMethod{name: methodName}
	}
	return genericMock.mockedMethods[methodName]
}

func (genericMock *GenericMock) reset(methodName string, paramMatchers []Matcher) {
	genericMock.getOrCreateMockedMethod(methodName).reset(paramMatchers)
}

func (genericMock *GenericMock) Verify(
	inOrderContext *InOrderContext,
	invocationCountMatcher Matcher,
	methodName string,
	params []Param) []MethodInvocation {
	if GlobalFailHandler == nil {
		panic("No GlobalFailHandler set. Please use either RegisterMockFailHandler or RegisterMockTestingT to set a fail handler.")
	}
	defer func() { globalArgMatchers = nil }() // We don't want a panic somewhere during verification screw our global argMatchers

	if len(globalArgMatchers) != 0 {
		verifyArgMatcherUse(globalArgMatchers, params)
	}

	methodInvocations := genericMock.methodInvocations(methodName, params, globalArgMatchers)
	if inOrderContext != nil {
		for _, methodInvocation := range methodInvocations {
			if methodInvocation.orderingInvocationNumber <= inOrderContext.invocationCounter {
				GlobalFailHandler(fmt.Sprintf("Expected function call \"%v\" with params %v before function call \"%v\" with params %v",
					methodName, params, inOrderContext.lastInvokedMethodName, inOrderContext.lastInvokedMethodParams))
			}
			inOrderContext.invocationCounter = methodInvocation.orderingInvocationNumber
			inOrderContext.lastInvokedMethodName = methodName
			inOrderContext.lastInvokedMethodParams = params
		}
	}
	if !invocationCountMatcher.Matches(len(methodInvocations)) {
		if len(globalArgMatchers) == 0 {
			GlobalFailHandler(fmt.Sprintf(
				"Mock invocation count for method \"%s\" with params %v does not match expectation.\n\n\t%v",
				methodName, params, invocationCountMatcher.FailureMessage()))
		} else {
			GlobalFailHandler(fmt.Sprintf(
				"Mock invocation count for method \"%s\" with params %v does not match expectation.\n\n\t%v",
				methodName, globalArgMatchers, invocationCountMatcher.FailureMessage()))
		}
	}
	return methodInvocations
}

func (genericMock *GenericMock) GetInvocationParams(methodInvocations []MethodInvocation) [][]Param {
	if len(methodInvocations) == 0 {
		return nil
	}
	result := make([][]Param, len(methodInvocations[len(methodInvocations)-1].params))
	for i, invocation := range methodInvocations {
		for u, param := range invocation.params {
			if result[u] == nil {
				result[u] = make([]Param, len(methodInvocations))
			}
			result[u][i] = param
		}
	}
	return result
}

func (genericMock *GenericMock) methodInvocations(methodName string, params []Param, matchers []Matcher) []MethodInvocation {
	var invocations []MethodInvocation
	if _, exists := genericMock.mockedMethods[methodName]; exists {
		for _, invocation := range genericMock.mockedMethods[methodName].invocations {
			if (len(matchers) != 0 && Matchers(matchers).Matches(invocation.params)) ||
				(reflect.DeepEqual(params, invocation.params) ||
					(len(params) == 0 && len(invocation.params) == 0)) {
				invocations = append(invocations, invocation)
			}
		}
	}
	return invocations
}

type mockedMethod struct {
	name        string
	invocations []MethodInvocation
	stubbings   Stubbings
}

func (method *mockedMethod) Invoke(params []Param) ReturnValues {
	method.invocations = append(method.invocations, MethodInvocation{params, globalInvocationCounter.nextNumber()})
	stubbing := method.stubbings.find(params)
	if stubbing == nil {
		return ReturnValues{}
	}
	return stubbing.Invoke(params)
}

func (method *mockedMethod) stub(paramMatchers Matchers, callback func([]Param) ReturnValues) {
	stubbing := method.stubbings.findByMatchers(paramMatchers)
	if stubbing == nil {
		stubbing = &Stubbing{paramMatchers: paramMatchers}
		method.stubbings = append(method.stubbings, stubbing)
	}
	stubbing.callbackSequence = append(stubbing.callbackSequence, callback)
}

func (method *mockedMethod) removeLastInvocation() {
	method.invocations = method.invocations[:len(method.invocations)-1]
}

func (method *mockedMethod) reset(paramMatchers Matchers) {
	method.stubbings.removeByMatchers(paramMatchers)
}

type Counter struct {
	count int
}

func (counter *Counter) nextNumber() (nextNumber int) {
	nextNumber = counter.count
	counter.count++
	return
}

var globalInvocationCounter = Counter{1}

{'fraction_non_alphanumeric': 0.1013482457484296, 'fraction_numerical': 0.0025279607783055004, 'mean_word_length': 5.616827166751141, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1226716', 'n_tokens_mistral': 4031, 'n_tokens_neox': 3804, 'n_words': 971}