mirror of
https://github.com/caddyserver/caddy.git
synced 2026-04-01 14:52:20 -04:00
169 lines
3.8 KiB
Go
169 lines
3.8 KiB
Go
package caddyhttp
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestHandlerErrorError(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
err HandlerError
|
|
contains []string
|
|
}{
|
|
{
|
|
name: "full error",
|
|
err: HandlerError{
|
|
ID: "abc123",
|
|
StatusCode: 404,
|
|
Err: fmt.Errorf("not found"),
|
|
Trace: "pkg.Func (file.go:10)",
|
|
},
|
|
contains: []string{"abc123", "404", "not found", "pkg.Func"},
|
|
},
|
|
{
|
|
name: "empty error",
|
|
err: HandlerError{},
|
|
contains: []string{},
|
|
},
|
|
{
|
|
name: "error with only status code",
|
|
err: HandlerError{
|
|
StatusCode: 500,
|
|
},
|
|
contains: []string{"500"},
|
|
},
|
|
{
|
|
name: "error with only message",
|
|
err: HandlerError{
|
|
Err: fmt.Errorf("something broke"),
|
|
},
|
|
contains: []string{"something broke"},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := tt.err.Error()
|
|
for _, needle := range tt.contains {
|
|
if !strings.Contains(result, needle) {
|
|
t.Errorf("Error() = %q, should contain %q", result, needle)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHandlerErrorUnwrap(t *testing.T) {
|
|
originalErr := fmt.Errorf("original error")
|
|
he := HandlerError{Err: originalErr}
|
|
|
|
unwrapped := he.Unwrap()
|
|
if unwrapped != originalErr {
|
|
t.Errorf("Unwrap() = %v, want %v", unwrapped, originalErr)
|
|
}
|
|
}
|
|
|
|
func TestError(t *testing.T) {
|
|
t.Run("creates error with ID and trace", func(t *testing.T) {
|
|
err := fmt.Errorf("test error")
|
|
he := Error(500, err)
|
|
|
|
if he.StatusCode != 500 {
|
|
t.Errorf("StatusCode = %d, want 500", he.StatusCode)
|
|
}
|
|
if he.ID == "" {
|
|
t.Error("ID should not be empty")
|
|
}
|
|
if len(he.ID) != 9 {
|
|
t.Errorf("ID length = %d, want 9", len(he.ID))
|
|
}
|
|
if he.Trace == "" {
|
|
t.Error("Trace should not be empty")
|
|
}
|
|
if he.Err != err {
|
|
t.Error("Err should be the original error")
|
|
}
|
|
})
|
|
|
|
t.Run("unwraps existing HandlerError", func(t *testing.T) {
|
|
inner := HandlerError{
|
|
ID: "existing_id",
|
|
StatusCode: 404,
|
|
Err: fmt.Errorf("not found"),
|
|
Trace: "existing trace",
|
|
}
|
|
|
|
he := Error(500, inner)
|
|
|
|
// Should keep existing ID
|
|
if he.ID != "existing_id" {
|
|
t.Errorf("ID = %q, want 'existing_id'", he.ID)
|
|
}
|
|
// Should keep existing StatusCode
|
|
if he.StatusCode != 404 {
|
|
t.Errorf("StatusCode = %d, want 404 (existing)", he.StatusCode)
|
|
}
|
|
// Should keep existing Trace
|
|
if he.Trace != "existing trace" {
|
|
t.Errorf("Trace = %q, want 'existing trace'", he.Trace)
|
|
}
|
|
})
|
|
|
|
t.Run("fills missing fields in existing HandlerError", func(t *testing.T) {
|
|
inner := HandlerError{
|
|
Err: fmt.Errorf("inner error"),
|
|
// ID, StatusCode, and Trace are all empty
|
|
}
|
|
|
|
he := Error(503, inner)
|
|
|
|
if he.ID == "" {
|
|
t.Error("should fill missing ID")
|
|
}
|
|
if he.StatusCode != 503 {
|
|
t.Errorf("should fill missing StatusCode with %d, got %d", 503, he.StatusCode)
|
|
}
|
|
if he.Trace == "" {
|
|
t.Error("should fill missing Trace")
|
|
}
|
|
})
|
|
|
|
t.Run("generates unique IDs", func(t *testing.T) {
|
|
ids := make(map[string]struct{})
|
|
for i := 0; i < 100; i++ {
|
|
he := Error(500, fmt.Errorf("error %d", i))
|
|
if _, exists := ids[he.ID]; exists {
|
|
t.Errorf("duplicate ID generated: %s", he.ID)
|
|
}
|
|
ids[he.ID] = struct{}{}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestErrorAsHandlerError(t *testing.T) {
|
|
he := Error(404, fmt.Errorf("not found"))
|
|
var target HandlerError
|
|
if !errors.As(he, &target) {
|
|
t.Error("Error() result should be assertable as HandlerError via errors.As")
|
|
}
|
|
}
|
|
|
|
func TestHandlerErrorWithWrappedError(t *testing.T) {
|
|
// Test that errors.As can unwrap a wrapped HandlerError
|
|
inner := HandlerError{
|
|
ID: "inner",
|
|
StatusCode: 404,
|
|
Err: fmt.Errorf("inner error"),
|
|
}
|
|
wrapped := fmt.Errorf("wrapped: %w", inner)
|
|
|
|
he := Error(500, wrapped)
|
|
// Since wrapped contains a HandlerError, it should be unwrapped
|
|
if he.ID != "inner" {
|
|
t.Errorf("should unwrap to inner ID 'inner', got %q", he.ID)
|
|
}
|
|
}
|