Рыба проекта. Минимальная функциональность
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
package pgdump
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Options holds configuration for the pg_dump invocation.
|
||||
type Options struct {
|
||||
Host string
|
||||
Port int
|
||||
Database string
|
||||
User string
|
||||
Password string
|
||||
Key string
|
||||
ExcludeTables []string
|
||||
}
|
||||
|
||||
// Dumper defines the contract for executing pg_dump.
|
||||
type Dumper interface {
|
||||
Dump(
|
||||
ctx context.Context,
|
||||
opts Options,
|
||||
sink io.Writer,
|
||||
) error
|
||||
}
|
||||
|
||||
// pgDumpFailedError is returned when pg_dump exits with a non-zero status.
|
||||
type pgDumpFailedError struct {
|
||||
exitCode int
|
||||
}
|
||||
|
||||
func (e *pgDumpFailedError) Error() string {
|
||||
return fmt.Sprintf("pg_dump failed with exit code %d", e.exitCode)
|
||||
}
|
||||
|
||||
// Is reports whether target is a pgDumpFailedError with the same exit code.
|
||||
func (e *pgDumpFailedError) Is(target error) bool {
|
||||
other, ok := target.(*pgDumpFailedError)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return e.exitCode == other.exitCode
|
||||
}
|
||||
|
||||
// ErrPgDumpFailed creates a new pg_dump failed error with the given exit code.
|
||||
func ErrPgDumpFailed(exitCode int) error {
|
||||
return &pgDumpFailedError{exitCode: exitCode}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package pgdump
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestErrPgDumpFailed_Error(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
exitCode int
|
||||
want string
|
||||
}{
|
||||
{name: "zero", exitCode: 0, want: "pg_dump failed with exit code 0"},
|
||||
{name: "one", exitCode: 1, want: "pg_dump failed with exit code 1"},
|
||||
{name: "large", exitCode: 137, want: "pg_dump failed with exit code 137"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := ErrPgDumpFailed(tc.exitCode)
|
||||
if err == nil {
|
||||
t.Fatalf("ErrPgDumpFailed(%d) returned nil, want error", tc.exitCode)
|
||||
}
|
||||
if got := err.Error(); got != tc.want {
|
||||
t.Fatalf("Error() = %q, want %q", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrPgDumpFailed_Is(t *testing.T) {
|
||||
base := ErrPgDumpFailed(1)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
target error
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "same exit code",
|
||||
target: ErrPgDumpFailed(1),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "different exit code",
|
||||
target: ErrPgDumpFailed(2),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "unrelated error type",
|
||||
target: errors.New("something else"),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
// Is does not unwrap target: a fmt.Errorf-wrapped pgDumpFailedError
|
||||
// fails the exact type check, so errors.Is reports false here.
|
||||
name: "wrapped same-type error",
|
||||
target: fmt.Errorf("wrapped: %w", ErrPgDumpFailed(1)),
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := errors.Is(base, tc.target); got != tc.want {
|
||||
t.Fatalf("errors.Is(%v, %v) = %v, want %v", base, tc.target, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user