coder/coderd/database/tx_test.go

82 lines
1.9 KiB
Go

package database_test
import (
"database/sql"
"testing"
"github.com/lib/pq"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbmock"
)
func TestReadModifyUpdate_OK(t *testing.T) {
t.Parallel()
mDB := dbmock.NewMockStore(gomock.NewController(t))
mDB.EXPECT().
InTx(gomock.Any(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}).
Times(1).
Return(nil)
err := database.ReadModifyUpdate(mDB, func(tx database.Store) error {
return nil
})
require.NoError(t, err)
}
func TestReadModifyUpdate_RetryOK(t *testing.T) {
t.Parallel()
mDB := dbmock.NewMockStore(gomock.NewController(t))
firstUpdate := mDB.EXPECT().
InTx(gomock.Any(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}).
Times(1).
Return(&pq.Error{Code: pq.ErrorCode("40001")})
mDB.EXPECT().
InTx(gomock.Any(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}).
After(firstUpdate).
Times(1).
Return(nil)
err := database.ReadModifyUpdate(mDB, func(tx database.Store) error {
return nil
})
require.NoError(t, err)
}
func TestReadModifyUpdate_HardError(t *testing.T) {
t.Parallel()
mDB := dbmock.NewMockStore(gomock.NewController(t))
mDB.EXPECT().
InTx(gomock.Any(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}).
Times(1).
Return(xerrors.New("a bad thing happened"))
err := database.ReadModifyUpdate(mDB, func(tx database.Store) error {
return nil
})
require.ErrorContains(t, err, "a bad thing happened")
}
func TestReadModifyUpdate_TooManyRetries(t *testing.T) {
t.Parallel()
mDB := dbmock.NewMockStore(gomock.NewController(t))
mDB.EXPECT().
InTx(gomock.Any(), &sql.TxOptions{Isolation: sql.LevelRepeatableRead}).
Times(5).
Return(&pq.Error{Code: pq.ErrorCode("40001")})
err := database.ReadModifyUpdate(mDB, func(tx database.Store) error {
return nil
})
require.ErrorContains(t, err, "too many errors")
}