Skip to content

Commit

Permalink
Add OutOfRangeError and handle it properly
Browse files Browse the repository at this point in the history
  • Loading branch information
epapbak committed Oct 4, 2024
1 parent f96e307 commit 6092b48
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 18 deletions.
9 changes: 4 additions & 5 deletions types/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@

package types

import (
"errors"
)

// Uint64ToUint32 safely converts a uint64 into a uint32 without overflow
func Uint64ToUint32(v uint64) (uint32, error) {
// Check for overflow without casting
if v > uint64(^uint32(0)) { // ^uint32(0) is the maximum uint32 value (4,294,967,295)
return 0, errors.New("value exceeds uint32 range")
return 0, &OutOfRangeError{
Value: v,
Type: "uint32",
}
}

return uint32(v), nil // #nosec G103: safe after bounds check
Expand Down
33 changes: 21 additions & 12 deletions types/conversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,33 @@ func TestUint64ToUint32(t *testing.T) {
name string
input uint64
want uint32
wantErr bool
errType error
}{
{"Zero", 0, 0, false},
{"Max uint32", 4294967295, 4294967295, false},
{"Overflow", 4294967296, 0, true},
{"Large overflow", 18446744073709551615, 0, true},
{"Mid-range value", 2147483648, 2147483648, false},
{"Zero", 0, 0, nil},
{"Max uint32", 4294967295, 4294967295, nil},
{"Overflow", 4294967296, 0, &OutOfRangeError{}},
{"Large overflow", 18446744073709551615, 0, &OutOfRangeError{}},
{"Mid-range value", 2147483648, 2147483648, nil},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Uint64ToUint32(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("Uint64ToUint32() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Uint64ToUint32() = %v, want %v", got, tt.want)
if tt.errType != nil {
// Check if the error is of the expected type
if err == nil {
t.Errorf("Expected error type %T, got no error", tt.errType)
} else if _, ok := err.(*OutOfRangeError); !ok {
t.Errorf("Expected error type *OutOfRangeError, got %T", err)
}
} else {
if err != nil {
t.Errorf("Uint64ToUint32() error = %v, want no error", err)
return
}
if got != tt.want {
t.Errorf("Uint64ToUint32() = %v, want %v", got, tt.want)
}
}
})
}
Expand Down
13 changes: 12 additions & 1 deletion types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,25 @@ func (e *ValidationError) Error() string {
)
}

// OutOfRangeError indicates that a value is outside the expected range.
type OutOfRangeError struct {
Value uint64
Type string
}

// Error returns a formatted error string for the OutOfRangeError.
func (e *OutOfRangeError) Error() string {
return fmt.Sprintf("value %d out of range for %s", e.Value, e.Type)
}

// HandleServerError handles separate server errors and sends appropriate responses
func HandleServerError(writer http.ResponseWriter, err error) {
var level = log.Warn() // set the default log level for most HTTP responses

var respErr error

switch err := err.(type) {
case *RouterMissingParamError, *RouterParsingError, *json.SyntaxError, *NoBodyError, *ValidationError:
case *RouterMissingParamError, *RouterParsingError, *json.SyntaxError, *NoBodyError, *ValidationError, *OutOfRangeError:
respErr = responses.SendBadRequest(writer, err.Error())
case *json.UnmarshalTypeError:
respErr = responses.SendBadRequest(writer, "bad type in json data")
Expand Down

0 comments on commit 6092b48

Please sign in to comment.