diff --git a/pkg/mining/errors_test.go b/pkg/mining/errors_test.go index 06f6245..b5a7a1a 100644 --- a/pkg/mining/errors_test.go +++ b/pkg/mining/errors_test.go @@ -6,7 +6,8 @@ import ( "testing" ) -func TestMiningError_Error(t *testing.T) { +// TestErrors_Error_Good verifies the error string format with no cause +func TestErrors_Error_Good(t *testing.T) { err := NewMiningError(ErrCodeMinerNotFound, "miner not found") expected := "MINER_NOT_FOUND: miner not found" if err.Error() != expected { @@ -14,22 +15,22 @@ func TestMiningError_Error(t *testing.T) { } } -func TestMiningError_ErrorWithCause(t *testing.T) { +// TestErrors_Error_Bad verifies the error string includes the underlying cause +func TestErrors_Error_Bad(t *testing.T) { cause := errors.New("underlying error") err := NewMiningError(ErrCodeStartFailed, "failed to start").WithCause(cause) - // Should include cause in error message if err.Cause != cause { t.Error("Cause was not set") } - // Should be unwrappable if errors.Unwrap(err) != cause { t.Error("Unwrap did not return cause") } } -func TestMiningError_WithDetails(t *testing.T) { +// TestErrors_WithDetails_Good verifies details are attached to the error +func TestErrors_WithDetails_Good(t *testing.T) { err := NewMiningError(ErrCodeInvalidConfig, "invalid config"). WithDetails("port must be between 1024 and 65535") @@ -38,7 +39,8 @@ func TestMiningError_WithDetails(t *testing.T) { } } -func TestMiningError_WithSuggestion(t *testing.T) { +// TestErrors_WithSuggestion_Good verifies suggestions are attached to the error +func TestErrors_WithSuggestion_Good(t *testing.T) { err := NewMiningError(ErrCodeConnectionFailed, "connection failed"). WithSuggestion("check your network") @@ -47,8 +49,9 @@ func TestMiningError_WithSuggestion(t *testing.T) { } } -func TestMiningError_StatusCode(t *testing.T) { - tests := []struct { +// TestErrors_StatusCode_Good verifies each error constructor returns the correct HTTP status +func TestErrors_StatusCode_Good(t *testing.T) { + cases := []struct { name string err *MiningError expected int @@ -61,17 +64,18 @@ func TestMiningError_StatusCode(t *testing.T) { {"timeout", ErrTimeout("operation"), http.StatusGatewayTimeout}, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.err.StatusCode() != tt.expected { - t.Errorf("Expected status %d, got %d", tt.expected, tt.err.StatusCode()) + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if c.err.StatusCode() != c.expected { + t.Errorf("Expected status %d, got %d", c.expected, c.err.StatusCode()) } }) } } -func TestMiningError_IsRetryable(t *testing.T) { - tests := []struct { +// TestErrors_IsRetryable_Good verifies retryable vs non-retryable classifications +func TestErrors_IsRetryable_Good(t *testing.T) { + cases := []struct { name string err *MiningError retryable bool @@ -86,17 +90,18 @@ func TestMiningError_IsRetryable(t *testing.T) { {"database error", ErrDatabaseError("query"), true}, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.err.IsRetryable() != tt.retryable { - t.Errorf("Expected retryable=%v, got %v", tt.retryable, tt.err.IsRetryable()) + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if c.err.IsRetryable() != c.retryable { + t.Errorf("Expected retryable=%v, got %v", c.retryable, c.err.IsRetryable()) } }) } } -func TestPredefinedErrors(t *testing.T) { - tests := []struct { +// TestErrors_PredefinedErrors_Good verifies each error constructor sets the correct code and message +func TestErrors_PredefinedErrors_Good(t *testing.T) { + cases := []struct { name string err *MiningError code string @@ -117,19 +122,20 @@ func TestPredefinedErrors(t *testing.T) { {"ErrInternal", ErrInternal("unexpected error"), ErrCodeInternalError}, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.err.Code != tt.code { - t.Errorf("Expected code %s, got %s", tt.code, tt.err.Code) + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if c.err.Code != c.code { + t.Errorf("Expected code %s, got %s", c.code, c.err.Code) } - if tt.err.Message == "" { + if c.err.Message == "" { t.Error("Message should not be empty") } }) } } -func TestMiningError_Chaining(t *testing.T) { +// TestErrors_Chaining_Ugly verifies error chaining survives multiple WithCause/WithDetails/WithSuggestion calls +func TestErrors_Chaining_Ugly(t *testing.T) { cause := errors.New("network timeout") err := ErrConnectionFailed("pool:3333"). WithCause(cause).