package fetcher import ( "fmt" "github.com/stretchr/testify/assert" "net" "net/url" "testing" ) func TestClassifyHTTPStatus401(test *testing.T) { fetchError := ClassifyError(nil, 401) assert.Equal(test, 401, fetchError.StatusCode) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "authentication") } func TestClassifyHTTPStatus403(test *testing.T) { fetchError := ClassifyError(nil, 403) assert.Equal(test, 403, fetchError.StatusCode) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "forbidden") } func TestClassifyHTTPStatus404(test *testing.T) { fetchError := ClassifyError(nil, 404) assert.Equal(test, 404, fetchError.StatusCode) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "not found") } func TestClassifyHTTPStatus410(test *testing.T) { fetchError := ClassifyError(nil, 410) assert.Equal(test, 410, fetchError.StatusCode) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "permanently removed") } func TestClassifyHTTPStatus429(test *testing.T) { fetchError := ClassifyError(nil, 429) assert.Equal(test, 429, fetchError.StatusCode) assert.True(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "rate limited") } func TestClassifyHTTPServerErrors(test *testing.T) { serverErrorCodes := []int{500, 502, 503, 504} for _, statusCode := range serverErrorCodes { test.Run(fmt.Sprintf("status_%d", statusCode), func(test *testing.T) { fetchError := ClassifyError(nil, statusCode) assert.Equal(test, statusCode, fetchError.StatusCode) assert.True(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "server error") }) } } func TestClassifyHTTPUnknownClientError(test *testing.T) { fetchError := ClassifyError(nil, 418) assert.Equal(test, 418, fetchError.StatusCode) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "418") } func TestClassifyDNSNotFoundError(test *testing.T) { dnsError := &net.DNSError{ Name: "nonexistent.example.com", IsNotFound: true, } fetchError := ClassifyError(dnsError, 0) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "DNS") } func TestClassifyDNSTemporaryError(test *testing.T) { dnsError := &net.DNSError{ Name: "flaky.example.com", IsNotFound: false, } fetchError := ClassifyError(dnsError, 0) assert.True(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "DNS") } func TestClassifyTimeoutError(test *testing.T) { timeoutError := &url.Error{ Op: "Get", URL: "https://slow.example.com", Err: &timeoutErr{}, } fetchError := ClassifyError(timeoutError, 0) assert.True(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "timed out") } type timeoutErr struct{} func (timeoutError *timeoutErr) Error() string { return "connection timed out" } func (timeoutError *timeoutErr) Timeout() bool { return true } func (timeoutError *timeoutErr) Temporary() bool { return true } func TestClassifyNetworkOpError(test *testing.T) { opError := &net.OpError{ Op: "dial", Net: "tcp", Err: fmt.Errorf("connection refused"), } fetchError := ClassifyError(opError, 0) assert.True(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "network") } func TestClassifyTLSError(test *testing.T) { tlsError := fmt.Errorf("tls: handshake failure") fetchError := ClassifyError(tlsError, 0) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "TLS") } func TestClassifyCertificateError(test *testing.T) { certError := fmt.Errorf("x509: certificate has expired") fetchError := ClassifyError(certError, 0) assert.False(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "certificate") } func TestClassifyNilError(test *testing.T) { fetchError := ClassifyError(nil, 0) assert.True(test, fetchError.Retryable) assert.Contains(test, fetchError.UserMessage, "unknown") } func TestFetchErrorInterface(test *testing.T) { underlyingError := fmt.Errorf("some network issue") fetchError := &FetchError{ StatusCode: 0, UserMessage: "test error", Retryable: true, UnderlyingError: underlyingError, } assert.Contains(test, fetchError.Error(), "test error") assert.Contains(test, fetchError.Error(), "some network issue") assert.Equal(test, underlyingError, fetchError.Unwrap()) } func TestFetchErrorWithoutUnderlying(test *testing.T) { fetchError := &FetchError{ UserMessage: "standalone error", } assert.Equal(test, "standalone error", fetchError.Error()) assert.Nil(test, fetchError.Unwrap()) }