NOISSUE - Add internal type to find NestError and Add Auth key algorithm to journal docker compose (#3304)

Signed-off-by: Arvindh <arvindh91@gmail.com>
This commit is contained in:
Arvindh
2025-12-30 20:50:35 +05:30
committed by GitHub
parent c679224596
commit a526a2ccd5
8 changed files with 123 additions and 94 deletions
+2 -2
View File
@@ -270,8 +270,8 @@ jobs:
run: |
modules=()
if [[ "${{ steps.changes.outputs.workflow }}" == "true" ]]; then
# If workflow changed, test everything
if [[ "${{ steps.changes.outputs.workflow }}" == "true" || "${{ steps.changes.outputs.pkg-errors }}" == "true" ]]; then
# If workflow or pkg/errors changed, test everything
modules=("auth" "channels" "cli" "clients" "coap" "domains" "groups" "http" "internal" "journal" "logger" "mqtt" "pkg-errors" "pkg-events" "pkg-grpcclient" "pkg-messaging" "pkg-sdk" "pkg-transformers" "pkg-ulid" "pkg-uuid" "users" "ws" "notifications" "api" "consumers" "readers")
else
# Add only changed modules
+6 -5
View File
@@ -18,6 +18,7 @@ import (
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/auth/tokenizer/asymmetric"
smqerrors "github.com/absmach/supermq/pkg/errors"
"github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/lestrrat-go/jwx/v2/jwt"
@@ -58,7 +59,7 @@ func TestNewKeyManager(t *testing.T) {
name string
setupKey func() string
expectErr bool
errContains string
expectedErr error
}{
{
name: "valid PEM key",
@@ -85,7 +86,7 @@ func TestNewKeyManager(t *testing.T) {
return filepath.Join(tmpDir, "nonexistent.key")
},
expectErr: true,
errContains: "failed to load private key",
expectedErr: smqerrors.New("failed to load private key"),
},
{
name: "invalid key size",
@@ -96,7 +97,7 @@ func TestNewKeyManager(t *testing.T) {
return invalidPath
},
expectErr: true,
errContains: "invalid ED25519 key size",
expectedErr: smqerrors.New("invalid ED25519 key size"),
},
}
@@ -108,8 +109,8 @@ func TestNewKeyManager(t *testing.T) {
if tc.expectErr {
assert.Error(t, err)
if tc.errContains != "" {
assert.Contains(t, err.Error(), tc.errContains)
if tc.expectedErr != nil {
assert.True(t, smqerrors.Contains(err, tc.expectedErr))
}
assert.Nil(t, km)
} else {
@@ -59,6 +59,7 @@ services:
SMQ_AUTH_GRPC_CLIENT_CERT: ${SMQ_AUTH_GRPC_CLIENT_CERT:+/auth-grpc-client.crt}
SMQ_AUTH_GRPC_CLIENT_KEY: ${SMQ_AUTH_GRPC_CLIENT_KEY:+/auth-grpc-client.key}
SMQ_AUTH_GRPC_SERVER_CA_CERTS: ${SMQ_AUTH_GRPC_SERVER_CA_CERTS:+/auth-grpc-server-ca.crt}
SMQ_AUTH_KEYS_ALGORITHM: ${SMQ_AUTH_KEYS_ALGORITHM}
SMQ_ES_URL: ${SMQ_ES_URL}
SMQ_JAEGER_URL: ${SMQ_JAEGER_URL}
SMQ_JAEGER_TRACE_RATIO: ${SMQ_JAEGER_TRACE_RATIO}
+3 -3
View File
@@ -267,7 +267,7 @@ func TestPublish(t *testing.T) {
err: errMalformedTopic,
},
{
desc: "publish with malformwd subtopic",
desc: "publish with malformed subtopic",
topic: &malformedSubtopics,
status: http.StatusBadRequest,
password: clientKey,
@@ -411,7 +411,7 @@ func TestPublish(t *testing.T) {
authNErr: nil,
authZRes: &grpcChannelsV1.AuthzRes{Authorized: true},
authZErr: nil,
publishErr: errors.New("failed to publish"),
publishErr: errFailedPublishToMsgBroker,
err: errFailedPublishToMsgBroker,
},
{
@@ -453,7 +453,7 @@ func TestPublish(t *testing.T) {
assert.Equal(t, tc.status, hpe.StatusCode())
}
if tc.err != nil {
assert.Contains(t, err.Error(), tc.err.Error(), fmt.Sprintf("expected error containing: %v, got: %v", tc.err, err))
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error containing: %v, got: %v", tc.err, err))
}
authCall.Unset()
repoCall.Unset()
+42 -68
View File
@@ -3,10 +3,7 @@
package errors
import (
"errors"
"fmt"
)
const internalServiceError = "internal server error"
type NestError interface {
Error
@@ -22,31 +19,30 @@ func (e *customError) Embed(err error) error {
return &customError{
msg: e.msg,
err: fmt.Errorf("%w: %w", e.err, err),
err: Wrap(err, e.err),
}
}
type nestableError interface {
NestError
isNestable()
}
type RequestError struct {
customError
}
var _ NestError = (*RequestError)(nil)
var _ nestableError = (*RequestError)(nil)
func NewRequestError(message string) NestError {
return &RequestError{
customError: customError{
msg: message,
err: errors.New(message),
},
customError: newCustomError(message),
}
}
func NewRequestErrorWithErr(message string, err error) NestError {
return &RequestError{
customError: customError{
msg: message,
err: fmt.Errorf("%w: %w", errors.New(message), err),
},
customError: newCustomErrorWithError(message, err),
}
}
@@ -57,27 +53,23 @@ func (e *RequestError) Embed(err error) error {
}
}
func (*RequestError) isNestable() {}
type AuthNError struct {
customError
}
var _ NestError = (*AuthNError)(nil)
var _ nestableError = (*AuthNError)(nil)
func NewAuthNError(message string) NestError {
return &AuthNError{
customError: customError{
msg: message,
err: errors.New(message),
},
customError: newCustomError(message),
}
}
func NewAuthNErrorWithErr(message string, err error) NestError {
return &AuthNError{
customError: customError{
msg: message,
err: fmt.Errorf("%w: %w", errors.New(message), err),
},
customError: newCustomErrorWithError(message, err),
}
}
@@ -88,7 +80,9 @@ func (e *AuthNError) Embed(err error) error {
}
}
var _ NestError = (*AuthZError)(nil)
func (*AuthNError) isNestable() {}
var _ nestableError = (*AuthZError)(nil)
type AuthZError struct {
customError
@@ -103,43 +97,33 @@ func (e *AuthZError) Embed(err error) error {
func NewAuthZError(message string) NestError {
return &AuthZError{
customError: customError{
msg: message,
err: errors.New(message),
},
customError: newCustomError(message),
}
}
func NewAuthZErrorWithErr(message string, err error) NestError {
return &AuthZError{
customError: customError{
msg: message,
err: fmt.Errorf("%w: %w", errors.New(message), err),
},
customError: newCustomErrorWithError(message, err),
}
}
func (*AuthZError) isNestable() {}
type InternalError struct {
customError
}
var _ NestError = (*InternalError)(nil)
var _ nestableError = (*InternalError)(nil)
func NewInternalError() error {
return &InternalError{
customError: customError{
msg: "internal server error",
err: errors.New("internal server error"),
},
customError: newCustomError(internalServiceError),
}
}
func NewInternalErrorWithErr(err error) NestError {
return &InternalError{
customError: customError{
msg: "internal server error",
err: fmt.Errorf("%w: %w", errors.New("internal server error"), err),
},
customError: newCustomErrorWithError(internalServiceError, err),
}
}
@@ -150,27 +134,23 @@ func (e *InternalError) Embed(err error) error {
}
}
func (*InternalError) isNestable() {}
type ServiceError struct {
customError
}
var _ NestError = (*ServiceError)(nil)
var _ nestableError = (*ServiceError)(nil)
func NewServiceError(message string) NestError {
return &ServiceError{
customError: customError{
msg: message,
err: errors.New(message),
},
customError: newCustomError(message),
}
}
func NewServiceErrorWithErr(message string, err error) NestError {
return &ServiceError{
customError: customError{
msg: message,
err: fmt.Errorf("%w: %w", errors.New(message), err),
},
customError: newCustomErrorWithError(message, err),
}
}
@@ -181,27 +161,23 @@ func (e *ServiceError) Embed(err error) error {
}
}
func (*ServiceError) isNestable() {}
type MediaTypeError struct {
customError
}
var _ NestError = (*MediaTypeError)(nil)
var _ nestableError = (*MediaTypeError)(nil)
func NewMediaTypeError(message string) NestError {
return &MediaTypeError{
customError: customError{
msg: message,
err: errors.New(message),
},
customError: newCustomError(message),
}
}
func NewMediaTypeErrorWithErr(message string, err error) NestError {
return &MediaTypeError{
customError: customError{
msg: message,
err: fmt.Errorf("%w: %w", errors.New(message), err),
},
customError: newCustomErrorWithError(message, err),
}
}
@@ -212,27 +188,23 @@ func (e *MediaTypeError) Embed(err error) error {
}
}
func (*MediaTypeError) isNestable() {}
type NotFoundError struct {
customError
}
var _ NestError = (*NotFoundError)(nil)
var _ nestableError = (*NotFoundError)(nil)
func NewNotFoundError(message string) NestError {
return &NotFoundError{
customError: customError{
msg: message,
err: errors.New(message),
},
customError: newCustomError(message),
}
}
func NewNotFoundErrorWithErr(message string, err error) NestError {
return &NotFoundError{
customError: customError{
msg: message,
err: fmt.Errorf("%w: %w", errors.New(message), err),
},
customError: newCustomErrorWithError(message, err),
}
}
@@ -242,3 +214,5 @@ func (e *NotFoundError) Embed(err error) error {
customError: *embedded.(*customError),
}
}
func (*NotFoundError) isNestable() {}
+20 -6
View File
@@ -6,7 +6,6 @@ package errors
import (
"encoding/json"
"errors"
"fmt"
)
// Error specifies an API that must be fullfiled by error type.
@@ -32,11 +31,25 @@ type customError struct {
err error
}
func newCustomError(msg string) customError {
return customError{
msg: msg,
err: nil,
}
}
func newCustomErrorWithError(msg string, err error) customError {
return customError{
msg: msg,
err: err,
}
}
// New returns an Error that formats as the given text.
func New(text string) Error {
return &customError{
msg: text,
err: errors.New(text),
err: nil,
}
}
@@ -47,7 +60,7 @@ func (ce *customError) Error() string {
if ce.err == nil {
return ce.msg
}
return ce.err.Error()
return ce.msg + " : " + ce.err.Error()
}
func (ce *customError) Msg() string {
@@ -66,6 +79,7 @@ func (ce *customError) MarshalJSON() ([]byte, error) {
})
}
// Contains inspects if e2 error is contained in any layer of e1 error.
func Contains(e1, e2 error) bool {
if e1 == nil || e2 == nil {
return e2 == e1
@@ -86,15 +100,15 @@ func Wrap(wrapper, err error) error {
if wrapper == nil || err == nil {
return wrapper
}
if ne, ok := err.(NestError); ok {
if ne, ok := err.(nestableError); ok {
return ne.Embed(wrapper)
}
if ce, ok := wrapper.(NestError); ok {
if ce, ok := wrapper.(nestableError); ok {
return ce.Embed(err)
}
return &customError{
msg: wrapper.Error(),
err: fmt.Errorf("%w: %w", wrapper, err),
err: cast(err),
}
}
+47 -8
View File
@@ -41,21 +41,21 @@ func TestError(t *testing.T) {
desc: "level 1 wrapped error",
err: wrap(1),
msg: message(1),
bytes: []byte(`{"message":"0"}`),
bytes: []byte(`{"message":"1"}`),
bytesErr: nil,
},
{
desc: "level 2 wrapped error",
err: wrap(2),
msg: message(2),
bytes: []byte(`{"message":"0"}`),
bytes: []byte(`{"message":"2"}`),
bytesErr: nil,
},
{
desc: fmt.Sprintf("level %d wrapped error", level),
err: wrap(level),
msg: message(level),
bytes: []byte(`{"message":"0"}`),
bytes: []byte(`{"message":"10"}`),
bytesErr: nil,
},
{
@@ -80,6 +80,9 @@ func TestError(t *testing.T) {
}
func TestContains(t *testing.T) {
internalErr1 := errors.New("some internal error 1")
internalErr2 := errors.New("some internal error 2")
internalErr3 := errors.New("some internal error 3")
cases := []struct {
desc string
container error
@@ -164,6 +167,42 @@ func TestContains(t *testing.T) {
contained: err0,
contains: true,
},
{
desc: "check nested errors contains errors by adding error in creation",
container: errors.NewAuthNErrorWithErr("failed to authenticate", internalErr1),
contained: internalErr1,
contains: true,
},
{
desc: "check nested errors contains errors by adding error in creation (middle)",
container: errors.Wrap(errors.NewAuthNErrorWithErr("failed to authenticate", internalErr1), internalErr2),
contained: internalErr2,
contains: true,
},
{
desc: "check nested errors contains errors by adding error in creation",
container: errors.Wrap(errors.Wrap(errors.NewAuthNErrorWithErr("failed to authenticate", internalErr1), internalErr2), internalErr3),
contained: internalErr1,
contains: true,
},
{
desc: "check nested errors contains errors by adding error in creation (middle chain)",
container: errors.Wrap(errors.Wrap(errors.NewAuthNErrorWithErr("failed to authenticate", internalErr1), internalErr2), internalErr3),
contained: internalErr2,
contains: true,
},
{
desc: "check nested errors contains errors by adding error in creation (outer chain)",
container: errors.Wrap(errors.Wrap(errors.NewAuthNErrorWithErr("failed to authenticate", internalErr1), internalErr2), internalErr3),
contained: internalErr3,
contains: true,
},
{
desc: "check nested errors contains errors by wrapping",
container: errors.Wrap(errors.NewAuthNError("failed to authenticate"), internalErr1),
contained: internalErr1,
contains: true,
},
}
for _, c := range cases {
t.Run(c.desc, func(t *testing.T) {
@@ -286,8 +325,8 @@ func TestUnwrap(t *testing.T) {
{
desc: "err 1 wraped err 2",
err: errors.Wrap(err1, err2),
wrapper: err2,
wrapped: fmt.Errorf("%w: %w", err2, err1),
wrapper: err1,
wrapped: err2,
},
{
desc: "nil wraps nil",
@@ -334,10 +373,10 @@ func wrap(level int) error {
}
// message generates error message of wrap() generated wrapper error.
// The error message format is now "innermost: ... : outermost" due to fmt.Errorf wrapping.
// The error message format is "outermost : ... : innermost".
func message(level int) string {
if level == 0 {
if level <= 0 {
return "0"
}
return message(level-1) + ": " + strconv.Itoa(level)
return strconv.Itoa(level) + " : " + message(level-1)
}
+2 -2
View File
@@ -694,7 +694,7 @@ func TestPublish(t *testing.T) {
session: &sessionClient,
topic: wrongCharSubtopics,
payload: payload,
err: messaging.ErrMalformedTopic,
err: messaging.ErrMalformedSubtopic,
},
{
desc: "publish with subtopic",
@@ -731,7 +731,7 @@ func TestPublish(t *testing.T) {
repoCall := publisher.On("Publish", mock.Anything, mock.Anything, mock.Anything).Return(nil)
err := handler.Publish(ctx, &tc.topic, &tc.payload)
if tc.err != nil {
assert.Contains(t, err.Error(), tc.err.Error(), fmt.Sprintf("expected error message to contain: %v, got: %v", tc.err, err))
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("expected error message to contain: %v, got: %v", tc.err, err))
}
repoCall.Unset()
}