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

package mocks

import (
	blame "go.skia.org/infra/golden/go/blame"
	digest_counter "go.skia.org/infra/golden/go/digest_counter"

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

	paramtools "go.skia.org/infra/go/paramtools"

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

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

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

	url "net/url"
)

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

// CalcSummaries provides a mock function with given fields: query, is, head
func (_m *IndexSearcher) CalcSummaries(query url.Values, is types.IgnoreState, head bool) ([]*summary.TriageStatus, error) {
	ret := _m.Called(query, is, head)

	var r0 []*summary.TriageStatus
	if rf, ok := ret.Get(0).(func(url.Values, types.IgnoreState, bool) []*summary.TriageStatus); ok {
		r0 = rf(query, is, head)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*summary.TriageStatus)
		}
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(url.Values, types.IgnoreState, bool) error); ok {
		r1 = rf(query, is, head)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// DigestCountsByQuery provides a mock function with given fields: query, is
func (_m *IndexSearcher) DigestCountsByQuery(query url.Values, is types.IgnoreState) digest_counter.DigestCount {
	ret := _m.Called(query, is)

	var r0 digest_counter.DigestCount
	if rf, ok := ret.Get(0).(func(url.Values, types.IgnoreState) digest_counter.DigestCount); ok {
		r0 = rf(query, is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(digest_counter.DigestCount)
		}
	}

	return r0
}

// DigestCountsByTest provides a mock function with given fields: is
func (_m *IndexSearcher) DigestCountsByTest(is types.IgnoreState) map[types.TestName]digest_counter.DigestCount {
	ret := _m.Called(is)

	var r0 map[types.TestName]digest_counter.DigestCount
	if rf, ok := ret.Get(0).(func(types.IgnoreState) map[types.TestName]digest_counter.DigestCount); ok {
		r0 = rf(is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[types.TestName]digest_counter.DigestCount)
		}
	}

	return r0
}

// DigestCountsByTrace provides a mock function with given fields: is
func (_m *IndexSearcher) DigestCountsByTrace(is types.IgnoreState) map[tiling.TraceId]digest_counter.DigestCount {
	ret := _m.Called(is)

	var r0 map[tiling.TraceId]digest_counter.DigestCount
	if rf, ok := ret.Get(0).(func(types.IgnoreState) map[tiling.TraceId]digest_counter.DigestCount); ok {
		r0 = rf(is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[tiling.TraceId]digest_counter.DigestCount)
		}
	}

	return r0
}

// GetBlame provides a mock function with given fields: test, digest, commits
func (_m *IndexSearcher) GetBlame(test types.TestName, digest types.Digest, commits []*tiling.Commit) blame.BlameDistribution {
	ret := _m.Called(test, digest, commits)

	var r0 blame.BlameDistribution
	if rf, ok := ret.Get(0).(func(types.TestName, types.Digest, []*tiling.Commit) blame.BlameDistribution); ok {
		r0 = rf(test, digest, commits)
	} else {
		r0 = ret.Get(0).(blame.BlameDistribution)
	}

	return r0
}

// GetIgnoreMatcher provides a mock function with given fields:
func (_m *IndexSearcher) GetIgnoreMatcher() paramtools.ParamMatcher {
	ret := _m.Called()

	var r0 paramtools.ParamMatcher
	if rf, ok := ret.Get(0).(func() paramtools.ParamMatcher); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(paramtools.ParamMatcher)
		}
	}

	return r0
}

// GetParamsetSummary provides a mock function with given fields: test, digest, is
func (_m *IndexSearcher) GetParamsetSummary(test types.TestName, digest types.Digest, is types.IgnoreState) paramtools.ParamSet {
	ret := _m.Called(test, digest, is)

	var r0 paramtools.ParamSet
	if rf, ok := ret.Get(0).(func(types.TestName, types.Digest, types.IgnoreState) paramtools.ParamSet); ok {
		r0 = rf(test, digest, is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(paramtools.ParamSet)
		}
	}

	return r0
}

// GetParamsetSummaryByTest provides a mock function with given fields: is
func (_m *IndexSearcher) GetParamsetSummaryByTest(is types.IgnoreState) map[types.TestName]map[types.Digest]paramtools.ParamSet {
	ret := _m.Called(is)

	var r0 map[types.TestName]map[types.Digest]paramtools.ParamSet
	if rf, ok := ret.Get(0).(func(types.IgnoreState) map[types.TestName]map[types.Digest]paramtools.ParamSet); ok {
		r0 = rf(is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[types.TestName]map[types.Digest]paramtools.ParamSet)
		}
	}

	return r0
}

// GetSummaries provides a mock function with given fields: is
func (_m *IndexSearcher) GetSummaries(is types.IgnoreState) []*summary.TriageStatus {
	ret := _m.Called(is)

	var r0 []*summary.TriageStatus
	if rf, ok := ret.Get(0).(func(types.IgnoreState) []*summary.TriageStatus); ok {
		r0 = rf(is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*summary.TriageStatus)
		}
	}

	return r0
}

// MaxDigestsByTest provides a mock function with given fields: is
func (_m *IndexSearcher) MaxDigestsByTest(is types.IgnoreState) map[types.TestName]types.DigestSet {
	ret := _m.Called(is)

	var r0 map[types.TestName]types.DigestSet
	if rf, ok := ret.Get(0).(func(types.IgnoreState) map[types.TestName]types.DigestSet); ok {
		r0 = rf(is)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[types.TestName]types.DigestSet)
		}
	}

	return r0
}

// Tile provides a mock function with given fields:
func (_m *IndexSearcher) Tile() types.ComplexTile {
	ret := _m.Called()

	var r0 types.ComplexTile
	if rf, ok := ret.Get(0).(func() types.ComplexTile); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(types.ComplexTile)
		}
	}

	return r0
}
