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

package mocks

import (
	context "context"

	mock "github.com/stretchr/testify/mock"
	specs "go.skia.org/infra/task_scheduler/go/specs"

	task_cfg_cache "go.skia.org/infra/task_scheduler/go/task_cfg_cache"

	time "time"

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

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

// Cleanup provides a mock function with given fields: ctx, period
func (_m *TaskCfgCache) Cleanup(ctx context.Context, period time.Duration) error {
	ret := _m.Called(ctx, period)

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

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

	return r0
}

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

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

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

	return r0
}

// Get provides a mock function with given fields: _a0, _a1
func (_m *TaskCfgCache) Get(_a0 context.Context, _a1 types.RepoState) (*specs.TasksCfg, error, error) {
	ret := _m.Called(_a0, _a1)

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

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

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

	if rf, ok := ret.Get(2).(func(context.Context, types.RepoState) error); ok {
		r2 = rf(_a0, _a1)
	} else {
		r2 = ret.Error(2)
	}

	return r0, r1, r2
}

// Set provides a mock function with given fields: ctx, rs, cfg, storedErr
func (_m *TaskCfgCache) Set(ctx context.Context, rs types.RepoState, cfg *specs.TasksCfg, storedErr error) error {
	ret := _m.Called(ctx, rs, cfg, storedErr)

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

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, types.RepoState, *specs.TasksCfg, error) error); ok {
		r0 = rf(ctx, rs, cfg, storedErr)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SetIfUnset provides a mock function with given fields: ctx, rs, fn
func (_m *TaskCfgCache) SetIfUnset(ctx context.Context, rs types.RepoState, fn func(context.Context) (*task_cfg_cache.CachedValue, error)) (*task_cfg_cache.CachedValue, error) {
	ret := _m.Called(ctx, rs, fn)

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

	var r0 *task_cfg_cache.CachedValue
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, types.RepoState, func(context.Context) (*task_cfg_cache.CachedValue, error)) (*task_cfg_cache.CachedValue, error)); ok {
		return rf(ctx, rs, fn)
	}
	if rf, ok := ret.Get(0).(func(context.Context, types.RepoState, func(context.Context) (*task_cfg_cache.CachedValue, error)) *task_cfg_cache.CachedValue); ok {
		r0 = rf(ctx, rs, fn)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*task_cfg_cache.CachedValue)
		}
	}

	if rf, ok := ret.Get(1).(func(context.Context, types.RepoState, func(context.Context) (*task_cfg_cache.CachedValue, error)) error); ok {
		r1 = rf(ctx, rs, fn)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// NewTaskCfgCache creates a new instance of TaskCfgCache. 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 NewTaskCfgCache(t interface {
	mock.TestingT
	Cleanup(func())
}) *TaskCfgCache {
	mock := &TaskCfgCache{}
	mock.Mock.Test(t)

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

	return mock
}
