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

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

import (
	reflect "reflect"

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

// MockSolidFireServiceIface is a mock of SolidFireServiceIface interface.
type MockSolidFireServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockSolidFireServiceIfaceMockRecorder
	isgomock struct{}
}

// MockSolidFireServiceIfaceMockRecorder is the mock recorder for MockSolidFireServiceIface.
type MockSolidFireServiceIfaceMockRecorder struct {
	mock *MockSolidFireServiceIface
}

// NewMockSolidFireServiceIface creates a new mock instance.
func NewMockSolidFireServiceIface(ctrl *gomock.Controller) *MockSolidFireServiceIface {
	mock := &MockSolidFireServiceIface{ctrl: ctrl}
	mock.recorder = &MockSolidFireServiceIfaceMockRecorder{mock}
	return mock
}

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

// GetSolidFireAccountId mocks base method.
func (m *MockSolidFireServiceIface) GetSolidFireAccountId(p *GetSolidFireAccountIdParams) (*GetSolidFireAccountIdResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetSolidFireAccountId", p)
	ret0, _ := ret[0].(*GetSolidFireAccountIdResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// GetSolidFireVolumeAccessGroupIds mocks base method.
func (m *MockSolidFireServiceIface) GetSolidFireVolumeAccessGroupIds(p *GetSolidFireVolumeAccessGroupIdsParams) (*GetSolidFireVolumeAccessGroupIdsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetSolidFireVolumeAccessGroupIds", p)
	ret0, _ := ret[0].(*GetSolidFireVolumeAccessGroupIdsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// GetSolidFireVolumeSize mocks base method.
func (m *MockSolidFireServiceIface) GetSolidFireVolumeSize(p *GetSolidFireVolumeSizeParams) (*GetSolidFireVolumeSizeResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetSolidFireVolumeSize", p)
	ret0, _ := ret[0].(*GetSolidFireVolumeSizeResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// NewGetSolidFireAccountIdParams mocks base method.
func (m *MockSolidFireServiceIface) NewGetSolidFireAccountIdParams(accountid, storageid string) *GetSolidFireAccountIdParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewGetSolidFireAccountIdParams", accountid, storageid)
	ret0, _ := ret[0].(*GetSolidFireAccountIdParams)
	return ret0
}

// NewGetSolidFireAccountIdParams indicates an expected call of NewGetSolidFireAccountIdParams.
func (mr *MockSolidFireServiceIfaceMockRecorder) NewGetSolidFireAccountIdParams(accountid, storageid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewGetSolidFireAccountIdParams", reflect.TypeOf((*MockSolidFireServiceIface)(nil).NewGetSolidFireAccountIdParams), accountid, storageid)
}

// NewGetSolidFireVolumeAccessGroupIdsParams mocks base method.
func (m *MockSolidFireServiceIface) NewGetSolidFireVolumeAccessGroupIdsParams(clusterid, storageid string) *GetSolidFireVolumeAccessGroupIdsParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewGetSolidFireVolumeAccessGroupIdsParams", clusterid, storageid)
	ret0, _ := ret[0].(*GetSolidFireVolumeAccessGroupIdsParams)
	return ret0
}

// NewGetSolidFireVolumeAccessGroupIdsParams indicates an expected call of NewGetSolidFireVolumeAccessGroupIdsParams.
func (mr *MockSolidFireServiceIfaceMockRecorder) NewGetSolidFireVolumeAccessGroupIdsParams(clusterid, storageid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewGetSolidFireVolumeAccessGroupIdsParams", reflect.TypeOf((*MockSolidFireServiceIface)(nil).NewGetSolidFireVolumeAccessGroupIdsParams), clusterid, storageid)
}

// NewGetSolidFireVolumeSizeParams mocks base method.
func (m *MockSolidFireServiceIface) NewGetSolidFireVolumeSizeParams(volumeid string) *GetSolidFireVolumeSizeParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewGetSolidFireVolumeSizeParams", volumeid)
	ret0, _ := ret[0].(*GetSolidFireVolumeSizeParams)
	return ret0
}

// NewGetSolidFireVolumeSizeParams indicates an expected call of NewGetSolidFireVolumeSizeParams.
func (mr *MockSolidFireServiceIfaceMockRecorder) NewGetSolidFireVolumeSizeParams(volumeid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewGetSolidFireVolumeSizeParams", reflect.TypeOf((*MockSolidFireServiceIface)(nil).NewGetSolidFireVolumeSizeParams), volumeid)
}
