diff --git a/.golangci.yml b/.golangci.yml index de83c10..32ba246 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -66,6 +66,7 @@ linters: - dogsled - depguard - dupl + - errorlint - gocognit - goconst - gocritic @@ -90,10 +91,13 @@ linters: - unparam - unused - whitespace + - wrapcheck + - tparallel + # golangci.com configuration # https://github.com/golangci/golangci/wiki/Configuration service: - golangci-lint-version: 1.30.x + golangci-lint-version: 1.37.x prepare: - echo "here I can run custom commands, but no preparation needed for this repo" diff --git a/.travis.yml b/.travis.yml index eb8e22c..beb4498 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,8 @@ env: - GO111MODULE=on go: - - 1.14.x - 1.15.x + - 1.16.x - tip matrix: @@ -18,7 +18,7 @@ matrix: - go: tip before_install: - - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0 + - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.37.1 script: - make ci_tests diff --git a/CHANGELOG.md b/CHANGELOG.md index a19c969..36f6efc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ + +## [v0.5.0] - 2021-03-04 + +### Added +- Add support for pointer to retry.StopError + + ## [v0.4.1] - 2020-08-16 @@ -58,7 +65,8 @@ -[Unreleased]: https://github.com/arsham/dbtools/compare/v0.4.1...HEAD +[Unreleased]: https://github.com/arsham/dbtools/compare/v0.5.0...HEAD +[v0.5.0]: https://github.com/arsham/dbtools/compare/v0.4.1...v0.5.0 [v0.4.1]: https://github.com/arsham/dbtools/compare/v0.4.0...v0.4.1 [v0.4.0]: https://github.com/arsham/dbtools/compare/v0.3.2...v0.4.0 [v0.3.2]: https://github.com/arsham/dbtools/compare/v0.3.1...v0.3.2 diff --git a/Makefile b/Makefile index 845e44c..4b23e2b 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ tests: ## Run unit tests in watch mode. You can set: [run, timeout, short, dir, .PHONY: dependencies dependencies: ## Install dependencies requried for development operations. @go get -u github.com/cespare/reflex - @go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.30.0 + @go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.37.1 @go get -u github.com/git-chglog/git-chglog/cmd/git-chglog @go get github.com/stretchr/testify/mock @go get github.com/vektra/mockery/.../ diff --git a/README.md b/README.md index 576c11f..f0c21b6 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,14 @@ [![Build Status](https://travis-ci.org/arsham/dbtools.svg?branch=master)](https://travis-ci.org/arsham/dbtools) [![Coverage Status](https://codecov.io/gh/arsham/dbtools/branch/master/graph/badge.svg)](https://codecov.io/gh/arsham/dbtools) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Go Report Card](https://goreportcard.com/badge/github.com/arsham/dbtools)](https://goreportcard.com/report/github.com/arsham/dbtools) This library contains goroutine safe helpers for retrying transactions until they succeed and handles errors in a developer friendly way. There are helpers for using with [go-sqlmock][go-sqlmock] in tests. There is also a `Mocha` inspired reporter for [spec BDD library][spec]. -This library supports `Go >= 1.14`. +This library supports `Go >= 1.15`. 1. [Transaction](#transaction) * [PGX Pool](#pgx-pool) diff --git a/db.go b/db.go index 6a5341f..5153a9a 100644 --- a/db.go +++ b/db.go @@ -3,7 +3,6 @@ package dbtools import ( "context" "database/sql" - "io" "time" "github.com/arsham/retry" @@ -87,7 +86,7 @@ func (t *Transaction) PGX(ctx context.Context, transactions ...func(pgx.Tx) erro select { case <-ctx.Done(): e := errors.Wrap(tx.Rollback(ctx), "rolling back transaction") - return retry.StopError{ + return &retry.StopError{ Err: multierror.Append(ctx.Err(), e).ErrorOrNil(), } default: @@ -104,8 +103,12 @@ func (t *Transaction) PGX(ctx context.Context, transactions ...func(pgx.Tx) erro if err != nil { e := errors.Wrap(tx.Rollback(ctx), "rolling back transaction") e = multierror.Append(err, e).ErrorOrNil() - if _, ok := err.(retry.StopError); ok { - e = retry.StopError{Err: e} + var ( + v1 retry.StopError + v2 *retry.StopError + ) + if errors.As(err, &v1) || errors.As(err, &v2) { + e = &retry.StopError{Err: e} } return e } @@ -128,7 +131,7 @@ func (t *Transaction) DB(ctx context.Context, transactions ...func(Tx) error) er select { case <-ctx.Done(): e := errors.Wrap(tx.Rollback(), "rolling back transaction") - return retry.StopError{ + return &retry.StopError{ Err: multierror.Append(ctx.Err(), e).ErrorOrNil(), } default: @@ -145,8 +148,12 @@ func (t *Transaction) DB(ctx context.Context, transactions ...func(Tx) error) er if err != nil { e := errors.Wrap(tx.Rollback(), "rolling back transaction") e = multierror.Append(err, e).ErrorOrNil() - if _, ok := err.(retry.StopError); ok { - e = retry.StopError{Err: e} + var ( + v1 retry.StopError + v2 *retry.StopError + ) + if errors.As(err, &v1) || errors.As(err, &v2) { + e = &retry.StopError{Err: e} } return e } @@ -154,73 +161,3 @@ func (t *Transaction) DB(ctx context.Context, transactions ...func(Tx) error) er return errors.Wrap(tx.Commit(), "committing transaction") }) } - -// WithTransaction creates a transaction on db and uses it to call fn functions -// one by one. The first function that returns an error or panics will cause the -// loop to stop and transaction to be rolled back. -// Deprecated: use Transaction instead. -func WithTransaction(db *sql.DB, fn ...func(*sql.Tx) error) error { - tx, err := db.Begin() - if err != nil { - return errors.Wrap(err, "starting transaction") - } - for _, f := range fn { - var err error - func() { - defer func() { - if r := recover(); r != nil { - err = errors.Wrapf(errPanic, "%v", r) - } - }() - err = f(tx) - }() - if err != nil { - e := errors.Wrap(tx.Rollback(), "rolling back transaction") - return multierror.Append(err, e).ErrorOrNil() - } - } - return errors.Wrap(tx.Commit(), "committing transaction") -} - -// Retry calls fn for retries times until it returns nil. If retries is zero fn -// would not be called. It delays and retries if the function returns any errors -// or panics. The fn function receives the current iteration as its argument. -// Deprecated: use http://github.com/arsham/retry library instead. -func Retry(retries int, delay time.Duration, fn func(int) error) error { - var err error - for i := 0; i < retries; i++ { - func() { - defer func() { - if r := recover(); r != nil { - err = errors.Wrapf(errPanic, "%v", r) - } - }() - err = fn(i) - }() - switch err { - case io.EOF, nil: - return nil - } - time.Sleep(delay * time.Duration(i+1)) - } - return err -} - -// RetryTransaction combines WithTransaction and Retry calls. It stops the call -// if context is times out or cancelled. -// Deprecated: use Transaction instead. -func RetryTransaction(ctx context.Context, db *sql.DB, retries int, delay time.Duration, fn ...func(*sql.Tx) error) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - return Retry(retries, delay, func(int) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - return WithTransaction(db, fn...) - }) -} diff --git a/db_example_test.go b/db_example_test.go index 442be04..a42a73f 100644 --- a/db_example_test.go +++ b/db_example_test.go @@ -90,7 +90,7 @@ func ExampleTransaction_PGX_stopTrying() { return nil }, func(pgx.Tx) error { fmt.Println("Running second query.") - return retry.StopError{Err: assert.AnError} + return &retry.StopError{Err: assert.AnError} }) fmt.Printf("Transaction returns my error: %t", strings.Contains(err.Error(), assert.AnError.Error())) diff --git a/db_test.go b/db_test.go index 10fa09a..c55430e 100644 --- a/db_test.go +++ b/db_test.go @@ -2,16 +2,12 @@ package dbtools_test import ( "context" - "database/sql" - "fmt" "testing" - "time" "github.com/DATA-DOG/go-sqlmock" "github.com/arsham/dbtools" "github.com/arsham/dbtools/mocks" "github.com/arsham/retry" - "github.com/hashicorp/go-multierror" "github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/pgx/v4/stdlib" @@ -25,7 +21,9 @@ func TestNewTransaction(t *testing.T) { t.Parallel() db, _, err := sqlmock.New() require.NoError(t, err) - defer db.Close() + t.Cleanup(func() { + db.Close() + }) tcs := map[string]struct { db interface{} conf []dbtools.ConfigFunc @@ -44,6 +42,7 @@ func TestNewTransaction(t *testing.T) { for name, tc := range tcs { tc := tc t.Run(name, func(t *testing.T) { + t.Parallel() _, err := dbtools.NewTransaction(tc.db, tc.conf...) if tc.wantErr == nil { assert.NoError(t, err) @@ -55,11 +54,13 @@ func TestNewTransaction(t *testing.T) { } func TestTransaction(t *testing.T) { + t.Parallel() t.Run("PGX", testTransactionPGX) t.Run("DB", testTransactionDB) } func testTransactionPGX(t *testing.T) { + t.Parallel() t.Run("NilDatabase", testTransactionPGXNilDatabase) t.Run("BeginError", testTransactionPGXBeginError) t.Run("CancelledContext", testTransactionPGXCancelledContext) @@ -302,6 +303,11 @@ func testTransactionPGXCommitError(t *testing.T) { } func testTransactionPGXShortStop(t *testing.T) { + t.Run("WithValue", testTransactionPGXShortStopWithValue) + t.Run("WithPointer", testTransactionPGXShortStopWithPointer) +} + +func testTransactionPGXShortStopWithValue(t *testing.T) { t.Parallel() db := &mocks.Pool{} defer db.AssertExpectations(t) @@ -331,6 +337,36 @@ func testTransactionPGXShortStop(t *testing.T) { assert.Equal(t, total, calls) } +func testTransactionPGXShortStopWithPointer(t *testing.T) { + t.Parallel() + db := &mocks.Pool{} + defer db.AssertExpectations(t) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + total := 3 + tr, err := dbtools.NewTransaction(db, dbtools.RetryCount(total*10)) + require.NoError(t, err) + + tx := &mocks.PGXTx{} + defer tx.AssertExpectations(t) + + db.On("Begin", mock.Anything).Return(tx, nil). + Times(total) + tx.On("Rollback", mock.Anything).Return(nil).Times(total) + + calls := 0 + err = tr.PGX(ctx, func(pgx.Tx) error { + calls++ + if calls >= total { + return &retry.StopError{Err: assert.AnError} + } + return errors.New(randomString(10)) + }) + assertInError(t, err, assert.AnError) + assert.Equal(t, total, calls) +} + func testTransactionPGXRetrySuccess(t *testing.T) { t.Parallel() db := &mocks.Pool{} @@ -400,6 +436,7 @@ func testTransactionPGXMultipleFunctions(t *testing.T) { assert.Equal(t, 3, callsFn2) } +// nolint:wrapcheck // no need to check these. func testTransactionPGXRealDatabase(t *testing.T) { t.Parallel() if testing.Short() { @@ -693,6 +730,11 @@ func testTransactionDBCommitError(t *testing.T) { } func testTransactionDBShortStop(t *testing.T) { + t.Run("WithValue", testTransactionDBShortStopWithValue) + t.Run("WithPointer", testTransactionDBShortStopWithPointer) +} + +func testTransactionDBShortStopWithValue(t *testing.T) { t.Parallel() db := &mocks.DB{} defer db.AssertExpectations(t) @@ -722,6 +764,36 @@ func testTransactionDBShortStop(t *testing.T) { assert.Equal(t, total, calls) } +func testTransactionDBShortStopWithPointer(t *testing.T) { + t.Parallel() + db := &mocks.DB{} + defer db.AssertExpectations(t) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + total := 3 + tr, err := dbtools.NewTransaction(db, dbtools.RetryCount(total*10)) + require.NoError(t, err) + + tx := &mocks.Tx{} + defer tx.AssertExpectations(t) + + db.On("BeginTx", mock.Anything, mock.Anything).Return(tx, nil). + Times(total) + tx.On("Rollback").Return(nil).Times(total) + + calls := 0 + err = tr.DB(ctx, func(dbtools.Tx) error { + calls++ + if calls >= total { + return &retry.StopError{Err: assert.AnError} + } + return errors.New(randomString(10)) + }) + assertInError(t, err, assert.AnError) + assert.Equal(t, total, calls) +} + func testTransactionDBRetrySuccess(t *testing.T) { t.Parallel() db := &mocks.DB{} @@ -791,6 +863,7 @@ func testTransactionDBMultipleFunctions(t *testing.T) { assert.Equal(t, 3, callsFn2) } +// nolint:wrapcheck // no need to check these. func testTransactionDBRealDatabase(t *testing.T) { t.Parallel() if testing.Short() { @@ -839,524 +912,3 @@ func testTransactionDBRealDatabase(t *testing.T) { require.NoError(t, err) assert.ElementsMatch(t, names, gotNames) } - -func TestWithTransaction(t *testing.T) { - t.Run("BeginCommit", testWithTransactionBeginCommit) - t.Run("RollbackFirst", testWithTransactionRollbackFirst) - t.Run("RollbackSecond", testWithTransactionRollbackSecond) - t.Run("Commit", testWithTransactionCommit) - t.Run("FunctionPanic", testWithTransactionFunctionPanic) -} - -func testWithTransactionBeginCommit(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin(). - WillReturnError(assert.AnError) - err = dbtools.WithTransaction(db) - assert.Equal(t, assert.AnError, errors.Cause(err)) - - dbMock.ExpectBegin() - dbMock.ExpectCommit(). - WillReturnError(assert.AnError) - err = dbtools.WithTransaction(db) - assert.Equal(t, assert.AnError, errors.Cause(err)) - - dbMock.ExpectBegin() - dbMock.ExpectCommit() - err = dbtools.WithTransaction(db) - assert.NoError(t, err) -} - -func testWithTransactionRollbackFirst(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - err = dbtools.WithTransaction(db, func(*sql.Tx) error { - return assert.AnError - }, func(*sql.Tx) error { - t.Error("didn't expect to be called") - return nil - }) - mErr, ok := err.(*multierror.Error) - require.True(t, ok, "not a multierror") - var wantErr error - for _, e := range mErr.Errors { - if errors.Cause(e) == assert.AnError { - wantErr = e - } - } - assert.Equal(t, assert.AnError, errors.Cause(wantErr)) -} - -func testWithTransactionRollbackSecond(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - err = dbtools.WithTransaction(db, func(*sql.Tx) error { - return nil - }, func(*sql.Tx) error { - return assert.AnError - }) - mErr, ok := err.(*multierror.Error) - require.True(t, ok, "not a multierror") - var wantErr error - for _, e := range mErr.Errors { - if errors.Cause(e) == assert.AnError { - wantErr = e - } - } - assert.Equal(t, assert.AnError, errors.Cause(wantErr)) -} - -func testWithTransactionCommit(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectCommit() - err = dbtools.WithTransaction(db, func(*sql.Tx) error { - return nil - }) - assert.NoError(t, err) - - dbMock.ExpectBegin() - dbMock.ExpectCommit(). - WillReturnError(assert.AnError) - err = dbtools.WithTransaction(db, func(*sql.Tx) error { - return nil - }) - assert.Equal(t, assert.AnError, errors.Cause(err)) -} - -func testWithTransactionFunctionPanic(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - require.NotPanics(t, func() { - err := dbtools.WithTransaction(db, func(*sql.Tx) error { - panic("for some reason") - }, func(*sql.Tx) error { - t.Error("didn't expect to be called") - return nil - }) - assert.Error(t, err) - }) -} - -func ExampleWithTransaction() { - // For this example we are using sqlmock, but you can use an actual - // connection with this function. - db, dbMock, err := sqlmock.New() - if err != nil { - panic(err) - } - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - fmt.Printf("there were unfulfilled expectations: %s\n", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectCommit() - err = dbtools.WithTransaction(db, func(*sql.Tx) error { - fmt.Println("Running first query.") - return nil - }, func(*sql.Tx) error { - fmt.Println("Running second query.") - return nil - }) - fmt.Println("Transaction has an error:", err != nil) - - // Output: - // Running first query. - // Running second query. - // Transaction has an error: false -} - -func ExampleWithTransaction_two() { - // For this example we are using sqlmock, but you can use an actual - // connection with this function. - db, dbMock, err := sqlmock.New() - if err != nil { - panic(err) - } - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - fmt.Printf("there were unfulfilled expectations: %s\n", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - err = dbtools.WithTransaction(db, func(*sql.Tx) error { - fmt.Println("Running first query.") - return nil - }, func(*sql.Tx) error { - fmt.Println("Running second query.") - return errors.New("something happened") - }, func(*sql.Tx) error { - fmt.Println("Running third query.") - return nil - }) - fmt.Println("Transaction has an error:", err != nil) - - // Output: - // Running first query. - // Running second query. - // Transaction has an error: true -} - -func TestRetry(t *testing.T) { - t.Run("Delay", testRetryDelay) - t.Run("Retries", testRetryRetries) - t.Run("FunctionPanic", testRetryFunctionPanic) -} - -func testRetryDelay(t *testing.T) { - t.Parallel() - // In this setup, the delays would be 100, 200, 300, 400. So in 1 second - // there would be 4 calls. - count := 0 - delay := time.Millisecond * 100 - start := time.Now() - err := dbtools.Retry(4, delay, func(int) error { - count++ - return assert.AnError - }) - latency := time.Since(start) - assert.Equal(t, 4, count) - assert.Equal(t, assert.AnError, errors.Cause(err)) - if latency.Nanoseconds()-time.Second.Nanoseconds() > delay.Nanoseconds() { - t.Errorf("didn't finish in time: %d", latency.Nanoseconds()) - } -} - -func testRetryRetries(t *testing.T) { - t.Parallel() - retries := 100 - count := 0 - err := dbtools.Retry(retries, time.Nanosecond, func(int) error { - count++ - if count >= 20 { - return nil - } - return assert.AnError - }) - assert.NoError(t, err) - assert.Equal(t, 20, count) -} - -func testRetryFunctionPanic(t *testing.T) { - t.Parallel() - retries := 100 - count := 0 - assert.NotPanics(t, func() { - err := dbtools.Retry(retries, time.Nanosecond, func(int) error { - count++ - panic("for some reason") - }) - assert.Error(t, err) - }) - assert.Equal(t, retries, count) -} - -func ExampleRetry() { - err := dbtools.Retry(100, time.Nanosecond, func(i int) error { - fmt.Printf("Running iteration %d.\n", i+1) - if i < 1 { - return errors.New("ignored error") - } - return nil - }) - fmt.Println("Error:", err) - - // Output: - // Running iteration 1. - // Running iteration 2. - // Error: -} - -func ExampleRetry_two() { - err := dbtools.Retry(2, time.Nanosecond, func(i int) error { - fmt.Printf("Running iteration %d.\n", i+1) - return errors.New("some error") - }) - fmt.Println("Error:", err) - - // Output: - // Running iteration 1. - // Running iteration 2. - // Error: some error -} - -func TestRetryTransaction(t *testing.T) { - t.Run("Retry", testRetryTransactionRetry) - t.Run("ContextCancelled", testRetryTransactionContextCancelled) -} - -func testRetryTransactionRetry(t *testing.T) { - t.Run("ZeroTimes", testRetryTransactionRetryZeroTimes) - t.Run("Once", testRetryTransactionRetryOnce) - t.Run("MoreTime", testRetryTransactionRetryMoreTime) - t.Run("Error", testRetryTransactionRetryError) -} - -func testRetryTransactionRetryZeroTimes(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - - ctx := context.Background() - err = dbtools.RetryTransaction(ctx, db, 0, time.Nanosecond, func(*sql.Tx) error { - t.Error("didn't expect the function to be called") - return nil - }) - assert.NoError(t, err) -} - -func testRetryTransactionRetryOnce(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - - dbMock.ExpectBegin() - dbMock.ExpectCommit() - - calls := 0 - ctx := context.Background() - err = dbtools.RetryTransaction(ctx, db, 100, time.Nanosecond, func(*sql.Tx) error { - calls++ - return nil - }) - assert.NoError(t, err) - assert.Equal(t, calls, 1, "function calls") -} - -func testRetryTransactionRetryMoreTime(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - - dbMock.ExpectBegin() - dbMock.ExpectRollback() - dbMock.ExpectBegin() - dbMock.ExpectCommit() - - calls := 0 - ctx := context.Background() - err = dbtools.RetryTransaction(ctx, db, 100, time.Nanosecond, func(*sql.Tx) error { - calls++ - if calls < 2 { - return assert.AnError - } - return nil - }) - assert.NoError(t, err) - assert.Equal(t, calls, 2, "function calls") -} - -func ExampleRetryTransaction() { - // For this example we are using sqlmock, but you can use an actual - // connection with this function. - db, dbMock, err := sqlmock.New() - if err != nil { - panic(err) - } - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - fmt.Printf("there were unfulfilled expectations: %s\n", err) - } - }() - - dbMock.ExpectBegin() - dbMock.ExpectRollback() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - dbMock.ExpectBegin() - dbMock.ExpectCommit() - - calls := 0 - ctx := context.Background() - err = dbtools.RetryTransaction(ctx, db, 100, time.Millisecond*100, func(*sql.Tx) error { - calls++ - fmt.Printf("Running iteration %d.\n", calls) - if calls < 3 { - return errors.New("some error") - } - return nil - }) - fmt.Println("Error:", err) - - // Output: - // Running iteration 1. - // Running iteration 2. - // Running iteration 3. - // Error: -} - -func testRetryTransactionRetryError(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - - dbMock.ExpectBegin() - dbMock.ExpectRollback() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - - ctx := context.Background() - err = dbtools.RetryTransaction(ctx, db, 3, time.Nanosecond, func(*sql.Tx) error { - return assert.AnError - }) - mErr, ok := err.(*multierror.Error) - require.True(t, ok, "not a multierror") - var wantErr error - for _, e := range mErr.Errors { - if errors.Cause(e) == assert.AnError { - wantErr = e - } - } - assert.Equal(t, assert.AnError, wantErr, "want context cancelled instead") -} - -func testRetryTransactionContextCancelled(t *testing.T) { - t.Run("AtBeginning", testRetryTransactionContextCancelledAtBeginning) - t.Run("FirstRetry", testRetryTransactionContextCancelledFirstRetry) - t.Run("SecondRetry", testRetryTransactionContextCancelledSecondRetry) -} - -func testRetryTransactionContextCancelledAtBeginning(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - ctx, cancel := context.WithCancel(context.Background()) - cancel() - err = dbtools.RetryTransaction(ctx, db, 100, time.Nanosecond, func(*sql.Tx) error { - t.Error("didn't expect to get called") - return nil - }) - assert.Equal(t, ctx.Err(), err) -} - -func testRetryTransactionContextCancelledFirstRetry(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - called := false - err = dbtools.RetryTransaction(ctx, db, 100, time.Nanosecond, func(*sql.Tx) error { - assert.False(t, called, "didn't expect to get called") - cancel() - called = true - return assert.AnError - }) - assert.Equal(t, ctx.Err(), errors.Cause(err)) -} - -func testRetryTransactionContextCancelledSecondRetry(t *testing.T) { - t.Parallel() - db, dbMock, err := sqlmock.New() - require.NoError(t, err) - defer db.Close() - defer func() { - if err := dbMock.ExpectationsWereMet(); err != nil { - t.Errorf("there were unfulfilled expectations: %s", err) - } - }() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - dbMock.ExpectBegin() - dbMock.ExpectRollback() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - calls := 0 - err = dbtools.RetryTransaction(ctx, db, 100, time.Nanosecond, func(*sql.Tx) error { - calls++ - if calls < 2 { - return assert.AnError - } - cancel() - return assert.AnError - }) - assert.Equal(t, ctx.Err(), errors.Cause(err)) -} diff --git a/dbtesting/dbtesting_test.go b/dbtesting/dbtesting_test.go index 8d5b2ac..26bffc2 100644 --- a/dbtesting/dbtesting_test.go +++ b/dbtesting/dbtesting_test.go @@ -20,6 +20,7 @@ func TestOkValue(t *testing.T) { for name, tc := range tcs { tc := tc t.Run(name, func(t *testing.T) { + t.Parallel() db, mock, err := sqlmock.New() if err != nil { t.Fatalf("got %v, want nil", err) @@ -63,6 +64,7 @@ func ExampleOkValue() { } func TestValueRecorder(t *testing.T) { + t.Parallel() t.Run("Record", testValueRecorderRecord) t.Run("RecordPanic", testValueRecorderRecordPanic) t.Run("For", testValueRecorderFor) diff --git a/dbtesting/mocha_test.go b/dbtesting/mocha_test.go index 2c3f778..6b6a8f3 100644 --- a/dbtesting/mocha_test.go +++ b/dbtesting/mocha_test.go @@ -15,6 +15,7 @@ import ( ) func TestTerminal(t *testing.T) { + t.Parallel() t.Run("Start", testTerminalStart) t.Run("Specs", testTerminalSpecs) } diff --git a/go.mod b/go.mod index b1351bf..191c001 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,33 @@ module github.com/arsham/dbtools -go 1.14 +go 1.15 require ( github.com/DATA-DOG/go-sqlmock v1.5.0 - github.com/arsham/retry v0.1.1 + github.com/arsham/retry v0.2.0 + github.com/gogo/protobuf v1.2.1 // indirect + github.com/google/go-cmp v0.5.4 // indirect github.com/hashicorp/go-multierror v1.1.0 github.com/jackc/pgconn v1.6.4 github.com/jackc/pgproto3/v2 v2.0.4 // indirect github.com/jackc/pgx/v4 v4.8.1 + github.com/lib/pq v1.9.0 // indirect + github.com/onsi/ginkgo v1.14.2 // indirect + github.com/onsi/gomega v1.10.4 // indirect github.com/pkg/errors v0.9.1 github.com/sclevine/spec v1.4.0 + github.com/sirupsen/logrus v1.7.0 // indirect github.com/stretchr/objx v0.3.0 // indirect - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.7.0 github.com/testcontainers/testcontainers-go v0.7.0 - golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect + golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect + golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect + golang.org/x/sys v0.0.0-20210304152209-afaa3650a925 // indirect + golang.org/x/text v0.3.4 // indirect + golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a // indirect + google.golang.org/grpc v1.21.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/go.sum b/go.sum index 8ab3e5c..9347251 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -9,8 +8,8 @@ github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6 github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/arsham/retry v0.1.1 h1:49OILWGAtTdFVQNi/yEmbfbc48zsSFVAqe8XtFhzcKo= -github.com/arsham/retry v0.1.1/go.mod h1:g6PJOHhR9WMEnzrmnRrDjGU7udI/Bh9x10Dg+C+0+cg= +github.com/arsham/retry v0.2.0 h1:0yFArG6vhUZAqkIUdApRhWuwnpBsQQX+UqPTnJhML9I= +github.com/arsham/retry v0.2.0/go.mod h1:pnsvdnYLFbkKLxLPOCOVWO+hiI/4HV9U/rfm+bk8EK4= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -20,10 +19,8 @@ github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVl github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -35,8 +32,9 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -50,15 +48,27 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -71,7 +81,6 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= @@ -99,7 +108,6 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.0.2 h1:q1Hsy66zh4vuNsajBUF2PNqfAMMfxU5mk594lPE9vjY= github.com/jackc/pgproto3/v2 v2.0.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.4 h1:RHkX5ZUD9bl/kn0f9dYUWs1N7Nwvo1wwUYvKiR26Zco= github.com/jackc/pgproto3/v2 v2.0.4/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= @@ -128,14 +136,12 @@ github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv github.com/jackc/puddle v1.1.1 h1:PJAw7H/9hoWC4Kf3J8iNmL1SwA6E8vfsLqBiL+F6CtI= github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= 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= @@ -144,17 +150,16 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -162,11 +167,18 @@ github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8d github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M= +github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.4 h1:NiTx7EEvBzu9sFOD1zORteLSt3o8gnlvZZwSE9TnY9U= +github.com/onsi/gomega v1.10.4/go.mod h1:g/HbgYopi++010VEqkFgJHKC09uJiW9UkXvMUuKHUCQ= github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= @@ -191,23 +203,22 @@ github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoM github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/testcontainers/testcontainers-go v0.7.0 h1:IaAsq5JY49GhDgCUKY87mo6JeOLOwp321iEP/SQjJKE= github.com/testcontainers/testcontainers-go v0.7.0/go.mod h1:4dloDPrC94+8ebXA+Iei3Jy+gxF6uHQssJkB3mlP9Rg= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -228,24 +239,32 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -256,18 +275,31 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304152209-afaa3650a925 h1:Ee/Y8w57dY5pI4wYh0ZdFQn++NMCNRNIOKXCZ/82iUM= +golang.org/x/sys v0.0.0-20210304152209-afaa3650a925/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180810170437-e96c4e24768d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -277,37 +309,46 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a h1:Ob5/580gVHBJZgXnff1cZDbG+xLtMVE5mDRTe+nIsX4= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v0.0.0-20181223230014-1083505acf35 h1:zpdCK+REwbk+rqjJmHhiCN6iBIigrZ39glqSF0P3KF0= gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/helper_test.go b/helper_test.go index 9583f84..6ec0b40 100644 --- a/helper_test.go +++ b/helper_test.go @@ -30,9 +30,6 @@ func assertInError(t *testing.T, haystack, needle error) bool { t.Errorf("want %v in %v", needle, haystack) return false } - if errors.Cause(haystack) == needle { - return true - } if errors.Is(haystack, needle) { return true } @@ -41,12 +38,12 @@ func assertInError(t *testing.T, haystack, needle error) bool { "want\n\t%v\nin\n\t%v", needle, haystack, ) } - merr, ok := errors.Cause(haystack).(*multierror.Error) - if !ok { + var merr *multierror.Error + if !errors.As(haystack, &merr) { return contains() } for _, err := range merr.Errors { - if errors.Cause(err) == needle { + if errors.Is(needle, err) { return true } }