// 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"

	testing "testing"

	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)

	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()

	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)

	var r0 *specs.TasksCfg
	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)
		}
	}

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

	var r2 error
	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)

	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)

	var r0 *task_cfg_cache.CachedValue
	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)
		}
	}

	var r1 error
	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 cleanup function to assert the mocks expectations.
func NewTaskCfgCache(t testing.TB) *TaskCfgCache {
	mock := &TaskCfgCache{}

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

	return mock
}
