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

package mocks

import (
	context "context"

	iam "cloud.google.com/go/iam"
	gopubsub "go.skia.org/infra/go/pubsub"

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

	pubsub "cloud.google.com/go/pubsub"

	time "time"
)

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

// Config provides a mock function with given fields: ctx
func (_m *Subscription) Config(ctx context.Context) (pubsub.SubscriptionConfig, error) {
	ret := _m.Called(ctx)

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

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

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

	return r0, r1
}

// CreateSnapshot provides a mock function with given fields: ctx, name
func (_m *Subscription) CreateSnapshot(ctx context.Context, name string) (*pubsub.SnapshotConfig, error) {
	ret := _m.Called(ctx, name)

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

	var r0 *pubsub.SnapshotConfig
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, string) (*pubsub.SnapshotConfig, error)); ok {
		return rf(ctx, name)
	}
	if rf, ok := ret.Get(0).(func(context.Context, string) *pubsub.SnapshotConfig); ok {
		r0 = rf(ctx, name)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(*pubsub.SnapshotConfig)
		}
	}

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

	return r0, r1
}

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

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

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

	return r0
}

// Exists provides a mock function with given fields: ctx
func (_m *Subscription) Exists(ctx context.Context) (bool, error) {
	ret := _m.Called(ctx)

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

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

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

	return r0, r1
}

// IAM provides a mock function with no fields
func (_m *Subscription) IAM() *iam.Handle {
	ret := _m.Called()

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

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

	return r0
}

// ID provides a mock function with no fields
func (_m *Subscription) ID() string {
	ret := _m.Called()

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

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

	return r0
}

// Receive provides a mock function with given fields: ctx, f
func (_m *Subscription) Receive(ctx context.Context, f func(context.Context, *pubsub.Message)) error {
	ret := _m.Called(ctx, f)

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

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

	return r0
}

// SeekToSnapshot provides a mock function with given fields: ctx, snap
func (_m *Subscription) SeekToSnapshot(ctx context.Context, snap gopubsub.Snapshot) error {
	ret := _m.Called(ctx, snap)

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

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

	return r0
}

// SeekToTime provides a mock function with given fields: ctx, t
func (_m *Subscription) SeekToTime(ctx context.Context, t time.Time) error {
	ret := _m.Called(ctx, t)

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

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

	return r0
}

// String provides a mock function with no fields
func (_m *Subscription) String() string {
	ret := _m.Called()

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

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

	return r0
}

// Update provides a mock function with given fields: ctx, cfg
func (_m *Subscription) Update(ctx context.Context, cfg pubsub.SubscriptionConfigToUpdate) (pubsub.SubscriptionConfig, error) {
	ret := _m.Called(ctx, cfg)

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

	var r0 pubsub.SubscriptionConfig
	var r1 error
	if rf, ok := ret.Get(0).(func(context.Context, pubsub.SubscriptionConfigToUpdate) (pubsub.SubscriptionConfig, error)); ok {
		return rf(ctx, cfg)
	}
	if rf, ok := ret.Get(0).(func(context.Context, pubsub.SubscriptionConfigToUpdate) pubsub.SubscriptionConfig); ok {
		r0 = rf(ctx, cfg)
	} else {
		r0 = ret.Get(0).(pubsub.SubscriptionConfig)
	}

	if rf, ok := ret.Get(1).(func(context.Context, pubsub.SubscriptionConfigToUpdate) error); ok {
		r1 = rf(ctx, cfg)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

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

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

	return mock
}
