/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You 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.
//

// Code generated by MockGen. DO NOT EDIT.
// Source: tps_limiter.go

// Package filter is a generated GoMock package.
package tps

import (
	reflect "reflect"
)

import (
	gomock "github.com/golang/mock/gomock"
)

import (
	common "github.com/apache/dubbo-go/common"
	protocol "github.com/apache/dubbo-go/protocol"
)

// MockTpsLimiter is a mock of TpsLimiter interface
type MockTpsLimiter struct {
	ctrl     *gomock.Controller
	recorder *MockTpsLimiterMockRecorder
}

// MockTpsLimiterMockRecorder is the mock recorder for MockTpsLimiter
type MockTpsLimiterMockRecorder struct {
	mock *MockTpsLimiter
}

// NewMockTpsLimiter creates a new mock instance
func NewMockTpsLimiter(ctrl *gomock.Controller) *MockTpsLimiter {
	mock := &MockTpsLimiter{ctrl: ctrl}
	mock.recorder = &MockTpsLimiterMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockTpsLimiter) EXPECT() *MockTpsLimiterMockRecorder {
	return m.recorder
}

// IsAllowable mocks base method
func (m *MockTpsLimiter) IsAllowable(arg0 common.URL, arg1 protocol.Invocation) bool {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "IsAllowable", arg0, arg1)
	ret0, _ := ret[0].(bool)
	return ret0
}

// IsAllowable indicates an expected call of IsAllowable
func (mr *MockTpsLimiterMockRecorder) IsAllowable(arg0, arg1 interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAllowable", reflect.TypeOf((*MockTpsLimiter)(nil).IsAllowable), arg0, arg1)
}
