Unistore Chore: add inocuous preparative changes for otel-based db observability (#94473)

add inocuous preparative changes for otel tracing
This commit is contained in:
Diego Augusto Molina 2024-10-09 20:32:09 +00:00 committed by GitHub
parent 8349db4947
commit 4a800eda9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 936 additions and 119 deletions

View File

@ -10,18 +10,19 @@ import (
"time"
"github.com/google/uuid"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"google.golang.org/protobuf/proto"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/grafana/grafana/pkg/storage/unified/sql/db"
"github.com/grafana/grafana/pkg/storage/unified/sql/dbutil"
"github.com/grafana/grafana/pkg/storage/unified/sql/sqltemplate"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
"google.golang.org/protobuf/proto"
apierrors "k8s.io/apimachinery/pkg/api/errors"
)
const trace_prefix = "sql.resource."
const tracePrefix = "sql.resource."
const defaultPollingInterval = 100 * time.Millisecond
type Backend interface {
@ -119,7 +120,7 @@ func (b *backend) Stop(_ context.Context) error {
}
func (b *backend) WriteEvent(ctx context.Context, event resource.WriteEvent) (int64, error) {
_, span := b.tracer.Start(ctx, trace_prefix+"WriteEvent")
_, span := b.tracer.Start(ctx, tracePrefix+"WriteEvent")
defer span.End()
// TODO: validate key ?
switch event.Type {
@ -135,7 +136,7 @@ func (b *backend) WriteEvent(ctx context.Context, event resource.WriteEvent) (in
}
func (b *backend) create(ctx context.Context, event resource.WriteEvent) (int64, error) {
ctx, span := b.tracer.Start(ctx, trace_prefix+"Create")
ctx, span := b.tracer.Start(ctx, tracePrefix+"Create")
defer span.End()
var newVersion int64
guid := uuid.New().String()
@ -192,7 +193,7 @@ func (b *backend) create(ctx context.Context, event resource.WriteEvent) (int64,
}
func (b *backend) update(ctx context.Context, event resource.WriteEvent) (int64, error) {
ctx, span := b.tracer.Start(ctx, trace_prefix+"Update")
ctx, span := b.tracer.Start(ctx, tracePrefix+"Update")
defer span.End()
var newVersion int64
guid := uuid.New().String()
@ -251,7 +252,7 @@ func (b *backend) update(ctx context.Context, event resource.WriteEvent) (int64,
}
func (b *backend) delete(ctx context.Context, event resource.WriteEvent) (int64, error) {
ctx, span := b.tracer.Start(ctx, trace_prefix+"Delete")
ctx, span := b.tracer.Start(ctx, tracePrefix+"Delete")
defer span.End()
var newVersion int64
guid := uuid.New().String()
@ -303,7 +304,7 @@ func (b *backend) delete(ctx context.Context, event resource.WriteEvent) (int64,
}
func (b *backend) ReadResource(ctx context.Context, req *resource.ReadRequest) *resource.ReadResponse {
_, span := b.tracer.Start(ctx, trace_prefix+".Read")
_, span := b.tracer.Start(ctx, tracePrefix+".Read")
defer span.End()
// TODO: validate key ?
@ -338,7 +339,7 @@ func (b *backend) ReadResource(ctx context.Context, req *resource.ReadRequest) *
}
func (b *backend) ListIterator(ctx context.Context, req *resource.ListRequest, cb func(resource.ListIterator) error) (int64, error) {
_, span := b.tracer.Start(ctx, trace_prefix+"List")
_, span := b.tracer.Start(ctx, tracePrefix+"List")
defer span.End()
if req.Options == nil || req.Options.Key.Group == "" || req.Options.Key.Resource == "" {
@ -608,7 +609,7 @@ func fetchLatestRV(ctx context.Context, x db.ContextExecer, d sqltemplate.Dialec
}
func (b *backend) poll(ctx context.Context, grp string, res string, since int64, stream chan<- *resource.WrittenEvent) (int64, error) {
ctx, span := b.tracer.Start(ctx, trace_prefix+"poll")
ctx, span := b.tracer.Start(ctx, tracePrefix+"poll")
defer span.End()
var records []*historyPollResponse

View File

@ -9,11 +9,10 @@ import (
"github.com/go-sql-driver/mysql"
"xorm.io/xorm"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/storage/unified/sql/db"
)
func getEngineMySQL(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, error) {
func getEngineMySQL(getter confGetter) (*xorm.Engine, error) {
config := mysql.NewConfig()
config.User = getter.String("user")
// accept the core Grafana jargon of `password` as well, originally Unified
@ -54,8 +53,6 @@ func getEngineMySQL(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, err
}
// FIXME: get rid of xorm
// TODO figure out why wrapping the db driver with hooks causes mysql errors when writing
//driverName := sqlstore.WrapDatabaseDriverWithHooks(db.DriverMySQL, tracer)
engine, err := xorm.NewEngine(db.DriverMySQL, config.FormatDSN())
if err != nil {
return nil, fmt.Errorf("open database: %w", err)
@ -68,7 +65,7 @@ func getEngineMySQL(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, err
return engine, nil
}
func getEnginePostgres(getter confGetter, tracer tracing.Tracer) (*xorm.Engine, error) {
func getEnginePostgres(getter confGetter) (*xorm.Engine, error) {
dsnKV := map[string]string{
"user": getter.String("user"),
// accept the core Grafana jargon of `password` as well, originally

View File

@ -25,14 +25,14 @@ func TestGetEngineMySQLFromConfig(t *testing.T) {
t.Run("happy path - with key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEngineMySQL(newValidMySQLGetter(true), nil)
engine, err := getEngineMySQL(newValidMySQLGetter(true))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
t.Run("happy path - without key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEngineMySQL(newValidMySQLGetter(false), nil)
engine, err := getEngineMySQL(newValidMySQLGetter(false))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
@ -47,7 +47,7 @@ func TestGetEngineMySQLFromConfig(t *testing.T) {
"db_user": "user",
"db_password": "password",
}, "db_")
engine, err := getEngineMySQL(getter, nil)
engine, err := getEngineMySQL(getter)
assert.Nil(t, engine)
assert.Error(t, err)
assert.ErrorIs(t, err, errInvalidUTF8Sequence)
@ -73,14 +73,14 @@ func TestGetEnginePostgresFromConfig(t *testing.T) {
t.Run("happy path - with key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEnginePostgres(newValidPostgresGetter(true), nil)
engine, err := getEnginePostgres(newValidPostgresGetter(true))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
t.Run("happy path - without key prefix", func(t *testing.T) {
t.Parallel()
engine, err := getEnginePostgres(newValidPostgresGetter(false), nil)
engine, err := getEnginePostgres(newValidPostgresGetter(false))
assert.NotNil(t, engine)
assert.NoError(t, err)
})
@ -94,7 +94,7 @@ func TestGetEnginePostgresFromConfig(t *testing.T) {
"db_user": "user",
"db_password": "password",
}, "db_")
engine, err := getEnginePostgres(getter, nil)
engine, err := getEnginePostgres(getter)
assert.Nil(t, engine)
assert.Error(t, err)
@ -110,7 +110,7 @@ func TestGetEnginePostgresFromConfig(t *testing.T) {
"db_user": "user",
"db_password": "password",
}, "db_")
engine, err := getEnginePostgres(getter, nil)
engine, err := getEnginePostgres(getter)
assert.Nil(t, engine)
assert.Error(t, err)

View File

@ -9,6 +9,7 @@ import (
"github.com/dlmiddlecote/sqlstats"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/trace"
"xorm.io/xorm"
infraDB "github.com/grafana/grafana/pkg/infra/db"
@ -63,7 +64,7 @@ type resourceDBProvider struct {
logQueries bool
}
func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracing.Tracer) (p *resourceDBProvider, err error) {
func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer trace.Tracer) (p *resourceDBProvider, err error) {
// Resource API has other configs in its section besides database ones, so
// we prefix them with "db_". We use the database config from core Grafana
// as fallback, and as it uses a dedicated INI section, then keys are not
@ -85,12 +86,12 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracin
// specific to Unified Storage
case dbType == dbTypePostgres:
p.registerMetrics = true
p.engine, err = getEnginePostgres(getter, tracer)
p.engine, err = getEnginePostgres(getter)
return p, err
case dbType == dbTypeMySQL:
p.registerMetrics = true
p.engine, err = getEngineMySQL(getter, tracer)
p.engine, err = getEngineMySQL(getter)
return p, err
// TODO: add support for SQLite
@ -103,12 +104,12 @@ func newResourceDBProvider(grafanaDB infraDB.DB, cfg *setting.Cfg, tracer tracin
case grafanaDBType == dbTypePostgres:
p.registerMetrics = true
p.engine, err = getEnginePostgres(fallbackGetter, tracer)
p.engine, err = getEnginePostgres(fallbackGetter)
return p, err
case grafanaDBType == dbTypeMySQL:
p.registerMetrics = true
p.engine, err = getEngineMySQL(fallbackGetter, tracer)
p.engine, err = getEngineMySQL(fallbackGetter)
return p, err
// TODO: add support for SQLite

View File

@ -0,0 +1,95 @@
package dbimpl
import (
"context"
"database/sql"
"database/sql/driver"
"sync"
)
var _ driver.Driver = driverWithoutIsolationLevel{}
var _ driver.Driver = driverWithIsolationLevel{}
const (
driverWithoutIsolationLevelName = "test driver without isolation levels"
driverWithIsolationLevelName = "test driver with isolation levels"
)
var registerTestDriversOnce sync.Once
func registerTestSQLDrivers() {
registerTestDriversOnce.Do(func() {
sql.Register(driverWithoutIsolationLevelName, driverWithoutIsolationLevel{})
sql.Register(driverWithIsolationLevelName, driverWithIsolationLevel{})
})
}
type (
// without isolation level
driverWithoutIsolationLevel struct{}
connWithoutIsolationLevel struct{}
// with isolation level
driverWithIsolationLevel struct{}
connWithIsolationLevel struct {
connWithoutIsolationLevel
}
// common
testStmt struct{}
testTx struct{}
testResults struct{}
testRows struct{}
)
// driver.Driver
func (driverWithoutIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithoutIsolationLevel{}, nil
}
func (driverWithIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithIsolationLevel{}, nil
}
// driver.Conn
func (connWithoutIsolationLevel) Prepare(query string) (driver.Stmt, error) {
return testStmt{}, nil
}
func (connWithoutIsolationLevel) Close() error {
return nil
}
func (connWithoutIsolationLevel) Begin() (driver.Tx, error) {
return testTx{}, nil
}
func (connWithIsolationLevel) BeginTx(context.Context, driver.TxOptions) (driver.Tx, error) {
return testTx{}, nil
}
// driver.Stmt
func (testStmt) Close() error { return nil }
func (testStmt) NumInput() int { return 0 }
func (testStmt) Exec(args []driver.Value) (driver.Result, error) { return testResults{}, nil }
func (testStmt) Query(args []driver.Value) (driver.Rows, error) { return testRows{}, nil }
// driver.Tx
func (testTx) Commit() error { return nil }
func (testTx) Rollback() error { return nil }
// driver.Results
func (testResults) LastInsertId() (int64, error) { return 1, nil }
func (testResults) RowsAffected() (int64, error) { return 1, nil }
// driver.Rows
func (testRows) Columns() []string { return nil }
func (testRows) Close() error { return nil }
func (testRows) Next(dest []driver.Value) error { return nil }

View File

@ -1,10 +1,7 @@
package dbimpl
import (
"context"
"database/sql"
"database/sql/driver"
"sync"
"testing"
"github.com/stretchr/testify/require"
@ -16,93 +13,6 @@ import (
const noIsolationLevelSupportErrStr = "sql: driver does not support non-" +
"default isolation level"
var _ driver.Driver = driverWithoutIsolationLevel{}
var _ driver.Driver = driverWithIsolationLevel{}
const (
driverWithoutIsolationLevelName = "test driver without isolation levels"
driverWithIsolationLevelName = "test driver with isolation levels"
)
var registerTestDriversOnce sync.Once
func registerTestSQLDrivers() {
registerTestDriversOnce.Do(func() {
sql.Register(driverWithoutIsolationLevelName, driverWithoutIsolationLevel{})
sql.Register(driverWithIsolationLevelName, driverWithIsolationLevel{})
})
}
type (
// without isolation level
driverWithoutIsolationLevel struct{}
connWithoutIsolationLevel struct{}
// with isolation level
driverWithIsolationLevel struct{}
connWithIsolationLevel struct {
connWithoutIsolationLevel
}
// common
testStmt struct{}
testTx struct{}
testResults struct{}
testRows struct{}
)
// driver.Driver
func (driverWithoutIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithoutIsolationLevel{}, nil
}
func (driverWithIsolationLevel) Open(name string) (driver.Conn, error) {
return connWithIsolationLevel{}, nil
}
// driver.Conn
func (connWithoutIsolationLevel) Prepare(query string) (driver.Stmt, error) {
return testStmt{}, nil
}
func (connWithoutIsolationLevel) Close() error {
return nil
}
func (connWithoutIsolationLevel) Begin() (driver.Tx, error) {
return testTx{}, nil
}
func (connWithIsolationLevel) BeginTx(context.Context, driver.TxOptions) (driver.Tx, error) {
return testTx{}, nil
}
// driver.Stmt
func (testStmt) Close() error { return nil }
func (testStmt) NumInput() int { return 0 }
func (testStmt) Exec(args []driver.Value) (driver.Result, error) { return testResults{}, nil }
func (testStmt) Query(args []driver.Value) (driver.Rows, error) { return testRows{}, nil }
// driver.Tx
func (testTx) Commit() error { return nil }
func (testTx) Rollback() error { return nil }
// driver.Results
func (testResults) LastInsertId() (int64, error) { return 1, nil }
func (testResults) RowsAffected() (int64, error) { return 1, nil }
// driver.Rows
func (testRows) Columns() []string { return nil }
func (testRows) Close() error { return nil }
func (testRows) Next(dest []driver.Value) error { return nil }
func TestReproIncident2144IndependentOfGrafanaDB(t *testing.T) {
t.Parallel()
registerTestSQLDrivers()

View File

@ -0,0 +1,482 @@
// Code generated by mockery v2.43.1. DO NOT EDIT.
package mocks
import (
context "context"
db "github.com/grafana/grafana/pkg/storage/unified/sql/db"
mock "github.com/stretchr/testify/mock"
sql "database/sql"
)
// DB is an autogenerated mock type for the DB type
type DB struct {
mock.Mock
}
type DB_Expecter struct {
mock *mock.Mock
}
func (_m *DB) EXPECT() *DB_Expecter {
return &DB_Expecter{mock: &_m.Mock}
}
// BeginTx provides a mock function with given fields: _a0, _a1
func (_m *DB) BeginTx(_a0 context.Context, _a1 *sql.TxOptions) (db.Tx, error) {
ret := _m.Called(_a0, _a1)
if len(ret) == 0 {
panic("no return value specified for BeginTx")
}
var r0 db.Tx
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *sql.TxOptions) (db.Tx, error)); ok {
return rf(_a0, _a1)
}
if rf, ok := ret.Get(0).(func(context.Context, *sql.TxOptions) db.Tx); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(db.Tx)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *sql.TxOptions) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DB_BeginTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BeginTx'
type DB_BeginTx_Call struct {
*mock.Call
}
// BeginTx is a helper method to define mock.On call
// - _a0 context.Context
// - _a1 *sql.TxOptions
func (_e *DB_Expecter) BeginTx(_a0 interface{}, _a1 interface{}) *DB_BeginTx_Call {
return &DB_BeginTx_Call{Call: _e.mock.On("BeginTx", _a0, _a1)}
}
func (_c *DB_BeginTx_Call) Run(run func(_a0 context.Context, _a1 *sql.TxOptions)) *DB_BeginTx_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*sql.TxOptions))
})
return _c
}
func (_c *DB_BeginTx_Call) Return(_a0 db.Tx, _a1 error) *DB_BeginTx_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *DB_BeginTx_Call) RunAndReturn(run func(context.Context, *sql.TxOptions) (db.Tx, error)) *DB_BeginTx_Call {
_c.Call.Return(run)
return _c
}
// DriverName provides a mock function with given fields:
func (_m *DB) DriverName() string {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for DriverName")
}
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// DB_DriverName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DriverName'
type DB_DriverName_Call struct {
*mock.Call
}
// DriverName is a helper method to define mock.On call
func (_e *DB_Expecter) DriverName() *DB_DriverName_Call {
return &DB_DriverName_Call{Call: _e.mock.On("DriverName")}
}
func (_c *DB_DriverName_Call) Run(run func()) *DB_DriverName_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *DB_DriverName_Call) Return(_a0 string) *DB_DriverName_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *DB_DriverName_Call) RunAndReturn(run func() string) *DB_DriverName_Call {
_c.Call.Return(run)
return _c
}
// ExecContext provides a mock function with given fields: ctx, query, args
func (_m *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ExecContext")
}
var r0 sql.Result
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (sql.Result, error)); ok {
return rf(ctx, query, args...)
}
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) sql.Result); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(sql.Result)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok {
r1 = rf(ctx, query, args...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DB_ExecContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExecContext'
type DB_ExecContext_Call struct {
*mock.Call
}
// ExecContext is a helper method to define mock.On call
// - ctx context.Context
// - query string
// - args ...interface{}
func (_e *DB_Expecter) ExecContext(ctx interface{}, query interface{}, args ...interface{}) *DB_ExecContext_Call {
return &DB_ExecContext_Call{Call: _e.mock.On("ExecContext",
append([]interface{}{ctx, query}, args...)...)}
}
func (_c *DB_ExecContext_Call) Run(run func(ctx context.Context, query string, args ...interface{})) *DB_ExecContext_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(context.Context), args[1].(string), variadicArgs...)
})
return _c
}
func (_c *DB_ExecContext_Call) Return(_a0 sql.Result, _a1 error) *DB_ExecContext_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *DB_ExecContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (sql.Result, error)) *DB_ExecContext_Call {
_c.Call.Return(run)
return _c
}
// PingContext provides a mock function with given fields: _a0
func (_m *DB) PingContext(_a0 context.Context) error {
ret := _m.Called(_a0)
if len(ret) == 0 {
panic("no return value specified for PingContext")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// DB_PingContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PingContext'
type DB_PingContext_Call struct {
*mock.Call
}
// PingContext is a helper method to define mock.On call
// - _a0 context.Context
func (_e *DB_Expecter) PingContext(_a0 interface{}) *DB_PingContext_Call {
return &DB_PingContext_Call{Call: _e.mock.On("PingContext", _a0)}
}
func (_c *DB_PingContext_Call) Run(run func(_a0 context.Context)) *DB_PingContext_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context))
})
return _c
}
func (_c *DB_PingContext_Call) Return(_a0 error) *DB_PingContext_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *DB_PingContext_Call) RunAndReturn(run func(context.Context) error) *DB_PingContext_Call {
_c.Call.Return(run)
return _c
}
// QueryContext provides a mock function with given fields: ctx, query, args
func (_m *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for QueryContext")
}
var r0 *sql.Rows
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (*sql.Rows, error)); ok {
return rf(ctx, query, args...)
}
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Rows); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Rows)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok {
r1 = rf(ctx, query, args...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DB_QueryContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryContext'
type DB_QueryContext_Call struct {
*mock.Call
}
// QueryContext is a helper method to define mock.On call
// - ctx context.Context
// - query string
// - args ...interface{}
func (_e *DB_Expecter) QueryContext(ctx interface{}, query interface{}, args ...interface{}) *DB_QueryContext_Call {
return &DB_QueryContext_Call{Call: _e.mock.On("QueryContext",
append([]interface{}{ctx, query}, args...)...)}
}
func (_c *DB_QueryContext_Call) Run(run func(ctx context.Context, query string, args ...interface{})) *DB_QueryContext_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(context.Context), args[1].(string), variadicArgs...)
})
return _c
}
func (_c *DB_QueryContext_Call) Return(_a0 *sql.Rows, _a1 error) *DB_QueryContext_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *DB_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (*sql.Rows, error)) *DB_QueryContext_Call {
_c.Call.Return(run)
return _c
}
// QueryRowContext provides a mock function with given fields: ctx, query, args
func (_m *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for QueryRowContext")
}
var r0 *sql.Row
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Row); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Row)
}
}
return r0
}
// DB_QueryRowContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryRowContext'
type DB_QueryRowContext_Call struct {
*mock.Call
}
// QueryRowContext is a helper method to define mock.On call
// - ctx context.Context
// - query string
// - args ...interface{}
func (_e *DB_Expecter) QueryRowContext(ctx interface{}, query interface{}, args ...interface{}) *DB_QueryRowContext_Call {
return &DB_QueryRowContext_Call{Call: _e.mock.On("QueryRowContext",
append([]interface{}{ctx, query}, args...)...)}
}
func (_c *DB_QueryRowContext_Call) Run(run func(ctx context.Context, query string, args ...interface{})) *DB_QueryRowContext_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(context.Context), args[1].(string), variadicArgs...)
})
return _c
}
func (_c *DB_QueryRowContext_Call) Return(_a0 *sql.Row) *DB_QueryRowContext_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *DB_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) *sql.Row) *DB_QueryRowContext_Call {
_c.Call.Return(run)
return _c
}
// Stats provides a mock function with given fields:
func (_m *DB) Stats() sql.DBStats {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Stats")
}
var r0 sql.DBStats
if rf, ok := ret.Get(0).(func() sql.DBStats); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(sql.DBStats)
}
return r0
}
// DB_Stats_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stats'
type DB_Stats_Call struct {
*mock.Call
}
// Stats is a helper method to define mock.On call
func (_e *DB_Expecter) Stats() *DB_Stats_Call {
return &DB_Stats_Call{Call: _e.mock.On("Stats")}
}
func (_c *DB_Stats_Call) Run(run func()) *DB_Stats_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *DB_Stats_Call) Return(_a0 sql.DBStats) *DB_Stats_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *DB_Stats_Call) RunAndReturn(run func() sql.DBStats) *DB_Stats_Call {
_c.Call.Return(run)
return _c
}
// WithTx provides a mock function with given fields: _a0, _a1, _a2
func (_m *DB) WithTx(_a0 context.Context, _a1 *sql.TxOptions, _a2 func(context.Context, db.Tx) error) error {
ret := _m.Called(_a0, _a1, _a2)
if len(ret) == 0 {
panic("no return value specified for WithTx")
}
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, *sql.TxOptions, func(context.Context, db.Tx) error) error); ok {
r0 = rf(_a0, _a1, _a2)
} else {
r0 = ret.Error(0)
}
return r0
}
// DB_WithTx_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WithTx'
type DB_WithTx_Call struct {
*mock.Call
}
// WithTx is a helper method to define mock.On call
// - _a0 context.Context
// - _a1 *sql.TxOptions
// - _a2 func(context.Context , db.Tx) error
func (_e *DB_Expecter) WithTx(_a0 interface{}, _a1 interface{}, _a2 interface{}) *DB_WithTx_Call {
return &DB_WithTx_Call{Call: _e.mock.On("WithTx", _a0, _a1, _a2)}
}
func (_c *DB_WithTx_Call) Run(run func(_a0 context.Context, _a1 *sql.TxOptions, _a2 func(context.Context, db.Tx) error)) *DB_WithTx_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*sql.TxOptions), args[2].(func(context.Context, db.Tx) error))
})
return _c
}
func (_c *DB_WithTx_Call) Return(_a0 error) *DB_WithTx_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *DB_WithTx_Call) RunAndReturn(run func(context.Context, *sql.TxOptions, func(context.Context, db.Tx) error) error) *DB_WithTx_Call {
_c.Call.Return(run)
return _c
}
// NewDB creates a new instance of DB. 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 NewDB(t interface {
mock.TestingT
Cleanup(func())
}) *DB {
mock := &DB{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -0,0 +1,328 @@
// Code generated by mockery v2.43.1. DO NOT EDIT.
package mocks
import (
context "context"
mock "github.com/stretchr/testify/mock"
sql "database/sql"
)
// Tx is an autogenerated mock type for the Tx type
type Tx struct {
mock.Mock
}
type Tx_Expecter struct {
mock *mock.Mock
}
func (_m *Tx) EXPECT() *Tx_Expecter {
return &Tx_Expecter{mock: &_m.Mock}
}
// Commit provides a mock function with given fields:
func (_m *Tx) Commit() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Commit")
}
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Tx_Commit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Commit'
type Tx_Commit_Call struct {
*mock.Call
}
// Commit is a helper method to define mock.On call
func (_e *Tx_Expecter) Commit() *Tx_Commit_Call {
return &Tx_Commit_Call{Call: _e.mock.On("Commit")}
}
func (_c *Tx_Commit_Call) Run(run func()) *Tx_Commit_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Tx_Commit_Call) Return(_a0 error) *Tx_Commit_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Tx_Commit_Call) RunAndReturn(run func() error) *Tx_Commit_Call {
_c.Call.Return(run)
return _c
}
// ExecContext provides a mock function with given fields: ctx, query, args
func (_m *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for ExecContext")
}
var r0 sql.Result
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (sql.Result, error)); ok {
return rf(ctx, query, args...)
}
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) sql.Result); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(sql.Result)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok {
r1 = rf(ctx, query, args...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Tx_ExecContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExecContext'
type Tx_ExecContext_Call struct {
*mock.Call
}
// ExecContext is a helper method to define mock.On call
// - ctx context.Context
// - query string
// - args ...interface{}
func (_e *Tx_Expecter) ExecContext(ctx interface{}, query interface{}, args ...interface{}) *Tx_ExecContext_Call {
return &Tx_ExecContext_Call{Call: _e.mock.On("ExecContext",
append([]interface{}{ctx, query}, args...)...)}
}
func (_c *Tx_ExecContext_Call) Run(run func(ctx context.Context, query string, args ...interface{})) *Tx_ExecContext_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(context.Context), args[1].(string), variadicArgs...)
})
return _c
}
func (_c *Tx_ExecContext_Call) Return(_a0 sql.Result, _a1 error) *Tx_ExecContext_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *Tx_ExecContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (sql.Result, error)) *Tx_ExecContext_Call {
_c.Call.Return(run)
return _c
}
// QueryContext provides a mock function with given fields: ctx, query, args
func (_m *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for QueryContext")
}
var r0 *sql.Rows
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) (*sql.Rows, error)); ok {
return rf(ctx, query, args...)
}
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Rows); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Rows)
}
}
if rf, ok := ret.Get(1).(func(context.Context, string, ...interface{}) error); ok {
r1 = rf(ctx, query, args...)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Tx_QueryContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryContext'
type Tx_QueryContext_Call struct {
*mock.Call
}
// QueryContext is a helper method to define mock.On call
// - ctx context.Context
// - query string
// - args ...interface{}
func (_e *Tx_Expecter) QueryContext(ctx interface{}, query interface{}, args ...interface{}) *Tx_QueryContext_Call {
return &Tx_QueryContext_Call{Call: _e.mock.On("QueryContext",
append([]interface{}{ctx, query}, args...)...)}
}
func (_c *Tx_QueryContext_Call) Run(run func(ctx context.Context, query string, args ...interface{})) *Tx_QueryContext_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(context.Context), args[1].(string), variadicArgs...)
})
return _c
}
func (_c *Tx_QueryContext_Call) Return(_a0 *sql.Rows, _a1 error) *Tx_QueryContext_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *Tx_QueryContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) (*sql.Rows, error)) *Tx_QueryContext_Call {
_c.Call.Return(run)
return _c
}
// QueryRowContext provides a mock function with given fields: ctx, query, args
func (_m *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
var _ca []interface{}
_ca = append(_ca, ctx, query)
_ca = append(_ca, args...)
ret := _m.Called(_ca...)
if len(ret) == 0 {
panic("no return value specified for QueryRowContext")
}
var r0 *sql.Row
if rf, ok := ret.Get(0).(func(context.Context, string, ...interface{}) *sql.Row); ok {
r0 = rf(ctx, query, args...)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*sql.Row)
}
}
return r0
}
// Tx_QueryRowContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryRowContext'
type Tx_QueryRowContext_Call struct {
*mock.Call
}
// QueryRowContext is a helper method to define mock.On call
// - ctx context.Context
// - query string
// - args ...interface{}
func (_e *Tx_Expecter) QueryRowContext(ctx interface{}, query interface{}, args ...interface{}) *Tx_QueryRowContext_Call {
return &Tx_QueryRowContext_Call{Call: _e.mock.On("QueryRowContext",
append([]interface{}{ctx, query}, args...)...)}
}
func (_c *Tx_QueryRowContext_Call) Run(run func(ctx context.Context, query string, args ...interface{})) *Tx_QueryRowContext_Call {
_c.Call.Run(func(args mock.Arguments) {
variadicArgs := make([]interface{}, len(args)-2)
for i, a := range args[2:] {
if a != nil {
variadicArgs[i] = a.(interface{})
}
}
run(args[0].(context.Context), args[1].(string), variadicArgs...)
})
return _c
}
func (_c *Tx_QueryRowContext_Call) Return(_a0 *sql.Row) *Tx_QueryRowContext_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Tx_QueryRowContext_Call) RunAndReturn(run func(context.Context, string, ...interface{}) *sql.Row) *Tx_QueryRowContext_Call {
_c.Call.Return(run)
return _c
}
// Rollback provides a mock function with given fields:
func (_m *Tx) Rollback() error {
ret := _m.Called()
if len(ret) == 0 {
panic("no return value specified for Rollback")
}
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
r0 = ret.Error(0)
}
return r0
}
// Tx_Rollback_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Rollback'
type Tx_Rollback_Call struct {
*mock.Call
}
// Rollback is a helper method to define mock.On call
func (_e *Tx_Expecter) Rollback() *Tx_Rollback_Call {
return &Tx_Rollback_Call{Call: _e.mock.On("Rollback")}
}
func (_c *Tx_Rollback_Call) Run(run func()) *Tx_Rollback_Call {
_c.Call.Run(func(args mock.Arguments) {
run()
})
return _c
}
func (_c *Tx_Rollback_Call) Return(_a0 error) *Tx_Rollback_Call {
_c.Call.Return(_a0)
return _c
}
func (_c *Tx_Rollback_Call) RunAndReturn(run func() error) *Tx_Rollback_Call {
_c.Call.Return(run)
return _c
}
// NewTx creates a new instance of Tx. 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 NewTx(t interface {
mock.TestingT
Cleanup(func())
}) *Tx {
mock := &Tx{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@ -5,6 +5,9 @@ import (
"database/sql"
)
//go:generate mockery --with-expecter --name DB
//go:generate mockery --with-expecter --name Tx
const (
DriverPostgres = "postgres"
DriverMySQL = "mysql"