// Code generated by mockery v0.0.0-dev. DO NOT EDIT.

package mocks

import (
	context "context"
	time "time"

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

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

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

// AddTasks provides a mock function with given fields: tasks
func (_m *TaskCache) AddTasks(tasks []*types.Task) {
	_m.Called(tasks)
}

// GetTask provides a mock function with given fields: id
func (_m *TaskCache) GetTask(id string) (*types.Task, error) {
	ret := _m.Called(id)

	if len(ret) == 0 {
		panic("no return value specified for GetTask")
	}

	var r0 *types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func(string) (*types.Task, error)); ok {
		return rf(id)
	}
	if rf, ok := ret.Get(0).(func(string) *types.Task); ok {
		r0 = rf(id)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*types.Task)
		}
	}

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

	return r0, r1
}

// GetTaskForCommit provides a mock function with given fields: repo, revision, name
func (_m *TaskCache) GetTaskForCommit(repo string, revision string, name string) (*types.Task, error) {
	ret := _m.Called(repo, revision, name)

	if len(ret) == 0 {
		panic("no return value specified for GetTaskForCommit")
	}

	var r0 *types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func(string, string, string) (*types.Task, error)); ok {
		return rf(repo, revision, name)
	}
	if rf, ok := ret.Get(0).(func(string, string, string) *types.Task); ok {
		r0 = rf(repo, revision, name)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*types.Task)
		}
	}

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

	return r0, r1
}

// GetTaskMaybeExpired provides a mock function with given fields: _a0, _a1
func (_m *TaskCache) GetTaskMaybeExpired(_a0 context.Context, _a1 string) (*types.Task, error) {
	ret := _m.Called(_a0, _a1)

	if len(ret) == 0 {
		panic("no return value specified for GetTaskMaybeExpired")
	}

	var r0 *types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) (*types.Task, error)); ok {
		return rf(_a0, _a1)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) *types.Task); ok {
		r0 = rf(_a0, _a1)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*types.Task)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
		r1 = rf(_a0, _a1)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// GetTasksByKey provides a mock function with given fields: key
func (_m *TaskCache) GetTasksByKey(key types.TaskKey) ([]*types.Task, error) {
	ret := _m.Called(key)

	if len(ret) == 0 {
		panic("no return value specified for GetTasksByKey")
	}

	var r0 []*types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func(types.TaskKey) ([]*types.Task, error)); ok {
		return rf(key)
	}
	if rf, ok := ret.Get(0).(func(types.TaskKey) []*types.Task); ok {
		r0 = rf(key)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*types.Task)
		}
	}

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

	return r0, r1
}

// GetTasksForCommits provides a mock function with given fields: repo, commits
func (_m *TaskCache) GetTasksForCommits(repo string, commits []string) (map[string]map[string]*types.Task, error) {
	ret := _m.Called(repo, commits)

	if len(ret) == 0 {
		panic("no return value specified for GetTasksForCommits")
	}

	var r0 map[string]map[string]*types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func(string, []string) (map[string]map[string]*types.Task, error)); ok {
		return rf(repo, commits)
	}
	if rf, ok := ret.Get(0).(func(string, []string) map[string]map[string]*types.Task); ok {
		r0 = rf(repo, commits)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(map[string]map[string]*types.Task)
		}
	}

	if rf, ok := ret.Get(1).(func(string, []string) error); ok {
		r1 = rf(repo, commits)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// GetTasksFromDateRange provides a mock function with given fields: from, to
func (_m *TaskCache) GetTasksFromDateRange(from time.Time, to time.Time) ([]*types.Task, error) {
	ret := _m.Called(from, to)

	if len(ret) == 0 {
		panic("no return value specified for GetTasksFromDateRange")
	}

	var r0 []*types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func(time.Time, time.Time) ([]*types.Task, error)); ok {
		return rf(from, to)
	}
	if rf, ok := ret.Get(0).(func(time.Time, time.Time) []*types.Task); ok {
		r0 = rf(from, to)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*types.Task)
		}
	}

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

	return r0, r1
}

// KnownTaskName provides a mock function with given fields: repo, name
func (_m *TaskCache) KnownTaskName(repo string, name string) bool {
	ret := _m.Called(repo, name)

	if len(ret) == 0 {
		panic("no return value specified for KnownTaskName")
	}

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

	return r0
}

// UnfinishedTasks provides a mock function with given fields:
func (_m *TaskCache) UnfinishedTasks() ([]*types.Task, error) {
	ret := _m.Called()

	if len(ret) == 0 {
		panic("no return value specified for UnfinishedTasks")
	}

	var r0 []*types.Task
	var r1 error
	if rf, ok := ret.Get(0).(func() ([]*types.Task, error)); ok {
		return rf()
	}
	if rf, ok := ret.Get(0).(func() []*types.Task); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*types.Task)
		}
	}

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

	return r0, r1
}

// Update provides a mock function with given fields: ctx
func (_m *TaskCache) Update(ctx context.Context) error {
	ret := _m.Called(ctx)

	if len(ret) == 0 {
		panic("no return value specified for Update")
	}

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

	return r0
}

// NewTaskCache creates a new instance of TaskCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewTaskCache(t interface {
	mock.TestingT
	Cleanup(func())
}) *TaskCache {
	mock := &TaskCache{}
	mock.Mock.Test(t)

	t.Cleanup(func() { mock.AssertExpectations(t) })

	return mock
}
