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

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

import (
	reflect "reflect"

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

// MockDiagnosticsServiceIface is a mock of DiagnosticsServiceIface interface.
type MockDiagnosticsServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockDiagnosticsServiceIfaceMockRecorder
	isgomock struct{}
}

// MockDiagnosticsServiceIfaceMockRecorder is the mock recorder for MockDiagnosticsServiceIface.
type MockDiagnosticsServiceIfaceMockRecorder struct {
	mock *MockDiagnosticsServiceIface
}

// NewMockDiagnosticsServiceIface creates a new mock instance.
func NewMockDiagnosticsServiceIface(ctrl *gomock.Controller) *MockDiagnosticsServiceIface {
	mock := &MockDiagnosticsServiceIface{ctrl: ctrl}
	mock.recorder = &MockDiagnosticsServiceIfaceMockRecorder{mock}
	return mock
}

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

// GetDiagnosticsData mocks base method.
func (m *MockDiagnosticsServiceIface) GetDiagnosticsData(p *GetDiagnosticsDataParams) (*GetDiagnosticsDataResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "GetDiagnosticsData", p)
	ret0, _ := ret[0].(*GetDiagnosticsDataResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// NewGetDiagnosticsDataParams mocks base method.
func (m *MockDiagnosticsServiceIface) NewGetDiagnosticsDataParams(targetid string) *GetDiagnosticsDataParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewGetDiagnosticsDataParams", targetid)
	ret0, _ := ret[0].(*GetDiagnosticsDataParams)
	return ret0
}

// NewGetDiagnosticsDataParams indicates an expected call of NewGetDiagnosticsDataParams.
func (mr *MockDiagnosticsServiceIfaceMockRecorder) NewGetDiagnosticsDataParams(targetid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewGetDiagnosticsDataParams", reflect.TypeOf((*MockDiagnosticsServiceIface)(nil).NewGetDiagnosticsDataParams), targetid)
}

// NewRunDiagnosticsParams mocks base method.
func (m *MockDiagnosticsServiceIface) NewRunDiagnosticsParams(ipaddress, targetid, diagnosticsType string) *RunDiagnosticsParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewRunDiagnosticsParams", ipaddress, targetid, diagnosticsType)
	ret0, _ := ret[0].(*RunDiagnosticsParams)
	return ret0
}

// NewRunDiagnosticsParams indicates an expected call of NewRunDiagnosticsParams.
func (mr *MockDiagnosticsServiceIfaceMockRecorder) NewRunDiagnosticsParams(ipaddress, targetid, diagnosticsType any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewRunDiagnosticsParams", reflect.TypeOf((*MockDiagnosticsServiceIface)(nil).NewRunDiagnosticsParams), ipaddress, targetid, diagnosticsType)
}

// RunDiagnostics mocks base method.
func (m *MockDiagnosticsServiceIface) RunDiagnostics(p *RunDiagnosticsParams) (*RunDiagnosticsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "RunDiagnostics", p)
	ret0, _ := ret[0].(*RunDiagnosticsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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