Adding application error tests

main
Drew Bednar 7 days ago
parent 0e5a46f050
commit f8ccbe90b4

@ -0,0 +1,60 @@
package ratchet
import (
"errors"
"fmt"
)
const INTERNAL_ERROR_MESSAGE = "internal error"
// Application error codes.
//
// Note: these are generic codes but map well to HTTP status codes.
const (
EINTERNAL = "internal"
ENOTFOUND = "not_found"
)
// Error respresents an application specific-error. Application errors can be
// unwrapped by the caller to extract out the code and message
//
// Any non-application error (like disk error) should be reported as an EINTERNAL
// error and the human user should only see "Internal error" as the message.
// These low-level internal error details should only be logged and reported to
// the operation of the application, not the end user.
type Error struct {
// Machine-readable error code.
Code string
// Human-readable error message.
Message string
}
// Error implements the error interface. Not used by the application otherwise.
func (e Error) Error() string {
return fmt.Sprintf("ratchet error: code=%s message=%s", e.Code, e.Message)
}
// ErrorCode unwraps an application error and returns its code.
// Non-application errors always return EINTERNAL.
func ErrorCode(err error) string {
var e *Error
if err == nil {
return ""
} else if errors.As(err, &e) {
return e.Code
}
return EINTERNAL
}
// ErrorMessage unwraps an application error and returns it's message.
// Non-application errors always return "Internal error".
func ErrorMessage(err error) string {
var e *Error
if err == nil {
return ""
} else if errors.As(err, &e) {
return e.Message
}
return INTERNAL_ERROR_MESSAGE
}

@ -0,0 +1,57 @@
package ratchet
import (
"errors"
"testing"
)
func AssertErrorString(t *testing.T, got, want string) {
t.Helper()
if got != want {
t.Errorf("Incorrect error code/message got %q want %q", got, want)
}
}
func TestErrorCode(t *testing.T) {
t.Run("should return empty", func(t *testing.T) {
got := ErrorCode(nil)
AssertErrorString(t, got, "")
})
t.Run("should return internal error", func(t *testing.T) {
want := EINTERNAL
got := ErrorCode(errors.New("Mock disk error"))
AssertErrorString(t, got, want)
})
t.Run("should return my code", func(t *testing.T) {
e := &Error{Code: "my_code", Message: "my_message"}
got := ErrorCode(e)
AssertErrorString(t, got, e.Code)
})
}
func TestErrorMessage(t *testing.T) {
t.Run("empty error should return empty string", func(t *testing.T) {
got := ErrorMessage(nil)
AssertErrorString(t, got, "")
})
t.Run("should return internal error message", func(t *testing.T) {
got := ErrorMessage(errors.New("Mock disk error"))
AssertErrorString(t, got, INTERNAL_ERROR_MESSAGE)
})
t.Run("should return application error message", func(t *testing.T) {
e := &Error{Message: "my_message"}
got := ErrorMessage(e)
AssertErrorString(t, got, e.Message)
})
}

@ -0,0 +1,33 @@
package ratchet
import (
"context"
"time"
)
type User struct {
ID int `json:"id"`
// User prefered name and email
Name string `json:"name"`
Email string `json:"email"`
// Randomly generated API key for use with the API
// "-" omits the key from serialization
APIKey string `json:"-"`
// Timestamps for user creatation and last update
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
// List of associated Oauth authentication Objects
// Not yet implemented
// Auths []*Auth `json:"auths"`
}
// UserService represents a service for managing users.
type UserService interface {
// Retrieves a user by ID along with their associated auth objects
// Returns ENOTFOUND if user does not exist.
FindUserByID(ctx context.Context, id int) (*User, error)
}
Loading…
Cancel
Save