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

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

import (
	reflect "reflect"

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

// MockHypervisorServiceIface is a mock of HypervisorServiceIface interface.
type MockHypervisorServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockHypervisorServiceIfaceMockRecorder
	isgomock struct{}
}

// MockHypervisorServiceIfaceMockRecorder is the mock recorder for MockHypervisorServiceIface.
type MockHypervisorServiceIfaceMockRecorder struct {
	mock *MockHypervisorServiceIface
}

// NewMockHypervisorServiceIface creates a new mock instance.
func NewMockHypervisorServiceIface(ctrl *gomock.Controller) *MockHypervisorServiceIface {
	mock := &MockHypervisorServiceIface{ctrl: ctrl}
	mock.recorder = &MockHypervisorServiceIfaceMockRecorder{mock}
	return mock
}

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

// GetHypervisorCapabilityByID mocks base method.
func (m *MockHypervisorServiceIface) GetHypervisorCapabilityByID(id string, opts ...OptionFunc) (*HypervisorCapability, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{id}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetHypervisorCapabilityByID", varargs...)
	ret0, _ := ret[0].(*HypervisorCapability)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetHypervisorCapabilityByID indicates an expected call of GetHypervisorCapabilityByID.
func (mr *MockHypervisorServiceIfaceMockRecorder) GetHypervisorCapabilityByID(id any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{id}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHypervisorCapabilityByID", reflect.TypeOf((*MockHypervisorServiceIface)(nil).GetHypervisorCapabilityByID), varargs...)
}

// ListHypervisorCapabilities mocks base method.
func (m *MockHypervisorServiceIface) ListHypervisorCapabilities(p *ListHypervisorCapabilitiesParams) (*ListHypervisorCapabilitiesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListHypervisorCapabilities", p)
	ret0, _ := ret[0].(*ListHypervisorCapabilitiesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// ListHypervisors mocks base method.
func (m *MockHypervisorServiceIface) ListHypervisors(p *ListHypervisorsParams) (*ListHypervisorsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListHypervisors", p)
	ret0, _ := ret[0].(*ListHypervisorsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

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

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

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

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

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

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

// UpdateHypervisorCapabilities mocks base method.
func (m *MockHypervisorServiceIface) UpdateHypervisorCapabilities(p *UpdateHypervisorCapabilitiesParams) (*UpdateHypervisorCapabilitiesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UpdateHypervisorCapabilities", p)
	ret0, _ := ret[0].(*UpdateHypervisorCapabilitiesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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