mirror of
https://github.com/hanzo-fi/go-libs.git
synced 2026-10-30 20:53:44 +00:00
353 lines
9.2 KiB
Go
353 lines
9.2 KiB
Go
package postgres_test
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/jackc/pgx/v5/pgconn"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/hanzo-fi/go-libs/v5/pkg/storage/postgres"
|
|
)
|
|
|
|
func TestResolveError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("NilError", func(t *testing.T) {
|
|
t.Parallel()
|
|
err := postgres.ResolveError(nil)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("NotFoundError", func(t *testing.T) {
|
|
t.Parallel()
|
|
err := postgres.ResolveError(sql.ErrNoRows)
|
|
require.ErrorIs(t, err, postgres.ErrNotFound)
|
|
})
|
|
|
|
t.Run("ValidationFailedError", func(t *testing.T) {
|
|
t.Parallel()
|
|
tests := map[string]*pgconn.PgError{
|
|
"not-null constraint violation": {
|
|
Code: "23502",
|
|
Message: "not-null constraint violation",
|
|
},
|
|
"invalid input syntax for type": {
|
|
Code: "22P02",
|
|
Message: "invalid input syntax for type",
|
|
},
|
|
}
|
|
|
|
for name, tt := range tests {
|
|
name := name
|
|
tt := tt
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
err := postgres.ResolveError(tt)
|
|
require.Error(t, err)
|
|
|
|
var validationErr postgres.ErrValidationFailed
|
|
require.ErrorAs(t, err, &validationErr)
|
|
require.Equal(t, tt.Error(), validationErr.Error())
|
|
require.Equal(t, tt, validationErr.Unwrap())
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("FKConstraintFailedError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23503",
|
|
Message: "foreign key constraint violation",
|
|
ConstraintName: "users_role_id_fkey",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.Error(t, err)
|
|
|
|
var fkErr postgres.ErrFKConstraintFailed
|
|
require.ErrorAs(t, err, &fkErr)
|
|
require.Equal(t, "users_role_id_fkey", fkErr.GetConstraint())
|
|
require.Equal(t, pgErr.Error(), fkErr.Error())
|
|
require.Equal(t, pgErr, fkErr.Unwrap())
|
|
})
|
|
|
|
t.Run("ConstraintsFailedError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23505",
|
|
Message: "unique constraint violation",
|
|
ConstraintName: "users_email_key",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.Error(t, err)
|
|
|
|
var constraintsErr postgres.ErrConstraintsFailed
|
|
require.ErrorAs(t, err, &constraintsErr)
|
|
require.Equal(t, "users_email_key", constraintsErr.GetConstraint())
|
|
require.Equal(t, pgErr.Error(), constraintsErr.Error())
|
|
require.Equal(t, pgErr, constraintsErr.Unwrap())
|
|
})
|
|
|
|
t.Run("TooManyClientError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "53300",
|
|
Message: "too many connections",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.Error(t, err)
|
|
|
|
var tooManyClientErr postgres.ErrTooManyClient
|
|
require.ErrorAs(t, err, &tooManyClientErr)
|
|
require.Equal(t, pgErr.Error(), tooManyClientErr.Error())
|
|
})
|
|
|
|
t.Run("DeadlockDetectedError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "40P01",
|
|
Message: "deadlock detected",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.ErrorIs(t, err, postgres.ErrDeadlockDetected)
|
|
})
|
|
|
|
t.Run("ReadOnlyTransactionError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "25006",
|
|
Message: "cannot execute CREATE TABLE in a read-only transaction",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.ErrorIs(t, err, postgres.ErrReadOnlyTransaction)
|
|
})
|
|
|
|
t.Run("SerializationError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "40001",
|
|
Message: "serialization failure",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.ErrorIs(t, err, postgres.ErrSerialization)
|
|
})
|
|
|
|
t.Run("MissingTableError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "42P01",
|
|
Message: "relation does not exist",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.ErrorIs(t, err, postgres.ErrMissingTable)
|
|
})
|
|
|
|
t.Run("MissingSchemaError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "3F000",
|
|
Message: "schema does not exist",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.ErrorIs(t, err, postgres.ErrMissingSchema)
|
|
})
|
|
|
|
t.Run("RaisedExceptionError", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "P0001",
|
|
Message: "custom exception message",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
require.Error(t, err)
|
|
|
|
var raisedErr postgres.ErrRaisedException
|
|
require.ErrorAs(t, err, &raisedErr)
|
|
require.Equal(t, "custom exception message", raisedErr.GetMessage())
|
|
require.Equal(t, pgErr.Error(), raisedErr.Error())
|
|
require.Equal(t, pgErr, raisedErr.Unwrap())
|
|
})
|
|
|
|
t.Run("OtherError", func(t *testing.T) {
|
|
t.Parallel()
|
|
originalErr := errors.New("some other error")
|
|
err := postgres.ResolveError(originalErr)
|
|
require.Equal(t, originalErr, err)
|
|
})
|
|
}
|
|
|
|
func TestIsNotFoundError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("WithNotFoundError", func(t *testing.T) {
|
|
t.Parallel()
|
|
require.True(t, postgres.IsNotFoundError(postgres.ErrNotFound))
|
|
})
|
|
|
|
t.Run("WithWrappedNotFoundError", func(t *testing.T) {
|
|
t.Parallel()
|
|
wrappedErr := errors.New("wrapped not found error")
|
|
err := errors.Join(wrappedErr, postgres.ErrNotFound)
|
|
require.True(t, postgres.IsNotFoundError(err))
|
|
})
|
|
|
|
t.Run("WithOtherError", func(t *testing.T) {
|
|
t.Parallel()
|
|
err := errors.New("some other error")
|
|
require.False(t, postgres.IsNotFoundError(err))
|
|
})
|
|
|
|
t.Run("WithNilError", func(t *testing.T) {
|
|
t.Parallel()
|
|
require.False(t, postgres.IsNotFoundError(nil))
|
|
})
|
|
}
|
|
|
|
func TestErrConstraintsFailed(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("Is", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23505",
|
|
Message: "unique constraint violation",
|
|
ConstraintName: "users_email_key",
|
|
}
|
|
constraintsErr := postgres.ErrConstraintsFailed{} // Create a zero value for comparison
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
require.True(t, errors.Is(err, constraintsErr))
|
|
})
|
|
}
|
|
|
|
func TestErrRaisedException(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("Is", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "P0001",
|
|
Message: "custom exception message",
|
|
}
|
|
raisedErr := postgres.ErrRaisedException{} // Create a zero value for comparison
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
require.True(t, errors.Is(err, raisedErr))
|
|
})
|
|
}
|
|
|
|
func TestErrTooManyClient(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("Unwrap", func(t *testing.T) {
|
|
t.Parallel()
|
|
originalErr := &pgconn.PgError{
|
|
Code: "53300",
|
|
Message: "too many connections",
|
|
}
|
|
err := postgres.ResolveError(originalErr)
|
|
|
|
var tooManyClientErr postgres.ErrTooManyClient
|
|
require.ErrorAs(t, err, &tooManyClientErr)
|
|
|
|
// Since ErrTooManyClient doesn't have an Unwrap method, we can't test it directly
|
|
// But we can verify the Error method returns the original error message
|
|
require.Equal(t, originalErr.Error(), tooManyClientErr.Error())
|
|
})
|
|
}
|
|
|
|
func TestErrFKConstraintFailed(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("Is", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23503",
|
|
Message: "foreign key constraint violation",
|
|
ConstraintName: "users_role_id_fkey",
|
|
}
|
|
fkErr := postgres.ErrFKConstraintFailed{} // Create a zero value for comparison
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
require.True(t, errors.Is(err, fkErr))
|
|
})
|
|
}
|
|
|
|
func TestErrValidationFailed(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("Is", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23502",
|
|
Message: "not-null constraint violation",
|
|
}
|
|
validationErr := postgres.ErrValidationFailed{} // Create a zero value for comparison
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
require.True(t, errors.Is(err, validationErr))
|
|
})
|
|
}
|
|
|
|
func TestConstructorFunctions(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("newErrFkConstraintFailed", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23503",
|
|
Message: "foreign key constraint violation",
|
|
ConstraintName: "users_role_id_fkey",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
var fkErr postgres.ErrFKConstraintFailed
|
|
require.ErrorAs(t, err, &fkErr)
|
|
require.Equal(t, pgErr, fkErr.Unwrap())
|
|
require.Equal(t, "users_role_id_fkey", fkErr.GetConstraint())
|
|
})
|
|
|
|
t.Run("newErrNonNullValidationFailed", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23502",
|
|
Message: "not-null constraint violation",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
var validationErr postgres.ErrValidationFailed
|
|
require.ErrorAs(t, err, &validationErr)
|
|
require.Equal(t, pgErr, validationErr.Unwrap())
|
|
})
|
|
|
|
t.Run("newErrConstraintsFailed", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "23505",
|
|
Message: "unique constraint violation",
|
|
ConstraintName: "users_email_key",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
var constraintsErr postgres.ErrConstraintsFailed
|
|
require.ErrorAs(t, err, &constraintsErr)
|
|
require.Equal(t, pgErr, constraintsErr.Unwrap())
|
|
require.Equal(t, "users_email_key", constraintsErr.GetConstraint())
|
|
})
|
|
|
|
t.Run("newErrRaisedException", func(t *testing.T) {
|
|
t.Parallel()
|
|
pgErr := &pgconn.PgError{
|
|
Code: "P0001",
|
|
Message: "custom exception message",
|
|
}
|
|
err := postgres.ResolveError(pgErr)
|
|
|
|
var raisedErr postgres.ErrRaisedException
|
|
require.ErrorAs(t, err, &raisedErr)
|
|
require.Equal(t, pgErr, raisedErr.Unwrap())
|
|
require.Equal(t, "custom exception message", raisedErr.GetMessage())
|
|
})
|
|
}
|