//
// 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: ./cloudstack/ASNumberRangeService.go
//
// Generated by this command:
//
//	mockgen -destination=./cloudstack/ASNumberRangeService_mock.go -package=cloudstack -copyright_file=header.txt -source=./cloudstack/ASNumberRangeService.go
//

// Package cloudstack is a generated GoMock package.
package cloudstack

import (
	reflect "reflect"

	gomock "go.uber.org/mock/gomock"
)

// MockASNumberRangeServiceIface is a mock of ASNumberRangeServiceIface interface.
type MockASNumberRangeServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockASNumberRangeServiceIfaceMockRecorder
	isgomock struct{}
}

// MockASNumberRangeServiceIfaceMockRecorder is the mock recorder for MockASNumberRangeServiceIface.
type MockASNumberRangeServiceIfaceMockRecorder struct {
	mock *MockASNumberRangeServiceIface
}

// NewMockASNumberRangeServiceIface creates a new mock instance.
func NewMockASNumberRangeServiceIface(ctrl *gomock.Controller) *MockASNumberRangeServiceIface {
	mock := &MockASNumberRangeServiceIface{ctrl: ctrl}
	mock.recorder = &MockASNumberRangeServiceIfaceMockRecorder{mock}
	return mock
}

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

// CreateASNRange mocks base method.
func (m *MockASNumberRangeServiceIface) CreateASNRange(p *CreateASNRangeParams) (*CreateASNRangeResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "CreateASNRange", p)
	ret0, _ := ret[0].(*CreateASNRangeResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// CreateASNRange indicates an expected call of CreateASNRange.
func (mr *MockASNumberRangeServiceIfaceMockRecorder) CreateASNRange(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateASNRange", reflect.TypeOf((*MockASNumberRangeServiceIface)(nil).CreateASNRange), p)
}

// DeleteASNRange mocks base method.
func (m *MockASNumberRangeServiceIface) DeleteASNRange(p *DeleteASNRangeParams) (*DeleteASNRangeResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteASNRange", p)
	ret0, _ := ret[0].(*DeleteASNRangeResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// DeleteASNRange indicates an expected call of DeleteASNRange.
func (mr *MockASNumberRangeServiceIfaceMockRecorder) DeleteASNRange(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteASNRange", reflect.TypeOf((*MockASNumberRangeServiceIface)(nil).DeleteASNRange), p)
}

// ListASNRanges mocks base method.
func (m *MockASNumberRangeServiceIface) ListASNRanges(p *ListASNRangesParams) (*ListASNRangesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListASNRanges", p)
	ret0, _ := ret[0].(*ListASNRangesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListASNRanges indicates an expected call of ListASNRanges.
func (mr *MockASNumberRangeServiceIfaceMockRecorder) ListASNRanges(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListASNRanges", reflect.TypeOf((*MockASNumberRangeServiceIface)(nil).ListASNRanges), p)
}

// NewCreateASNRangeParams mocks base method.
func (m *MockASNumberRangeServiceIface) NewCreateASNRangeParams(endasn, startasn int64, zoneid string) *CreateASNRangeParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewCreateASNRangeParams", endasn, startasn, zoneid)
	ret0, _ := ret[0].(*CreateASNRangeParams)
	return ret0
}

// NewCreateASNRangeParams indicates an expected call of NewCreateASNRangeParams.
func (mr *MockASNumberRangeServiceIfaceMockRecorder) NewCreateASNRangeParams(endasn, startasn, zoneid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewCreateASNRangeParams", reflect.TypeOf((*MockASNumberRangeServiceIface)(nil).NewCreateASNRangeParams), endasn, startasn, zoneid)
}

// NewDeleteASNRangeParams mocks base method.
func (m *MockASNumberRangeServiceIface) NewDeleteASNRangeParams(id string) *DeleteASNRangeParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewDeleteASNRangeParams", id)
	ret0, _ := ret[0].(*DeleteASNRangeParams)
	return ret0
}

// NewDeleteASNRangeParams indicates an expected call of NewDeleteASNRangeParams.
func (mr *MockASNumberRangeServiceIfaceMockRecorder) NewDeleteASNRangeParams(id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewDeleteASNRangeParams", reflect.TypeOf((*MockASNumberRangeServiceIface)(nil).NewDeleteASNRangeParams), id)
}

// NewListASNRangesParams mocks base method.
func (m *MockASNumberRangeServiceIface) NewListASNRangesParams() *ListASNRangesParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListASNRangesParams")
	ret0, _ := ret[0].(*ListASNRangesParams)
	return ret0
}

// NewListASNRangesParams indicates an expected call of NewListASNRangesParams.
func (mr *MockASNumberRangeServiceIfaceMockRecorder) NewListASNRangesParams() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListASNRangesParams", reflect.TypeOf((*MockASNumberRangeServiceIface)(nil).NewListASNRangesParams))
}
