// Code generated by mockery v1.0.0. DO NOT EDIT.

package mocks

import (
	context "context"

	jsonio "go.skia.org/infra/golden/go/jsonio"

	mock "github.com/stretchr/testify/mock"

	tiling "go.skia.org/infra/golden/go/tiling"

	types "go.skia.org/infra/golden/go/types"
)

// GoldClient is an autogenerated mock type for the GoldClient type
type GoldClient struct {
	mock.Mock
}

// Check provides a mock function with given fields: name, imgFileName, keys, optionalKeys
func (_m *GoldClient) Check(name types.TestName, imgFileName string, keys map[string]string, optionalKeys map[string]string) (bool, error) {
	ret := _m.Called(name, imgFileName, keys, optionalKeys)

	var r0 bool
	if rf, ok := ret.Get(0).(func(types.TestName, string, map[string]string, map[string]string) bool); ok {
		r0 = rf(name, imgFileName, keys, optionalKeys)
	} else {
		r0 = ret.Get(0).(bool)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(types.TestName, string, map[string]string, map[string]string) error); ok {
		r1 = rf(name, imgFileName, keys, optionalKeys)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// Diff provides a mock function with given fields: ctx, name, corpus, imgFileName, outDir
func (_m *GoldClient) Diff(ctx context.Context, name types.TestName, corpus string, imgFileName string, outDir string) error {
	ret := _m.Called(ctx, name, corpus, imgFileName, outDir)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, types.TestName, string, string, string) error); ok {
		r0 = rf(ctx, name, corpus, imgFileName, outDir)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// Finalize provides a mock function with given fields:
func (_m *GoldClient) Finalize() error {
	ret := _m.Called()

	var r0 error
	if rf, ok := ret.Get(0).(func() error); ok {
		r0 = rf()
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// MostRecentPositiveDigest provides a mock function with given fields: traceId
func (_m *GoldClient) MostRecentPositiveDigest(traceId tiling.TraceID) (types.Digest, error) {
	ret := _m.Called(traceId)

	var r0 types.Digest
	if rf, ok := ret.Get(0).(func(tiling.TraceID) types.Digest); ok {
		r0 = rf(traceId)
	} else {
		r0 = ret.Get(0).(types.Digest)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(tiling.TraceID) error); ok {
		r1 = rf(traceId)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// SetSharedConfig provides a mock function with given fields: sharedConfig, skipValidation
func (_m *GoldClient) SetSharedConfig(sharedConfig jsonio.GoldResults, skipValidation bool) error {
	ret := _m.Called(sharedConfig, skipValidation)

	var r0 error
	if rf, ok := ret.Get(0).(func(jsonio.GoldResults, bool) error); ok {
		r0 = rf(sharedConfig, skipValidation)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// Test provides a mock function with given fields: name, imgFileName, imgDigest, additionalKeys, optionalKeys
func (_m *GoldClient) Test(name types.TestName, imgFileName string, imgDigest types.Digest, additionalKeys map[string]string, optionalKeys map[string]string) (bool, error) {
	ret := _m.Called(name, imgFileName, imgDigest, additionalKeys, optionalKeys)

	var r0 bool
	if rf, ok := ret.Get(0).(func(types.TestName, string, types.Digest, map[string]string, map[string]string) bool); ok {
		r0 = rf(name, imgFileName, imgDigest, additionalKeys, optionalKeys)
	} else {
		r0 = ret.Get(0).(bool)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(types.TestName, string, types.Digest, map[string]string, map[string]string) error); ok {
		r1 = rf(name, imgFileName, imgDigest, additionalKeys, optionalKeys)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// TriageAsPositive provides a mock function with given fields: testName, digest, algorithmName
func (_m *GoldClient) TriageAsPositive(testName types.TestName, digest types.Digest, algorithmName string) error {
	ret := _m.Called(testName, digest, algorithmName)

	var r0 error
	if rf, ok := ret.Get(0).(func(types.TestName, types.Digest, string) error); ok {
		r0 = rf(testName, digest, algorithmName)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// Whoami provides a mock function with given fields:
func (_m *GoldClient) Whoami() (string, error) {
	ret := _m.Called()

	var r0 string
	if rf, ok := ret.Get(0).(func() string); ok {
		r0 = rf()
	} else {
		r0 = ret.Get(0).(string)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func() error); ok {
		r1 = rf()
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}
