// Code generated by mockery v2.4.0. DO NOT EDIT.

package mocks

import (
	context "context"

	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/golden/go/tiling"

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

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

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

	var r0 digest_counter.DigestCount
	if rf, ok := ret.Get(0).(func(paramtools.ParamSet, 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
}

// MostRecentPositiveDigest provides a mock function with given fields: ctx, traceID
func (_m *IndexSearcher) MostRecentPositiveDigest(ctx context.Context, traceID tiling.TraceID) (types.Digest, error) {
	ret := _m.Called(ctx, traceID)

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

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

	return r0, r1
}

// SlicedTraces provides a mock function with given fields: is, query
func (_m *IndexSearcher) SlicedTraces(is types.IgnoreState, query map[string][]string) []*tiling.TracePair {
	ret := _m.Called(is, query)

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

	return r0
}

// SummarizeByGrouping provides a mock function with given fields: ctx, corpus, query, is, head
func (_m *IndexSearcher) SummarizeByGrouping(ctx context.Context, corpus string, query paramtools.ParamSet, is types.IgnoreState, head bool) ([]*summary.TriageStatus, error) {
	ret := _m.Called(ctx, corpus, query, is, head)

	var r0 []*summary.TriageStatus
	if rf, ok := ret.Get(0).(func(context.Context, string, paramtools.ParamSet, types.IgnoreState, bool) []*summary.TriageStatus); ok {
		r0 = rf(ctx, corpus, 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(context.Context, string, paramtools.ParamSet, types.IgnoreState, bool) error); ok {
		r1 = rf(ctx, corpus, query, is, head)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

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

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

	return r0
}
