diff --git a/storage/s3.go b/storage/s3.go index 3313be66e..1232933ac 100644 --- a/storage/s3.go +++ b/storage/s3.go @@ -84,7 +84,7 @@ func parseEndpoint(endpoint string) (urlpkg.URL, error) { u, err := urlpkg.Parse(endpoint) if err != nil { - return sentinelURL, fmt.Errorf("parse endpoint %q: %v", endpoint, err) + return sentinelURL, fmt.Errorf("parse endpoint %q: %w", endpoint, err) } return *u, nil @@ -1361,7 +1361,7 @@ func setSessionRegion(ctx context.Context, sess *session.Session, bucket string) } // don't deny any request to the service if region auto-fetching // receives an error. Delegate error handling to command execution. - err = fmt.Errorf("session: fetching region failed: %v", err) + err = fmt.Errorf("session: fetching region failed: %w", err) msg := log.ErrorMessage{Err: err.Error()} log.Error(msg) } else { diff --git a/storage/s3_test.go b/storage/s3_test.go index 11b52ebc3..82595cf66 100644 --- a/storage/s3_test.go +++ b/storage/s3_test.go @@ -40,6 +40,45 @@ func TestS3ImplementsStorageInterface(t *testing.T) { } } +func TestParseEndpoint(t *testing.T) { + t.Run("empty endpoint returns sentinel", func(t *testing.T) { + got, err := parseEndpoint("") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got != sentinelURL { + t.Errorf("got %v, want sentinel url", got) + } + }) + + t.Run("valid endpoint", func(t *testing.T) { + got, err := parseEndpoint("https://example.com:9000") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got.Host != "example.com:9000" || got.Scheme != "https" { + t.Errorf("got %v, want https://example.com:9000", got.String()) + } + }) + + t.Run("invalid endpoint wraps url.Error", func(t *testing.T) { + const endpoint = "http://[::1" + _, err := parseEndpoint(endpoint) + if err == nil { + t.Fatal("expected error, got nil") + } + + var urlErr *urlpkg.Error + if !errors.As(err, &urlErr) { + t.Errorf("expected error to wrap *url.Error, got %T: %v", err, err) + } + + if want := fmt.Sprintf("parse endpoint %q: ", endpoint); !strings.HasPrefix(err.Error(), want) { + t.Errorf("got %q, want prefix %q", err.Error(), want) + } + }) +} + func TestNewSessionPathStyle(t *testing.T) { testcases := []struct { name string