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

package mocks

import (
	context "context"

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

	time "time"

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

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

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

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

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

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

	return r0, r1
}

// GetJobsFromDateRange provides a mock function with given fields: _a0, _a1, _a2, _a3
func (_m *JobDB) GetJobsFromDateRange(_a0 context.Context, _a1 time.Time, _a2 time.Time, _a3 string) ([]*types.Job, error) {
	ret := _m.Called(_a0, _a1, _a2, _a3)

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

	var r0 []*types.Job
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time, string) ([]*types.Job, error)); ok {
		return rf(_a0, _a1, _a2, _a3)
	}
	if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time, string) []*types.Job); ok {
		r0 = rf(_a0, _a1, _a2, _a3)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).([]*types.Job)
		}
	}

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

	return r0, r1
}

// ModifiedJobsCh provides a mock function with given fields: _a0
func (_m *JobDB) ModifiedJobsCh(_a0 context.Context) <-chan []*types.Job {
	ret := _m.Called(_a0)

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

	var r0 <-chan []*types.Job
	if rf, ok := ret.Get(0).(func(context.Context) <-chan []*types.Job); ok {
		r0 = rf(_a0)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(<-chan []*types.Job)
		}
	}

	return r0
}

// PutJob provides a mock function with given fields: _a0, _a1
func (_m *JobDB) PutJob(_a0 context.Context, _a1 *types.Job) error {
	ret := _m.Called(_a0, _a1)

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

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, *types.Job) error); ok {
		r0 = rf(_a0, _a1)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// PutJobs provides a mock function with given fields: _a0, _a1
func (_m *JobDB) PutJobs(_a0 context.Context, _a1 []*types.Job) error {
	ret := _m.Called(_a0, _a1)

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

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, []*types.Job) error); ok {
		r0 = rf(_a0, _a1)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// PutJobsInChunks provides a mock function with given fields: _a0, _a1
func (_m *JobDB) PutJobsInChunks(_a0 context.Context, _a1 []*types.Job) error {
	ret := _m.Called(_a0, _a1)

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

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, []*types.Job) error); ok {
		r0 = rf(_a0, _a1)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// SearchJobs provides a mock function with given fields: _a0, _a1
func (_m *JobDB) SearchJobs(_a0 context.Context, _a1 *db.JobSearchParams) ([]*types.Job, error) {
	ret := _m.Called(_a0, _a1)

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

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

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

	return r0, r1
}

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

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

	return mock
}
