From bff5b81ad952f5a3068fae9daa2d64ec2f8bed15 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Wed, 17 May 2023 22:15:24 +0800 Subject: [PATCH 01/15] feat: support using session to execute statements in transaction (#3252) --- .gitignore | 4 +- core/stores/sqlc/cachedsql.go | 12 ++ core/stores/sqlc/cachedsql_test.go | 164 ++++++++++++++++-- core/stores/sqlx/bulkinserter_test.go | 24 +-- core/stores/sqlx/errors.go | 14 ++ core/stores/sqlx/orm_test.go | 136 +++++++-------- core/stores/sqlx/sqlconn.go | 10 +- core/stores/sqlx/sqlconn_test.go | 2 +- core/stores/sqlx/tx.go | 16 ++ core/stores/sqlx/tx_test.go | 233 ++++++++++++++++++++++++-- internal/dbtest/sql.go | 37 ++++ 11 files changed, 526 insertions(+), 126 deletions(-) create mode 100644 core/stores/sqlx/errors.go create mode 100644 internal/dbtest/sql.go diff --git a/.gitignore b/.gitignore index b38171f7d059..c306dab2374c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,10 @@ **/.idea **/.DS_Store **/logs +**/adhoc +**/coverage.txt # for test purpose -**/adhoc go.work go.work.sum @@ -27,4 +28,3 @@ go.work.sum # vim auto backup file *~ !OWNERS -coverage.txt diff --git a/core/stores/sqlc/cachedsql.go b/core/stores/sqlc/cachedsql.go index 52e5ee04f056..276926361105 100644 --- a/core/stores/sqlc/cachedsql.go +++ b/core/stores/sqlc/cachedsql.go @@ -226,3 +226,15 @@ func (cc CachedConn) Transact(fn func(sqlx.Session) error) error { func (cc CachedConn) TransactCtx(ctx context.Context, fn func(context.Context, sqlx.Session) error) error { return cc.db.TransactCtx(ctx, fn) } + +// WithSession returns a new CachedConn with given session. +// If query from session, the uncommitted data might be returned. +// Don't query for the uncommitted data, you should just use it, +// and don't use the cache for the uncommitted data. +// Not recommend to use cache within transactions due to consistency problem. +func (cc CachedConn) WithSession(session sqlx.Session) CachedConn { + return CachedConn{ + db: sqlx.NewSqlConnFromSession(session), + cache: cc.cache, + } +} diff --git a/core/stores/sqlc/cachedsql_test.go b/core/stores/sqlc/cachedsql_test.go index 5e97af26c5ed..064199cb9d88 100644 --- a/core/stores/sqlc/cachedsql_test.go +++ b/core/stores/sqlc/cachedsql_test.go @@ -15,6 +15,7 @@ import ( "testing" "time" + "github.com/DATA-DOG/go-sqlmock" "github.com/alicebob/miniredis/v2" "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/fx" @@ -24,6 +25,8 @@ import ( "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis/redistest" "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/syncx" + "github.com/zeromicro/go-zero/internal/dbtest" ) func init() { @@ -39,7 +42,7 @@ func TestCachedConn_GetCache(t *testing.T) { var value string err := c.GetCache("any", &value) assert.Equal(t, ErrNotFound, err) - r.Set("any", `"value"`) + _ = r.Set("any", `"value"`) err = c.GetCache("any", &value) assert.Nil(t, err) assert.Equal(t, "value", value) @@ -368,6 +371,24 @@ func TestStatFromMemory(t *testing.T) { assert.Equal(t, uint64(9), atomic.LoadUint64(&stats.Hit)) } +func TestCachedConn_DelCache(t *testing.T) { + r := redistest.CreateRedis(t) + + const ( + key = "user" + value = "any" + ) + assert.NoError(t, r.Set(key, value)) + + c := NewNodeConn(&trackedConn{}, r, cache.WithExpiry(time.Second*30)) + err := c.DelCache(key) + assert.Nil(t, err) + + val, err := r.Get(key) + assert.Nil(t, err) + assert.Empty(t, val) +} + func TestCachedConnQueryRow(t *testing.T) { r := redistest.CreateRedis(t) @@ -543,6 +564,125 @@ func TestNewConnWithCache(t *testing.T) { assert.True(t, conn.execValue) } +func TestCachedConn_WithSession(t *testing.T) { + dbtest.RunTxTest(t, func(tx *sql.Tx, mock sqlmock.Sqlmock) { + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + + r := redistest.CreateRedis(t) + conn := CachedConn{ + cache: cache.NewNode(r, syncx.NewSingleFlight(), stats, sql.ErrNoRows), + } + conn = conn.WithSession(sqlx.NewSessionFromTx(tx)) + res, err := conn.Exec(func(conn sqlx.SqlConn) (sql.Result, error) { + return conn.Exec("any") + }, "foo") + assert.NoError(t, err) + last, err := res.LastInsertId() + assert.NoError(t, err) + assert.Equal(t, int64(2), last) + affected, err := res.RowsAffected() + assert.NoError(t, err) + assert.Equal(t, int64(3), affected) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + mock.ExpectCommit() + + r := redistest.CreateRedis(t) + conn := CachedConn{ + db: sqlx.NewSqlConnFromDB(db), + cache: cache.NewNode(r, syncx.NewSingleFlight(), stats, sql.ErrNoRows), + } + assert.NoError(t, conn.Transact(func(session sqlx.Session) error { + conn = conn.WithSession(session) + res, err := conn.Exec(func(conn sqlx.SqlConn) (sql.Result, error) { + return conn.Exec("any") + }, "foo") + assert.NoError(t, err) + last, err := res.LastInsertId() + assert.NoError(t, err) + assert.Equal(t, int64(2), last) + affected, err := res.RowsAffected() + assert.NoError(t, err) + assert.Equal(t, int64(3), affected) + return nil + })) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectExec("any").WillReturnError(errors.New("foo")) + mock.ExpectRollback() + + r := redistest.CreateRedis(t) + conn := CachedConn{ + db: sqlx.NewSqlConnFromDB(db), + cache: cache.NewNode(r, syncx.NewSingleFlight(), stats, sql.ErrNoRows), + } + assert.Error(t, conn.Transact(func(session sqlx.Session) error { + conn = conn.WithSession(session) + _, err := conn.Exec(func(conn sqlx.SqlConn) (sql.Result, error) { + return conn.Exec("any") + }, "bar") + return err + })) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectQuery("any").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(2)) + mock.ExpectCommit() + + r := redistest.CreateRedis(t) + conn := CachedConn{ + db: sqlx.NewSqlConnFromDB(db), + cache: cache.NewNode(r, syncx.NewSingleFlight(), stats, sql.ErrNoRows), + } + assert.NoError(t, conn.Transact(func(session sqlx.Session) error { + var val string + conn = conn.WithSession(session) + err := conn.QueryRow(&val, "foo", func(conn sqlx.SqlConn, v interface{}) error { + return conn.QueryRow(v, "any") + }) + assert.Equal(t, "2", val) + return err + })) + val, err := r.Get("foo") + assert.NoError(t, err) + assert.Equal(t, `"2"`, val) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectQuery("any").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(2)) + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + mock.ExpectCommit() + + r := redistest.CreateRedis(t) + conn := CachedConn{ + db: sqlx.NewSqlConnFromDB(db), + cache: cache.NewNode(r, syncx.NewSingleFlight(), stats, sql.ErrNoRows), + } + assert.NoError(t, conn.Transact(func(session sqlx.Session) error { + var val string + conn = conn.WithSession(session) + assert.NoError(t, conn.QueryRow(&val, "foo", func(conn sqlx.SqlConn, v interface{}) error { + return conn.QueryRow(v, "any") + })) + assert.Equal(t, "2", val) + _, err := conn.Exec(func(conn sqlx.SqlConn) (sql.Result, error) { + return conn.Exec("any") + }, "foo") + return err + })) + val, err := r.Get("foo") + assert.NoError(t, err) + assert.Empty(t, val) + }) +} + func resetStats() { atomic.StoreUint64(&stats.Total, 0) atomic.StoreUint64(&stats.Hit, 0) @@ -554,35 +694,35 @@ type dummySqlConn struct { queryRow func(any, string, ...any) error } -func (d dummySqlConn) ExecCtx(ctx context.Context, query string, args ...any) (sql.Result, error) { +func (d dummySqlConn) ExecCtx(_ context.Context, _ string, _ ...any) (sql.Result, error) { return nil, nil } -func (d dummySqlConn) PrepareCtx(ctx context.Context, query string) (sqlx.StmtSession, error) { +func (d dummySqlConn) PrepareCtx(_ context.Context, _ string) (sqlx.StmtSession, error) { return nil, nil } -func (d dummySqlConn) QueryRowPartialCtx(ctx context.Context, v any, query string, args ...any) error { +func (d dummySqlConn) QueryRowPartialCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } -func (d dummySqlConn) QueryRowsCtx(ctx context.Context, v any, query string, args ...any) error { +func (d dummySqlConn) QueryRowsCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } -func (d dummySqlConn) QueryRowsPartialCtx(ctx context.Context, v any, query string, args ...any) error { +func (d dummySqlConn) QueryRowsPartialCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } -func (d dummySqlConn) TransactCtx(ctx context.Context, fn func(context.Context, sqlx.Session) error) error { +func (d dummySqlConn) TransactCtx(_ context.Context, _ func(context.Context, sqlx.Session) error) error { return nil } -func (d dummySqlConn) Exec(query string, args ...any) (sql.Result, error) { +func (d dummySqlConn) Exec(_ string, _ ...any) (sql.Result, error) { return nil, nil } -func (d dummySqlConn) Prepare(query string) (sqlx.StmtSession, error) { +func (d dummySqlConn) Prepare(_ string) (sqlx.StmtSession, error) { return nil, nil } @@ -597,15 +737,15 @@ func (d dummySqlConn) QueryRowCtx(_ context.Context, v any, query string, args . return nil } -func (d dummySqlConn) QueryRowPartial(v any, query string, args ...any) error { +func (d dummySqlConn) QueryRowPartial(_ any, _ string, _ ...any) error { return nil } -func (d dummySqlConn) QueryRows(v any, query string, args ...any) error { +func (d dummySqlConn) QueryRows(_ any, _ string, _ ...any) error { return nil } -func (d dummySqlConn) QueryRowsPartial(v any, query string, args ...any) error { +func (d dummySqlConn) QueryRowsPartial(_ any, _ string, _ ...any) error { return nil } diff --git a/core/stores/sqlx/bulkinserter_test.go b/core/stores/sqlx/bulkinserter_test.go index 523482520b92..ae4bca1bcc44 100644 --- a/core/stores/sqlx/bulkinserter_test.go +++ b/core/stores/sqlx/bulkinserter_test.go @@ -9,7 +9,7 @@ import ( "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" - "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/internal/dbtest" ) type mockedConn struct { @@ -81,7 +81,7 @@ func (c *mockedConn) Transact(func(session Session) error) error { } func TestBulkInserter(t *testing.T) { - runSqlTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { var conn mockedConn inserter, err := NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES(?, ?, ?)`) assert.Nil(t, err) @@ -98,7 +98,7 @@ func TestBulkInserter(t *testing.T) { } func TestBulkInserterSuffix(t *testing.T) { - runSqlTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { var conn mockedConn inserter, err := NewBulkInserter(&conn, `INSERT INTO classroom_dau(classroom, user, count) VALUES`+ `(?, ?, ?) ON DUPLICATE KEY UPDATE is_overtime=VALUES(is_overtime)`) @@ -119,7 +119,7 @@ func TestBulkInserterSuffix(t *testing.T) { } func TestBulkInserterBadStatement(t *testing.T) { - runSqlTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { var conn mockedConn _, err := NewBulkInserter(&conn, "foo") assert.NotNil(t, err) @@ -144,19 +144,3 @@ func TestBulkInserter_Update(t *testing.T) { assert.NotNil(t, inserter.UpdateStmt("foo")) assert.NotNil(t, inserter.Insert("foo", "bar")) } - -func runSqlTest(t *testing.T, fn func(db *sql.DB, mock sqlmock.Sqlmock)) { - logx.Disable() - - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - defer db.Close() - - fn(db, mock) - - if err := mock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } -} diff --git a/core/stores/sqlx/errors.go b/core/stores/sqlx/errors.go new file mode 100644 index 000000000000..efe0b159d3f2 --- /dev/null +++ b/core/stores/sqlx/errors.go @@ -0,0 +1,14 @@ +package sqlx + +import ( + "database/sql" + "errors" +) + +var ( + // ErrNotFound is an alias of sql.ErrNoRows + ErrNotFound = sql.ErrNoRows + + errCantNestTx = errors.New("cannot nest transactions") + errNoRawDBFromTx = errors.New("cannot get raw db from transaction") +) diff --git a/core/stores/sqlx/orm_test.go b/core/stores/sqlx/orm_test.go index 2efd04d6dc8d..4aab1bbac06c 100644 --- a/core/stores/sqlx/orm_test.go +++ b/core/stores/sqlx/orm_test.go @@ -8,11 +8,11 @@ import ( "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" - "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/internal/dbtest" ) func TestUnmarshalRowBool(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("1") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -25,7 +25,7 @@ func TestUnmarshalRowBool(t *testing.T) { } func TestUnmarshalRowBoolNotSettable(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("1") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -37,7 +37,7 @@ func TestUnmarshalRowBoolNotSettable(t *testing.T) { } func TestUnmarshalRowInt(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -50,7 +50,7 @@ func TestUnmarshalRowInt(t *testing.T) { } func TestUnmarshalRowInt8(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -63,7 +63,7 @@ func TestUnmarshalRowInt8(t *testing.T) { } func TestUnmarshalRowInt16(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("4") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -76,7 +76,7 @@ func TestUnmarshalRowInt16(t *testing.T) { } func TestUnmarshalRowInt32(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("5") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -89,7 +89,7 @@ func TestUnmarshalRowInt32(t *testing.T) { } func TestUnmarshalRowInt64(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("6") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -102,7 +102,7 @@ func TestUnmarshalRowInt64(t *testing.T) { } func TestUnmarshalRowUint(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -115,7 +115,7 @@ func TestUnmarshalRowUint(t *testing.T) { } func TestUnmarshalRowUint8(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -128,7 +128,7 @@ func TestUnmarshalRowUint8(t *testing.T) { } func TestUnmarshalRowUint16(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("4") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -141,7 +141,7 @@ func TestUnmarshalRowUint16(t *testing.T) { } func TestUnmarshalRowUint32(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("5") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -154,7 +154,7 @@ func TestUnmarshalRowUint32(t *testing.T) { } func TestUnmarshalRowUint64(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("6") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -167,7 +167,7 @@ func TestUnmarshalRowUint64(t *testing.T) { } func TestUnmarshalRowFloat32(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("7") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -180,7 +180,7 @@ func TestUnmarshalRowFloat32(t *testing.T) { } func TestUnmarshalRowFloat64(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"value"}).FromCSVString("8") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -193,7 +193,7 @@ func TestUnmarshalRowFloat64(t *testing.T) { } func TestUnmarshalRowString(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { const expect = "hello" rs := sqlmock.NewRows([]string{"value"}).FromCSVString(expect) mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -212,7 +212,7 @@ func TestUnmarshalRowStruct(t *testing.T) { Age int }) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("liao,5") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -230,7 +230,7 @@ func TestUnmarshalRowStructWithTags(t *testing.T) { Name string `db:"name"` }) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("liao,5") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -248,7 +248,7 @@ func TestUnmarshalRowStructWithTagsWrongColumns(t *testing.T) { Name string `db:"name"` }) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name"}).FromCSVString("liao") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -259,7 +259,7 @@ func TestUnmarshalRowStructWithTagsWrongColumns(t *testing.T) { } func TestUnmarshalRowsBool(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []bool{true, false} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("1\n0") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -273,7 +273,7 @@ func TestUnmarshalRowsBool(t *testing.T) { } func TestUnmarshalRowsInt(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []int{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -287,7 +287,7 @@ func TestUnmarshalRowsInt(t *testing.T) { } func TestUnmarshalRowsInt8(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []int8{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -301,7 +301,7 @@ func TestUnmarshalRowsInt8(t *testing.T) { } func TestUnmarshalRowsInt16(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []int16{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -315,7 +315,7 @@ func TestUnmarshalRowsInt16(t *testing.T) { } func TestUnmarshalRowsInt32(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []int32{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -329,7 +329,7 @@ func TestUnmarshalRowsInt32(t *testing.T) { } func TestUnmarshalRowsInt64(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []int64{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -343,7 +343,7 @@ func TestUnmarshalRowsInt64(t *testing.T) { } func TestUnmarshalRowsUint(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []uint{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -357,7 +357,7 @@ func TestUnmarshalRowsUint(t *testing.T) { } func TestUnmarshalRowsUint8(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []uint8{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -371,7 +371,7 @@ func TestUnmarshalRowsUint8(t *testing.T) { } func TestUnmarshalRowsUint16(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []uint16{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -385,7 +385,7 @@ func TestUnmarshalRowsUint16(t *testing.T) { } func TestUnmarshalRowsUint32(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []uint32{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -399,7 +399,7 @@ func TestUnmarshalRowsUint32(t *testing.T) { } func TestUnmarshalRowsUint64(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []uint64{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -413,7 +413,7 @@ func TestUnmarshalRowsUint64(t *testing.T) { } func TestUnmarshalRowsFloat32(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []float32{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -427,7 +427,7 @@ func TestUnmarshalRowsFloat32(t *testing.T) { } func TestUnmarshalRowsFloat64(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []float64{2, 3} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -441,7 +441,7 @@ func TestUnmarshalRowsFloat64(t *testing.T) { } func TestUnmarshalRowsString(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []string{"hello", "world"} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("hello\nworld") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -457,7 +457,7 @@ func TestUnmarshalRowsString(t *testing.T) { func TestUnmarshalRowsBoolPtr(t *testing.T) { yes := true no := false - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*bool{&yes, &no} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("1\n0") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -473,7 +473,7 @@ func TestUnmarshalRowsBoolPtr(t *testing.T) { func TestUnmarshalRowsIntPtr(t *testing.T) { two := 2 three := 3 - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*int{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -489,7 +489,7 @@ func TestUnmarshalRowsIntPtr(t *testing.T) { func TestUnmarshalRowsInt8Ptr(t *testing.T) { two := int8(2) three := int8(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*int8{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -505,7 +505,7 @@ func TestUnmarshalRowsInt8Ptr(t *testing.T) { func TestUnmarshalRowsInt16Ptr(t *testing.T) { two := int16(2) three := int16(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*int16{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -521,7 +521,7 @@ func TestUnmarshalRowsInt16Ptr(t *testing.T) { func TestUnmarshalRowsInt32Ptr(t *testing.T) { two := int32(2) three := int32(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*int32{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -537,7 +537,7 @@ func TestUnmarshalRowsInt32Ptr(t *testing.T) { func TestUnmarshalRowsInt64Ptr(t *testing.T) { two := int64(2) three := int64(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*int64{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -553,7 +553,7 @@ func TestUnmarshalRowsInt64Ptr(t *testing.T) { func TestUnmarshalRowsUintPtr(t *testing.T) { two := uint(2) three := uint(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*uint{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -569,7 +569,7 @@ func TestUnmarshalRowsUintPtr(t *testing.T) { func TestUnmarshalRowsUint8Ptr(t *testing.T) { two := uint8(2) three := uint8(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*uint8{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -585,7 +585,7 @@ func TestUnmarshalRowsUint8Ptr(t *testing.T) { func TestUnmarshalRowsUint16Ptr(t *testing.T) { two := uint16(2) three := uint16(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*uint16{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -601,7 +601,7 @@ func TestUnmarshalRowsUint16Ptr(t *testing.T) { func TestUnmarshalRowsUint32Ptr(t *testing.T) { two := uint32(2) three := uint32(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*uint32{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -617,7 +617,7 @@ func TestUnmarshalRowsUint32Ptr(t *testing.T) { func TestUnmarshalRowsUint64Ptr(t *testing.T) { two := uint64(2) three := uint64(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*uint64{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -633,7 +633,7 @@ func TestUnmarshalRowsUint64Ptr(t *testing.T) { func TestUnmarshalRowsFloat32Ptr(t *testing.T) { two := float32(2) three := float32(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*float32{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -649,7 +649,7 @@ func TestUnmarshalRowsFloat32Ptr(t *testing.T) { func TestUnmarshalRowsFloat64Ptr(t *testing.T) { two := float64(2) three := float64(3) - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*float64{&two, &three} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("2\n3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -665,7 +665,7 @@ func TestUnmarshalRowsFloat64Ptr(t *testing.T) { func TestUnmarshalRowsStringPtr(t *testing.T) { hello := "hello" world := "world" - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { expect := []*string{&hello, &world} rs := sqlmock.NewRows([]string{"value"}).FromCSVString("hello\nworld") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -697,7 +697,7 @@ func TestUnmarshalRowsStruct(t *testing.T) { Age int64 } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -736,7 +736,7 @@ func TestUnmarshalRowsStructWithNullStringType(t *testing.T) { NullString sql.NullString `db:"value"` } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "value"}).AddRow( "first", "firstnullstring").AddRow("second", nil) mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -771,7 +771,7 @@ func TestUnmarshalRowsStructWithTags(t *testing.T) { Name string `db:"name"` } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -812,7 +812,7 @@ func TestUnmarshalRowsStructAndEmbeddedAnonymousStructWithTags(t *testing.T) { Embed } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age", "value"}).FromCSVString("first,2,3\nsecond,3,4") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -854,7 +854,7 @@ func TestUnmarshalRowsStructAndEmbeddedStructPtrAnonymousWithTags(t *testing.T) *Embed } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age", "value"}).FromCSVString("first,2,3\nsecond,3,4") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -888,7 +888,7 @@ func TestUnmarshalRowsStructPtr(t *testing.T) { Age int64 } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -921,7 +921,7 @@ func TestUnmarshalRowsStructWithTagsPtr(t *testing.T) { Name string `db:"name"` } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -954,7 +954,7 @@ func TestUnmarshalRowsStructWithTagsPtrWithInnerPtr(t *testing.T) { Name string `db:"name"` } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"name", "age"}).FromCSVString("first,2\nsecond,3") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) assert.Nil(t, query(context.Background(), db, func(rows *sql.Rows) error { @@ -969,7 +969,7 @@ func TestUnmarshalRowsStructWithTagsPtrWithInnerPtr(t *testing.T) { } func TestCommonSqlConn_QueryRowOptional(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"age"}).FromCSVString("5") mock.ExpectQuery("select (.+) from users where user=?").WithArgs("anyone").WillReturnRows(rs) @@ -1019,7 +1019,7 @@ func TestUnmarshalRowError(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{"age"}).FromCSVString("5") mock.ExpectQuery("select (.+) from users where user=?").WithArgs( "anyone").WillReturnRows(rs) @@ -1091,7 +1091,7 @@ func TestAnonymousStructPr(t *testing.T) { Name string `db:"name"` } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{ "name", "age", @@ -1139,7 +1139,7 @@ func TestAnonymousStructPrError(t *testing.T) { Name string `db:"name"` } - runOrmTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { rs := sqlmock.NewRows([]string{ "name", "age", @@ -1154,7 +1154,7 @@ func TestAnonymousStructPrError(t *testing.T) { WithArgs("anyone").WillReturnRows(rs) assert.Error(t, query(context.Background(), db, func(rows *sql.Rows) error { return unmarshalRows(&value, rows, true) - }, "select name, age,grade,discipline,class_name,score from users where user=?", + }, "select name, age, grade, discipline, class_name, score from users where user=?", "anyone")) if len(value) > 0 { assert.Equal(t, value[0].score, 0) @@ -1162,22 +1162,6 @@ func TestAnonymousStructPrError(t *testing.T) { }) } -func runOrmTest(t *testing.T, fn func(db *sql.DB, mock sqlmock.Sqlmock)) { - logx.Disable() - - db, mock, err := sqlmock.New() - if err != nil { - t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) - } - defer db.Close() - - fn(db, mock) - - if err := mock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } -} - type mockedScanner struct { colErr error scanErr error diff --git a/core/stores/sqlx/sqlconn.go b/core/stores/sqlx/sqlconn.go index 7945ce1f74f3..e1297251ec68 100644 --- a/core/stores/sqlx/sqlconn.go +++ b/core/stores/sqlx/sqlconn.go @@ -11,9 +11,6 @@ import ( // spanName is used to identify the span name for the SQL execution. const spanName = "sql" -// ErrNotFound is an alias of sql.ErrNoRows -var ErrNotFound = sql.ErrNoRows - type ( // Session stands for raw connections or transaction sessions Session interface { @@ -131,6 +128,13 @@ func NewSqlConnFromDB(db *sql.DB, opts ...SqlOption) SqlConn { return conn } +// NewSqlConnFromSession returns a SqlConn with the given session. +func NewSqlConnFromSession(session Session) SqlConn { + return txConn{ + Session: session, + } +} + func (db *commonSqlConn) Exec(q string, args ...any) (result sql.Result, err error) { return db.ExecCtx(context.Background(), q, args...) } diff --git a/core/stores/sqlx/sqlconn_test.go b/core/stores/sqlx/sqlconn_test.go index 9ceb36a9a23d..cf1a148e2603 100644 --- a/core/stores/sqlx/sqlconn_test.go +++ b/core/stores/sqlx/sqlconn_test.go @@ -55,7 +55,7 @@ func TestSqlConn(t *testing.T) { } func buildConn() (mock sqlmock.Sqlmock, err error) { - connManager.GetResource(mockedDatasource, func() (io.Closer, error) { + _, err = connManager.GetResource(mockedDatasource, func() (io.Closer, error) { var db *sql.DB var err error db, mock, err = sqlmock.New() diff --git a/core/stores/sqlx/tx.go b/core/stores/sqlx/tx.go index e0d25a178c14..d983077ce499 100644 --- a/core/stores/sqlx/tx.go +++ b/core/stores/sqlx/tx.go @@ -15,11 +15,27 @@ type ( Rollback() error } + txConn struct { + Session + } + txSession struct { *sql.Tx } ) +func (s txConn) RawDB() (*sql.DB, error) { + return nil, errNoRawDBFromTx +} + +func (s txConn) Transact(_ func(Session) error) error { + return errCantNestTx +} + +func (s txConn) TransactCtx(_ context.Context, _ func(context.Context, Session) error) error { + return errCantNestTx +} + // NewSessionFromTx returns a Session with the given sql.Tx. // Use it with caution, it's provided for other ORM to interact with. func NewSessionFromTx(tx *sql.Tx) Session { diff --git a/core/stores/sqlx/tx_test.go b/core/stores/sqlx/tx_test.go index 9dd11a10735f..685f4494232b 100644 --- a/core/stores/sqlx/tx_test.go +++ b/core/stores/sqlx/tx_test.go @@ -6,7 +6,10 @@ import ( "errors" "testing" + "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" + "github.com/zeromicro/go-zero/core/breaker" + "github.com/zeromicro/go-zero/internal/dbtest" ) const ( @@ -23,51 +26,51 @@ func (mt *mockTx) Commit() error { return nil } -func (mt *mockTx) Exec(q string, args ...any) (sql.Result, error) { +func (mt *mockTx) Exec(_ string, _ ...any) (sql.Result, error) { return nil, nil } -func (mt *mockTx) ExecCtx(ctx context.Context, query string, args ...any) (sql.Result, error) { +func (mt *mockTx) ExecCtx(_ context.Context, _ string, _ ...any) (sql.Result, error) { return nil, nil } -func (mt *mockTx) Prepare(query string) (StmtSession, error) { +func (mt *mockTx) Prepare(_ string) (StmtSession, error) { return nil, nil } -func (mt *mockTx) PrepareCtx(ctx context.Context, query string) (StmtSession, error) { +func (mt *mockTx) PrepareCtx(_ context.Context, _ string) (StmtSession, error) { return nil, nil } -func (mt *mockTx) QueryRow(v any, q string, args ...any) error { +func (mt *mockTx) QueryRow(_ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRowCtx(ctx context.Context, v any, query string, args ...any) error { +func (mt *mockTx) QueryRowCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRowPartial(v any, q string, args ...any) error { +func (mt *mockTx) QueryRowPartial(_ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRowPartialCtx(ctx context.Context, v any, query string, args ...any) error { +func (mt *mockTx) QueryRowPartialCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRows(v any, q string, args ...any) error { +func (mt *mockTx) QueryRows(_ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRowsCtx(ctx context.Context, v any, query string, args ...any) error { +func (mt *mockTx) QueryRowsCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRowsPartial(v any, q string, args ...any) error { +func (mt *mockTx) QueryRowsPartial(_ any, _ string, _ ...any) error { return nil } -func (mt *mockTx) QueryRowsPartialCtx(ctx context.Context, v any, query string, args ...any) error { +func (mt *mockTx) QueryRowsPartialCtx(_ context.Context, _ any, _ string, _ ...any) error { return nil } @@ -101,3 +104,209 @@ func TestTransactRollback(t *testing.T) { assert.Equal(t, mockRollback, mock.status) assert.NotNil(t, err) } + +func TestTxExceptions(t *testing.T) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectCommit() + conn := NewSqlConnFromDB(db) + assert.NoError(t, conn.Transact(func(session Session) error { + return nil + })) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + conn := &commonSqlConn{ + connProv: func() (*sql.DB, error) { + return nil, errors.New("foo") + }, + beginTx: begin, + onError: func(ctx context.Context, err error) {}, + brk: breaker.NewBreaker(), + } + assert.Error(t, conn.Transact(func(session Session) error { + return nil + })) + }) + + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + _, err := conn.RawDB() + assert.Equal(t, errNoRawDBFromTx, err) + assert.Equal(t, errCantNestTx, conn.Transact(nil)) + assert.Equal(t, errCantNestTx, conn.TransactCtx(context.Background(), nil)) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + conn := NewSqlConnFromDB(db) + assert.Error(t, conn.Transact(func(session Session) error { + return errors.New("foo") + })) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectRollback().WillReturnError(errors.New("foo")) + conn := NewSqlConnFromDB(db) + assert.Error(t, conn.Transact(func(session Session) error { + panic("foo") + })) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectRollback() + conn := NewSqlConnFromDB(db) + assert.Error(t, conn.Transact(func(session Session) error { + panic(errors.New("foo")) + })) + }) +} + +func TestTxSession(t *testing.T) { + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + res, err := conn.Exec("any") + assert.NoError(t, err) + last, err := res.LastInsertId() + assert.NoError(t, err) + assert.Equal(t, int64(2), last) + affected, err := res.RowsAffected() + assert.NoError(t, err) + assert.Equal(t, int64(3), affected) + + mock.ExpectExec("any").WillReturnError(errors.New("foo")) + _, err = conn.Exec("any") + assert.Equal(t, "foo", err.Error()) + }) + + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any") + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + assert.NotNil(t, stmt) + + mock.ExpectPrepare("any").WillReturnError(errors.New("foo")) + _, err = conn.Prepare("any") + assert.Equal(t, "foo", err.Error()) + }) + + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"col"}).AddRow("foo") + mock.ExpectQuery("any").WillReturnRows(rows) + var val string + err := conn.QueryRow(&val, "any") + assert.NoError(t, err) + assert.Equal(t, "foo", val) + + mock.ExpectQuery("any").WillReturnError(errors.New("foo")) + err = conn.QueryRow(&val, "any") + assert.Equal(t, "foo", err.Error()) + }) + + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"col"}).AddRow("foo") + mock.ExpectQuery("any").WillReturnRows(rows) + var val string + err := conn.QueryRowPartial(&val, "any") + assert.NoError(t, err) + assert.Equal(t, "foo", val) + + mock.ExpectQuery("any").WillReturnError(errors.New("foo")) + err = conn.QueryRowPartial(&val, "any") + assert.Equal(t, "foo", err.Error()) + }) + + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"col"}).AddRow("foo").AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + var val []string + err := conn.QueryRows(&val, "any") + assert.NoError(t, err) + assert.Equal(t, []string{"foo", "bar"}, val) + + mock.ExpectQuery("any").WillReturnError(errors.New("foo")) + err = conn.QueryRows(&val, "any") + assert.Equal(t, "foo", err.Error()) + }) + + runTxTest(t, func(conn SqlConn, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"col"}).AddRow("foo").AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + var val []string + err := conn.QueryRowsPartial(&val, "any") + assert.NoError(t, err) + assert.Equal(t, []string{"foo", "bar"}, val) + + mock.ExpectQuery("any").WillReturnError(errors.New("foo")) + err = conn.QueryRowsPartial(&val, "any") + assert.Equal(t, "foo", err.Error()) + }) +} + +func TestTxRollback(t *testing.T) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + mock.ExpectQuery("foo").WillReturnError(errors.New("foo")) + mock.ExpectRollback() + + conn := NewSqlConnFromDB(db) + err := conn.Transact(func(session Session) error { + c := NewSqlConnFromSession(session) + _, err := c.Exec("any") + assert.NoError(t, err) + + var val string + return c.QueryRow(&val, "foo") + }) + assert.Error(t, err) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectExec("any").WillReturnError(errors.New("foo")) + mock.ExpectRollback() + + conn := NewSqlConnFromDB(db) + err := conn.Transact(func(session Session) error { + c := NewSqlConnFromSession(session) + if _, err := c.Exec("any"); err != nil { + return err + } + + var val string + assert.NoError(t, c.QueryRow(&val, "foo")) + return nil + }) + assert.Error(t, err) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + mock.ExpectQuery("foo").WillReturnRows(sqlmock.NewRows([]string{"col"}).AddRow("bar")) + mock.ExpectCommit() + + conn := NewSqlConnFromDB(db) + err := conn.Transact(func(session Session) error { + c := NewSqlConnFromSession(session) + _, err := c.Exec("any") + assert.NoError(t, err) + + var val string + assert.NoError(t, c.QueryRow(&val, "foo")) + assert.Equal(t, "bar", val) + return nil + }) + assert.NoError(t, err) + }) +} + +func runTxTest(t *testing.T, f func(conn SqlConn, mock sqlmock.Sqlmock)) { + dbtest.RunTxTest(t, func(tx *sql.Tx, mock sqlmock.Sqlmock) { + sess := NewSessionFromTx(tx) + conn := NewSqlConnFromSession(sess) + f(conn, mock) + }) +} diff --git a/internal/dbtest/sql.go b/internal/dbtest/sql.go new file mode 100644 index 000000000000..2e1be298c947 --- /dev/null +++ b/internal/dbtest/sql.go @@ -0,0 +1,37 @@ +package dbtest + +import ( + "database/sql" + "testing" + + "github.com/DATA-DOG/go-sqlmock" + "github.com/stretchr/testify/assert" +) + +// RunTest runs a test function with a mock database. +func RunTest(t *testing.T, fn func(db *sql.DB, mock sqlmock.Sqlmock)) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) + } + defer func() { + _ = db.Close() + }() + + fn(db, mock) + + if err = mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } +} + +// RunTxTest runs a test function with a mock database in a transaction. +func RunTxTest(t *testing.T, f func(tx *sql.Tx, mock sqlmock.Sqlmock)) { + RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + tx, err := db.Begin() + if assert.NoError(t, err) { + f(tx, mock) + } + }) +} From f95adae3c114303b024d77ed0b8cd8ea73955b5a Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Thu, 18 May 2023 11:00:03 +0800 Subject: [PATCH 02/15] Update readme-cn.md --- readme-cn.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme-cn.md b/readme-cn.md index c2c215dd3967..2a984e30e3a3 100644 --- a/readme-cn.md +++ b/readme-cn.md @@ -300,6 +300,7 @@ go-zero 已被许多公司用于生产部署,接入场景如在线教育、电 >88. 北京娱人共享智能科技有限公司 >89. 北京数智方科技有限公司 >90. 元匠科技 +>91. 宁波甬风信息科技有限公司 如果贵公司也已使用 go-zero,欢迎在 [登记地址](https://github.com/zeromicro/go-zero/issues/602) 登记,仅仅为了推广,不做其它用途。 From f7228e9af10b911fc9f21b6d943f2a73d692bf95 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Thu, 18 May 2023 12:24:04 +0800 Subject: [PATCH 03/15] chore: add more tests (#3256) --- core/stores/cache/cachenode_test.go | 121 +++++++++++++++++++++------- core/stores/cache/cacheopt_test.go | 28 +++++++ 2 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 core/stores/cache/cacheopt_test.go diff --git a/core/stores/cache/cachenode_test.go b/core/stores/cache/cachenode_test.go index 0a2c358c6607..6e16a102fba2 100644 --- a/core/stores/cache/cachenode_test.go +++ b/core/stores/cache/cachenode_test.go @@ -34,8 +34,10 @@ func init() { func TestCacheNode_DelCache(t *testing.T) { t.Run("del cache", func(t *testing.T) { - store := redistest.CreateRedis(t) - store.Type = redis.ClusterType + r, err := miniredis.Run() + assert.NoError(t, err) + defer r.Close() + store := redis.New(r.Addr(), redis.Cluster()) cn := cacheNode{ rds: store, @@ -166,40 +168,99 @@ func TestCacheNode_TakeBadRedis(t *testing.T) { } func TestCacheNode_TakeNotFound(t *testing.T) { - store := redistest.CreateRedis(t) + t.Run("not found", func(t *testing.T) { + store := redistest.CreateRedis(t) - cn := cacheNode{ - rds: store, - r: rand.New(rand.NewSource(time.Now().UnixNano())), - barrier: syncx.NewSingleFlight(), - lock: new(sync.Mutex), - unstableExpiry: mathx.NewUnstable(expiryDeviation), - stat: NewStat("any"), - errNotFound: errTestNotFound, - } - var str string - err := cn.Take(&str, "any", func(v any) error { - return errTestNotFound + cn := cacheNode{ + rds: store, + r: rand.New(rand.NewSource(time.Now().UnixNano())), + barrier: syncx.NewSingleFlight(), + lock: new(sync.Mutex), + unstableExpiry: mathx.NewUnstable(expiryDeviation), + stat: NewStat("any"), + errNotFound: errTestNotFound, + } + var str string + err := cn.Take(&str, "any", func(v any) error { + return errTestNotFound + }) + assert.True(t, cn.IsNotFound(err)) + assert.True(t, cn.IsNotFound(cn.Get("any", &str))) + val, err := store.Get("any") + assert.Nil(t, err) + assert.Equal(t, `*`, val) + + store.Set("any", "*") + err = cn.Take(&str, "any", func(v any) error { + return nil + }) + assert.True(t, cn.IsNotFound(err)) + assert.True(t, cn.IsNotFound(cn.Get("any", &str))) + + store.Del("any") + errDummy := errors.New("dummy") + err = cn.Take(&str, "any", func(v any) error { + return errDummy + }) + assert.Equal(t, errDummy, err) }) - assert.True(t, cn.IsNotFound(err)) - assert.True(t, cn.IsNotFound(cn.Get("any", &str))) - val, err := store.Get("any") - assert.Nil(t, err) - assert.Equal(t, `*`, val) - store.Set("any", "*") - err = cn.Take(&str, "any", func(v any) error { - return nil + t.Run("not found with redis error", func(t *testing.T) { + r, err := miniredis.Run() + assert.NoError(t, err) + defer r.Close() + store, err := redis.NewRedis(redis.RedisConf{ + Host: r.Addr(), + Type: redis.NodeType, + }) + assert.NoError(t, err) + + cn := cacheNode{ + rds: store, + r: rand.New(rand.NewSource(time.Now().UnixNano())), + barrier: syncx.NewSingleFlight(), + lock: new(sync.Mutex), + unstableExpiry: mathx.NewUnstable(expiryDeviation), + stat: NewStat("any"), + errNotFound: errTestNotFound, + } + var str string + err = cn.Take(&str, "any", func(v any) error { + r.SetError("mock error") + return errTestNotFound + }) + assert.True(t, cn.IsNotFound(err)) }) - assert.True(t, cn.IsNotFound(err)) - assert.True(t, cn.IsNotFound(cn.Get("any", &str))) +} - store.Del("any") - errDummy := errors.New("dummy") - err = cn.Take(&str, "any", func(v any) error { - return errDummy +func TestCacheNode_TakeCtxWithRedisError(t *testing.T) { + t.Run("not found with redis error", func(t *testing.T) { + r, err := miniredis.Run() + assert.NoError(t, err) + defer r.Close() + store, err := redis.NewRedis(redis.RedisConf{ + Host: r.Addr(), + Type: redis.NodeType, + }) + assert.NoError(t, err) + + cn := cacheNode{ + rds: store, + r: rand.New(rand.NewSource(time.Now().UnixNano())), + barrier: syncx.NewSingleFlight(), + lock: new(sync.Mutex), + unstableExpiry: mathx.NewUnstable(expiryDeviation), + stat: NewStat("any"), + errNotFound: errTestNotFound, + } + var str string + err = cn.Take(&str, "any", func(v any) error { + str = "foo" + r.SetError("mock error") + return nil + }) + assert.NoError(t, err) }) - assert.Equal(t, errDummy, err) } func TestCacheNode_TakeNotFoundButChangedByOthers(t *testing.T) { diff --git a/core/stores/cache/cacheopt_test.go b/core/stores/cache/cacheopt_test.go new file mode 100644 index 000000000000..7b7d82c47771 --- /dev/null +++ b/core/stores/cache/cacheopt_test.go @@ -0,0 +1,28 @@ +package cache + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestCacheOptions(t *testing.T) { + t.Run("default options", func(t *testing.T) { + o := newOptions() + assert.Equal(t, defaultExpiry, o.Expiry) + assert.Equal(t, defaultNotFoundExpiry, o.NotFoundExpiry) + }) + + t.Run("with expiry", func(t *testing.T) { + o := newOptions(WithExpiry(time.Second)) + assert.Equal(t, time.Second, o.Expiry) + assert.Equal(t, defaultNotFoundExpiry, o.NotFoundExpiry) + }) + + t.Run("with not found expiry", func(t *testing.T) { + o := newOptions(WithNotFoundExpiry(time.Second)) + assert.Equal(t, defaultExpiry, o.Expiry) + assert.Equal(t, time.Second, o.NotFoundExpiry) + }) +} From 90839965fa8d69403bcd4b293e4b12b5a8912846 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Thu, 18 May 2023 21:34:33 +0800 Subject: [PATCH 04/15] chore: remove directive for tests (#3257) --- core/stores/cache/cachenode_test.go | 11 ++++------- core/stores/cache/cleaner.go | 24 +++++++++++++++++------- core/stores/cache/cleaner_test.go | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/core/stores/cache/cachenode_test.go b/core/stores/cache/cachenode_test.go index 6e16a102fba2..f286639bc751 100644 --- a/core/stores/cache/cachenode_test.go +++ b/core/stores/cache/cachenode_test.go @@ -1,6 +1,3 @@ -//go:build !race - -// Disable data race detection is because of the timingWheel in cacheNode. package cache import ( @@ -58,16 +55,16 @@ func TestCacheNode_DelCache(t *testing.T) { }) t.Run("del cache with errors", func(t *testing.T) { - old := timingWheel + old := timingWheel.Load() ticker := timex.NewFakeTicker() - var err error - timingWheel, err = collection.NewTimingWheelWithTicker( + tw, err := collection.NewTimingWheelWithTicker( time.Millisecond, timingWheelSlots, func(key, value any) { clean(key, value) }, ticker) + timingWheel.Store(tw) assert.NoError(t, err) t.Cleanup(func() { - timingWheel = old + timingWheel.Store(old) }) r, err := miniredis.Run() diff --git a/core/stores/cache/cleaner.go b/core/stores/cache/cleaner.go index ce0b50a49596..24ec5780c823 100644 --- a/core/stores/cache/cleaner.go +++ b/core/stores/cache/cleaner.go @@ -2,6 +2,7 @@ package cache import ( "fmt" + "sync/atomic" "time" "github.com/zeromicro/go-zero/core/collection" @@ -19,7 +20,8 @@ const ( ) var ( - timingWheel *collection.TimingWheel + // use atomic to avoid data race in unit tests + timingWheel atomic.Value taskRunner = threading.NewTaskRunner(cleanWorkers) ) @@ -30,22 +32,27 @@ type delayTask struct { } func init() { - var err error - timingWheel, err = collection.NewTimingWheel(time.Second, timingWheelSlots, clean) + tw, err := collection.NewTimingWheel(time.Second, timingWheelSlots, clean) logx.Must(err) + timingWheel.Store(tw) proc.AddShutdownListener(func() { - timingWheel.Drain(clean) + if err := tw.Drain(clean); err != nil { + logx.Errorf("failed to drain timing wheel: %v", err) + } }) } // AddCleanTask adds a clean task on given keys. func AddCleanTask(task func() error, keys ...string) { - timingWheel.SetTimer(stringx.Randn(taskKeyLen), delayTask{ + tw := timingWheel.Load().(*collection.TimingWheel) + if err := tw.SetTimer(stringx.Randn(taskKeyLen), delayTask{ delay: time.Second, task: task, keys: keys, - }, time.Second) + }, time.Second); err != nil { + logx.Errorf("failed to set timer for keys: %q, error: %v", formatKeys(keys), err) + } } func clean(key, value any) { @@ -59,7 +66,10 @@ func clean(key, value any) { next, ok := nextDelay(dt.delay) if ok { dt.delay = next - timingWheel.SetTimer(key, dt, next) + tw := timingWheel.Load().(*collection.TimingWheel) + if err = tw.SetTimer(key, dt, next); err != nil { + logx.Errorf("failed to set timer for key: %s, error: %v", key, err) + } } else { msg := fmt.Sprintf("retried but failed to clear cache with keys: %q, error: %v", formatKeys(dt.keys), err) diff --git a/core/stores/cache/cleaner_test.go b/core/stores/cache/cleaner_test.go index 73f6b3f55eac..1497b9eb7a21 100644 --- a/core/stores/cache/cleaner_test.go +++ b/core/stores/cache/cleaner_test.go @@ -5,7 +5,9 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/zeromicro/go-zero/core/collection" "github.com/zeromicro/go-zero/core/proc" + "github.com/zeromicro/go-zero/core/timex" ) func TestNextDelay(t *testing.T) { @@ -49,6 +51,18 @@ func TestNextDelay(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + old := timingWheel.Load() + ticker := timex.NewFakeTicker() + tw, err := collection.NewTimingWheelWithTicker( + time.Millisecond, timingWheelSlots, func(key, value any) { + clean(key, value) + }, ticker) + timingWheel.Store(tw) + assert.NoError(t, err) + t.Cleanup(func() { + timingWheel.Store(old) + }) + next, ok := nextDelay(test.input) assert.Equal(t, test.ok, ok) assert.Equal(t, test.output, next) From 55e2c7ee83007ddbdc9d7f72fb603765aaf4f282 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Thu, 18 May 2023 23:11:32 +0800 Subject: [PATCH 05/15] chore: add more tests (#3258) --- core/stores/sqlx/sqlconn_test.go | 182 +++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/core/stores/sqlx/sqlconn_test.go b/core/stores/sqlx/sqlconn_test.go index cf1a148e2603..bbe15a924104 100644 --- a/core/stores/sqlx/sqlconn_test.go +++ b/core/stores/sqlx/sqlconn_test.go @@ -2,13 +2,16 @@ package sqlx import ( "database/sql" + "errors" "io" "testing" "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" + "github.com/zeromicro/go-zero/core/breaker" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/trace/tracetest" + "github.com/zeromicro/go-zero/internal/dbtest" ) const mockedDatasource = "sqlmock" @@ -54,6 +57,185 @@ func TestSqlConn(t *testing.T) { assert.Equal(t, 14, len(me.GetSpans())) } +func TestSqlConn_RawDB(t *testing.T) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"foo"}).AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + conn := NewSqlConnFromDB(db) + var val string + assert.NoError(t, conn.QueryRow(&val, "any")) + assert.Equal(t, "bar", val) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"foo"}).AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + conn := NewSqlConnFromDB(db) + var val string + assert.NoError(t, conn.QueryRowPartial(&val, "any")) + assert.Equal(t, "bar", val) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"any"}).AddRow("foo").AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + conn := NewSqlConnFromDB(db) + var vals []string + assert.NoError(t, conn.QueryRows(&vals, "any")) + assert.ElementsMatch(t, []string{"foo", "bar"}, vals) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + rows := sqlmock.NewRows([]string{"any"}).AddRow("foo").AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + conn := NewSqlConnFromDB(db) + var vals []string + assert.NoError(t, conn.QueryRowsPartial(&vals, "any")) + assert.ElementsMatch(t, []string{"foo", "bar"}, vals) + }) +} + +func TestSqlConn_Errors(t *testing.T) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + conn := NewSqlConnFromDB(db) + conn.(*commonSqlConn).connProv = func() (*sql.DB, error) { + return nil, errors.New("error") + } + _, err := conn.Prepare("any") + assert.Error(t, err) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectExec("any").WillReturnError(breaker.ErrServiceUnavailable) + conn := NewSqlConnFromDB(db) + _, err := conn.Exec("any") + assert.Error(t, err) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any").WillReturnError(breaker.ErrServiceUnavailable) + conn := NewSqlConnFromDB(db) + _, err := conn.Prepare("any") + assert.Error(t, err) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectBegin() + mock.ExpectRollback() + conn := NewSqlConnFromDB(db) + err := conn.Transact(func(session Session) error { + return breaker.ErrServiceUnavailable + }) + assert.Equal(t, breaker.ErrServiceUnavailable, err) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectQuery("any").WillReturnError(breaker.ErrServiceUnavailable) + conn := NewSqlConnFromDB(db) + var vals []string + err := conn.QueryRows(&vals, "any") + assert.Equal(t, breaker.ErrServiceUnavailable, err) + }) +} + +func TestStatement(t *testing.T) { + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any").WillBeClosed() + + conn := NewSqlConnFromDB(db) + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + assert.NoError(t, stmt.Close()) + }) + + dbtest.RunTxTest(t, func(tx *sql.Tx, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any").WillBeClosed() + + stmt, err := tx.Prepare("any") + assert.NoError(t, err) + st := statement{ + query: "foo", + stmt: stmt, + } + assert.NoError(t, st.Close()) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any") + mock.ExpectExec("any").WillReturnResult(sqlmock.NewResult(2, 3)) + + conn := NewSqlConnFromDB(db) + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + res, err := stmt.Exec() + assert.NoError(t, err) + lastInsertID, err := res.LastInsertId() + assert.NoError(t, err) + assert.Equal(t, int64(2), lastInsertID) + rowsAffected, err := res.RowsAffected() + assert.NoError(t, err) + assert.Equal(t, int64(3), rowsAffected) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any") + row := sqlmock.NewRows([]string{"foo"}).AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(row) + + conn := NewSqlConnFromDB(db) + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + + var val string + err = stmt.QueryRow(&val) + assert.NoError(t, err) + assert.Equal(t, "bar", val) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any") + row := sqlmock.NewRows([]string{"foo"}).AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(row) + + conn := NewSqlConnFromDB(db) + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + + var val string + err = stmt.QueryRowPartial(&val) + assert.NoError(t, err) + assert.Equal(t, "bar", val) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any") + rows := sqlmock.NewRows([]string{"any"}).AddRow("foo").AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + + conn := NewSqlConnFromDB(db) + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + + var vals []string + assert.NoError(t, stmt.QueryRows(&vals)) + assert.ElementsMatch(t, []string{"foo", "bar"}, vals) + }) + + dbtest.RunTest(t, func(db *sql.DB, mock sqlmock.Sqlmock) { + mock.ExpectPrepare("any") + rows := sqlmock.NewRows([]string{"any"}).AddRow("foo").AddRow("bar") + mock.ExpectQuery("any").WillReturnRows(rows) + + conn := NewSqlConnFromDB(db) + stmt, err := conn.Prepare("any") + assert.NoError(t, err) + + var vals []string + assert.NoError(t, stmt.QueryRowsPartial(&vals)) + assert.ElementsMatch(t, []string{"foo", "bar"}, vals) + }) +} + func buildConn() (mock sqlmock.Sqlmock, err error) { _, err = connManager.GetResource(mockedDatasource, func() (io.Closer, error) { var db *sql.DB From 701bb31ed2390d12437ba4d2d31eed2c7365e0b4 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Thu, 18 May 2023 23:43:50 +0800 Subject: [PATCH 06/15] chore: add more tests (#3259) --- core/stat/internal/cgroup_linux.go | 3 ++- core/stat/internal/cgroup_linux_test.go | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 core/stat/internal/cgroup_linux_test.go diff --git a/core/stat/internal/cgroup_linux.go b/core/stat/internal/cgroup_linux.go index 5b22054941b9..23bdda4827cb 100644 --- a/core/stat/internal/cgroup_linux.go +++ b/core/stat/internal/cgroup_linux.go @@ -3,6 +3,7 @@ package internal import ( "bufio" "fmt" + "math" "os" "path" "strconv" @@ -280,7 +281,7 @@ func runningInUserNS() bool { // We assume we are in the initial user namespace if we have a full // range - 4294967295 uids starting at uid 0. - if a == 0 && b == 0 && c == 4294967295 { + if a == 0 && b == 0 && c == math.MaxUint32 { return } inUserNS = true diff --git a/core/stat/internal/cgroup_linux_test.go b/core/stat/internal/cgroup_linux_test.go new file mode 100644 index 000000000000..a2faaf772d93 --- /dev/null +++ b/core/stat/internal/cgroup_linux_test.go @@ -0,0 +1,12 @@ +package internal + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRunningInUserNS(t *testing.T) { + // should be false in docker + assert.False(t, runningInUserNS()) +} From 99ce24e2ab936050c8d3135294e84cbf0840a346 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Fri, 19 May 2023 00:56:50 +0800 Subject: [PATCH 07/15] chore: add more tests (#3260) --- core/stat/internal/cgroup_linux.go | 1 + core/stores/builder/builder_test.go | 59 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/core/stat/internal/cgroup_linux.go b/core/stat/internal/cgroup_linux.go index 23bdda4827cb..5f53d9ed5af8 100644 --- a/core/stat/internal/cgroup_linux.go +++ b/core/stat/internal/cgroup_linux.go @@ -284,6 +284,7 @@ func runningInUserNS() bool { if a == 0 && b == 0 && c == math.MaxUint32 { return } + inUserNS = true }) diff --git a/core/stores/builder/builder_test.go b/core/stores/builder/builder_test.go index 8741b7d686fc..d8cfd33e3619 100644 --- a/core/stores/builder/builder_test.go +++ b/core/stores/builder/builder_test.go @@ -69,3 +69,62 @@ func TestFieldNamesWithDashTagAndOptions(t *testing.T) { assert.Equal(t, expected, out) }) } + +func TestPostgreSqlJoin(t *testing.T) { + // Test with empty input array + var input []string + var expectedOutput string + assert.Equal(t, expectedOutput, PostgreSqlJoin(input)) + + // Test with single element input array + input = []string{"foo"} + expectedOutput = "foo = $2" + assert.Equal(t, expectedOutput, PostgreSqlJoin(input)) + + // Test with multiple elements input array + input = []string{"foo", "bar", "baz"} + expectedOutput = "foo = $2, bar = $3, baz = $4" + assert.Equal(t, expectedOutput, PostgreSqlJoin(input)) +} + +type testStruct struct { + Foo string `db:"foo"` + Bar int `db:"bar"` + Baz bool `db:"-"` +} + +func TestRawFieldNames(t *testing.T) { + // Test with a struct without tags + in := struct { + Foo string + Bar int + }{} + expectedOutput := []string{"`Foo`", "`Bar`"} + assert.ElementsMatch(t, expectedOutput, RawFieldNames(in)) + + // Test pg without db tag + expectedOutput = []string{"Foo", "Bar"} + assert.ElementsMatch(t, expectedOutput, RawFieldNames(in, true)) + + // Test with a struct with tags + input := testStruct{} + expectedOutput = []string{"`foo`", "`bar`"} + assert.ElementsMatch(t, expectedOutput, RawFieldNames(input)) + + // Test with nil input (pointer) + var nilInput *testStruct + assert.Panics(t, func() { + RawFieldNames(nilInput) + }, "RawFieldNames should panic with nil input") + + // Test with non-struct input + inputInt := 42 + assert.Panics(t, func() { + RawFieldNames(inputInt) + }, "RawFieldNames should panic with non-struct input") + + // Test with PostgreSQL flag + input = testStruct{} + expectedOutput = []string{"foo", "bar"} + assert.ElementsMatch(t, expectedOutput, RawFieldNames(input, true)) +} From 925cf8d3d1e76470ae84f8af2330c391d7202952 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Fri, 19 May 2023 12:15:43 +0800 Subject: [PATCH 08/15] chore: add more tests (#3261) --- core/prof/runtime.go | 8 +++++++- core/prof/runtime_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 core/prof/runtime_test.go diff --git a/core/prof/runtime.go b/core/prof/runtime.go index 17ede442ee3f..af41d0517f68 100644 --- a/core/prof/runtime.go +++ b/core/prof/runtime.go @@ -2,6 +2,8 @@ package prof import ( "fmt" + "io" + "os" "runtime" "time" ) @@ -13,6 +15,10 @@ const ( // DisplayStats prints the goroutine, memory, GC stats with given interval, default to 5 seconds. func DisplayStats(interval ...time.Duration) { + displayStatsWithWriter(os.Stdout, interval...) +} + +func displayStatsWithWriter(writer io.Writer, interval ...time.Duration) { duration := defaultInterval for _, val := range interval { duration = val @@ -24,7 +30,7 @@ func DisplayStats(interval ...time.Duration) { for range ticker.C { var m runtime.MemStats runtime.ReadMemStats(&m) - fmt.Printf("Goroutines: %d, Alloc: %vm, TotalAlloc: %vm, Sys: %vm, NumGC: %v\n", + fmt.Fprintf(writer, "Goroutines: %d, Alloc: %vm, TotalAlloc: %vm, Sys: %vm, NumGC: %v\n", runtime.NumGoroutine(), m.Alloc/mega, m.TotalAlloc/mega, m.Sys/mega, m.NumGC) } }() diff --git a/core/prof/runtime_test.go b/core/prof/runtime_test.go new file mode 100644 index 000000000000..208e75f5f240 --- /dev/null +++ b/core/prof/runtime_test.go @@ -0,0 +1,36 @@ +package prof + +import ( + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestDisplayStats(t *testing.T) { + writer := &threadSafeBuffer{ + buf: strings.Builder{}, + } + displayStatsWithWriter(writer, time.Millisecond*10) + time.Sleep(time.Millisecond * 50) + assert.Contains(t, writer.String(), "Goroutines: ") +} + +type threadSafeBuffer struct { + buf strings.Builder + lock sync.Mutex +} + +func (b *threadSafeBuffer) String() string { + b.lock.Lock() + defer b.lock.Unlock() + return b.buf.String() +} + +func (b *threadSafeBuffer) Write(p []byte) (n int, err error) { + b.lock.Lock() + defer b.lock.Unlock() + return b.buf.Write(p) +} From a9aac7e4200ab39885200fcec48b33add425a0b8 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Fri, 19 May 2023 23:29:30 +0800 Subject: [PATCH 09/15] chore: add more tests (#3265) --- core/stat/internal/cgroup_linux_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/stat/internal/cgroup_linux_test.go b/core/stat/internal/cgroup_linux_test.go index a2faaf772d93..06bc5ac9fa5c 100644 --- a/core/stat/internal/cgroup_linux_test.go +++ b/core/stat/internal/cgroup_linux_test.go @@ -10,3 +10,18 @@ func TestRunningInUserNS(t *testing.T) { // should be false in docker assert.False(t, runningInUserNS()) } + +func TestCgroupV1(t *testing.T) { + if isCgroup2UnifiedMode() { + cg, err := currentCgroupV1() + assert.NoError(t, err) + _, err = cg.cpus() + assert.Error(t, err) + _, err = cg.cpuPeriodUs() + assert.Error(t, err) + _, err = cg.cpuQuotaUs() + assert.Error(t, err) + _, err = cg.usageAllCpus() + assert.Error(t, err) + } +} From 0f4973be060a3874cd7c7d1820a8de73f9252cd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 May 2023 21:43:24 +0800 Subject: [PATCH 10/15] chore(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 in /tools/goctl (#3268) --- tools/goctl/go.mod | 2 +- tools/goctl/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/goctl/go.mod b/tools/goctl/go.mod index b709681ed89e..265ce7a36032 100644 --- a/tools/goctl/go.mod +++ b/tools/goctl/go.mod @@ -11,7 +11,7 @@ require ( github.com/iancoleman/strcase v0.2.0 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 github.com/zeromicro/antlr v0.0.1 github.com/zeromicro/ddl-parser v1.0.4 diff --git a/tools/goctl/go.sum b/tools/goctl/go.sum index 85694bd7625d..63aa4225b8a2 100644 --- a/tools/goctl/go.sum +++ b/tools/goctl/go.sum @@ -284,8 +284,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 h1:+dBg5k7nuTE38VVdoroRsT0Z88fmvdYrI2EjzJst35I= github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1/go.mod h1:nmuySobZb4kFgFy6BptpXp/BBw+xFSyvVPP6auoJB4k= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= From fa1d6d50a84c39ce5effaaf3854249acc11df397 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 09:41:17 +0800 Subject: [PATCH 11/15] chore(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 (#3267) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 549bd773baa4..1f1a7ffbc55e 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.7 github.com/prometheus/client_golang v1.15.1 github.com/spaolacci/murmur3 v1.1.0 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 go.etcd.io/etcd/api/v3 v3.5.9 go.etcd.io/etcd/client/v3 v3.5.9 go.mongodb.org/mongo-driver v1.11.6 diff --git a/go.sum b/go.sum index 5d607581e624..57acfbac991d 100644 --- a/go.sum +++ b/go.sum @@ -297,8 +297,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= From 0cc8fe617b50953a7e30c3985aba53c5de50d6ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 05:08:30 +0000 Subject: [PATCH 12/15] chore(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index a72890cb1597..b2ca2becc6e6 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.7 github.com/prometheus/client_golang v1.15.1 github.com/spaolacci/murmur3 v1.1.0 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 go.etcd.io/etcd/api/v3 v3.5.9 go.etcd.io/etcd/client/v3 v3.5.9 go.mongodb.org/mongo-driver v1.11.6 diff --git a/go.sum b/go.sum index ddc51b80751b..9f32adda5faf 100644 --- a/go.sum +++ b/go.sum @@ -305,8 +305,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= From 39744c6508e6e2fbc01fef135bef1b8d29d36cb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 05:08:56 +0000 Subject: [PATCH 13/15] chore(deps): bump go.opentelemetry.io/otel/exporters/jaeger Bumps [go.opentelemetry.io/otel/exporters/jaeger](https://github.com/open-telemetry/opentelemetry-go) from 1.15.0 to 1.15.1. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.15.0...v1.15.1) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/jaeger dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a72890cb1597..0a4abd79b10c 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( go.etcd.io/etcd/client/v3 v3.5.9 go.mongodb.org/mongo-driver v1.11.6 go.opentelemetry.io/otel v1.15.1 - go.opentelemetry.io/otel/exporters/jaeger v1.15.0 + go.opentelemetry.io/otel/exporters/jaeger v1.15.1 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.1 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.15.1 go.opentelemetry.io/otel/exporters/zipkin v1.15.1 diff --git a/go.sum b/go.sum index ddc51b80751b..39788bd3f60f 100644 --- a/go.sum +++ b/go.sum @@ -339,8 +339,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8= go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc= -go.opentelemetry.io/otel/exporters/jaeger v1.15.0 h1:LUWu1vHy3KGxjSb9RijEsJ1UREjpDX43RVYnoDKoyq8= -go.opentelemetry.io/otel/exporters/jaeger v1.15.0/go.mod h1:PxigiLay9m921aZ1gQ3fDAE1oaxMSbOok/lZrpPndIg= +go.opentelemetry.io/otel/exporters/jaeger v1.15.1 h1:x3SLvwli0OyAJapNcOIzf1xXBRBA+HD3elrMQmFfmXo= +go.opentelemetry.io/otel/exporters/jaeger v1.15.1/go.mod h1:0Ck9b5oLL/bFZvfAEEqtrb1U0jZXjm5fWXMCOCG3vvM= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1 h1:XYDQtNzdb2T4uM1pku2m76eSMDJgqhJ+6KzkqgQBALc= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1/go.mod h1:uOTV75+LOzV+ODmL8ahRLWkFA3eQcSC2aAsbxIu4duk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.1 h1:tyoeaUh8REKay72DVYsSEBYV18+fGONe+YYPaOxgLoE= From ab876e0e700499a5c364a323ebb8f8ba68459bcd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 05:09:15 +0000 Subject: [PATCH 14/15] chore(deps): bump github.com/go-playground/validator/v10 Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.12.0 to 10.14.0. - [Release notes](https://github.com/go-playground/validator/releases) - [Commits](https://github.com/go-playground/validator/compare/v10.12.0...v10.14.0) --- updated-dependencies: - dependency-name: github.com/go-playground/validator/v10 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 5 +++-- go.sum | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index a72890cb1597..d4502c16eb42 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/fullstorydev/grpcurl v1.8.7 github.com/go-playground/locales v0.14.1 github.com/go-playground/universal-translator v0.18.1 - github.com/go-playground/validator/v10 v10.12.0 + github.com/go-playground/validator/v10 v10.14.0 github.com/go-redis/redis/v8 v8.11.5 github.com/go-sql-driver/mysql v1.7.1 github.com/golang-jwt/jwt/v4 v4.5.0 @@ -61,6 +61,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -77,7 +78,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.15.15 // indirect - github.com/leodido/go-urn v1.2.2 // indirect + github.com/leodido/go-urn v1.2.4 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect diff --git a/go.sum b/go.sum index ddc51b80751b..e75c171446d9 100644 --- a/go.sum +++ b/go.sum @@ -92,6 +92,8 @@ github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBD github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fullstorydev/grpcurl v1.8.7 h1:xJWosq3BQovQ4QrdPO72OrPiWuGgEsxY8ldYsJbPrqI= github.com/fullstorydev/grpcurl v1.8.7/go.mod h1:pVtM4qe3CMoLaIzYS8uvTuDj2jVYmXqMUkZeijnXp/E= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -113,8 +115,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.12.0 h1:E4gtWgxWxp8YSxExrQFv5BpCahla0PVF2oTTEYaWQGI= -github.com/go-playground/validator/v10 v10.12.0/go.mod h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= @@ -233,8 +235,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4= -github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -287,7 +289,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= From 4257568438c407ea3b7123441ed8d285d1a32fc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 05:10:22 +0000 Subject: [PATCH 15/15] chore(deps): bump github.com/stretchr/testify in /tools/goctl Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- tools/goctl/go.mod | 2 +- tools/goctl/go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/goctl/go.mod b/tools/goctl/go.mod index a3cd65d6566f..479dd58c8cbf 100644 --- a/tools/goctl/go.mod +++ b/tools/goctl/go.mod @@ -12,7 +12,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 github.com/suyuan32/knife v0.0.1-beta.1 github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 github.com/zeromicro/antlr v0.0.1 diff --git a/tools/goctl/go.sum b/tools/goctl/go.sum index dee05108d297..4736e7ab787e 100644 --- a/tools/goctl/go.sum +++ b/tools/goctl/go.sum @@ -71,12 +71,10 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/suyuan32/knife v0.0.1-beta.1 h1:scJUrOynuvps2gMGXgrFYp1JyPAxJgU/3q6jluGx/zY= github.com/suyuan32/knife v0.0.1-beta.1/go.mod h1:F5K5RUhrZdyo+Ln5dzmbtYIh6k+dbPgaMxWHZYFwRZA= github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 h1:+dBg5k7nuTE38VVdoroRsT0Z88fmvdYrI2EjzJst35I=