mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 04:10:34 +00:00
22ecbc24ee
Improve error handling and SDK error testing. The code now includes signal handling, error wrapping, checking for contained errors, and testing HTTP error responses. Additionally, assertions have been added to ensure the expected behavior is met. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
353 lines
7.1 KiB
Go
353 lines
7.1 KiB
Go
// Copyright (c) Abstract Machines
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package errors_test
|
|
|
|
import (
|
|
nerrors "errors"
|
|
"fmt"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/absmach/magistrala/pkg/errors"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
const level = 10
|
|
|
|
var (
|
|
err0 = errors.New("0")
|
|
err1 = errors.New("1")
|
|
err2 = errors.New("2")
|
|
nat = nerrors.New("native error")
|
|
)
|
|
|
|
func TestError(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
err error
|
|
msg string
|
|
bytes []byte
|
|
bytesErr error
|
|
}{
|
|
{
|
|
desc: "level 0 wrapped error",
|
|
err: err0,
|
|
msg: "0",
|
|
bytes: []byte(`{"error":"","message":"0"}`),
|
|
bytesErr: nil,
|
|
},
|
|
{
|
|
desc: "level 1 wrapped error",
|
|
err: wrap(1),
|
|
msg: message(1),
|
|
bytes: []byte(`{"error":"0","message":"1"}`),
|
|
bytesErr: nil,
|
|
},
|
|
{
|
|
desc: "level 2 wrapped error",
|
|
err: wrap(2),
|
|
msg: message(2),
|
|
bytes: []byte(`{"error":"1","message":"2"}`),
|
|
bytesErr: nil,
|
|
},
|
|
{
|
|
desc: fmt.Sprintf("level %d wrapped error", level),
|
|
err: wrap(level),
|
|
msg: message(level),
|
|
bytes: []byte(`{"error":"9","message":"` + strconv.Itoa(level) + `"}`),
|
|
bytesErr: nil,
|
|
},
|
|
{
|
|
desc: "nil error",
|
|
err: errors.New(""),
|
|
msg: "",
|
|
bytes: []byte(`{"error":"","message":""}`),
|
|
bytesErr: nil,
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.desc, func(t *testing.T) {
|
|
errMsg := c.err.Error()
|
|
assert.Equal(t, c.msg, errMsg)
|
|
err := c.err.(errors.Error)
|
|
data, derr := err.MarshalJSON()
|
|
assert.Equal(t, c.bytesErr, derr)
|
|
assert.Equal(t, c.bytes, data)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestContains(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
container error
|
|
contained error
|
|
contains bool
|
|
}{
|
|
{
|
|
desc: "nil contains nil",
|
|
container: nil,
|
|
contained: nil,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "nil contains non-nil",
|
|
container: nil,
|
|
contained: err0,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "non-nil contains nil",
|
|
container: err0,
|
|
contained: nil,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "non-nil contains non-nil",
|
|
container: err0,
|
|
contained: err1,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "res of errors.Wrap(err1, err0) contains err0",
|
|
container: errors.Wrap(err1, err0),
|
|
contained: err0,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "res of errors.Wrap(err1, err0) contains err1",
|
|
container: errors.Wrap(err1, err0),
|
|
contained: err1,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "res of errors.Wrap(err2, errors.Wrap(err1, err0)) contains err1",
|
|
container: errors.Wrap(err2, errors.Wrap(err1, err0)),
|
|
contained: err1,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: fmt.Sprintf("level %d wrapped error contains", level),
|
|
container: wrap(level),
|
|
contained: errors.New(strconv.Itoa(level / 2)),
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "superset wrapper error contains subset wrapper error",
|
|
container: wrap(level),
|
|
contained: wrap(level / 2),
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "native error contains error",
|
|
container: nat,
|
|
contained: err0,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "res of errors.Wrap(err1, errors.New('')) contains err1",
|
|
container: errors.Wrap(err1, nat),
|
|
contained: err1,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "error contains native error",
|
|
container: err0,
|
|
contained: nat,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "res of errors.Wrap(errors.New(''), err0) contains err0",
|
|
container: errors.Wrap(nat, err0),
|
|
contained: err0,
|
|
contains: true,
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.desc, func(t *testing.T) {
|
|
contains := errors.Contains(c.container, c.contained)
|
|
assert.Equal(t, c.contains, contains)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWrap(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
wrapper error
|
|
wrapped error
|
|
contained error
|
|
contains bool
|
|
}{
|
|
{
|
|
desc: "err 1 wraps err 2",
|
|
wrapper: err1,
|
|
wrapped: err0,
|
|
contained: err0,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "err2 wraps err1 wraps err0 and contains err0",
|
|
wrapper: err2,
|
|
wrapped: errors.Wrap(err1, err0),
|
|
contained: err0,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "err2 wraps err1 wraps err0 and contains err1",
|
|
wrapper: err2,
|
|
wrapped: errors.Wrap(err1, err0),
|
|
contained: err1,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "nil wraps nil",
|
|
wrapper: nil,
|
|
wrapped: nil,
|
|
contained: nil,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "err0 wraps nil",
|
|
wrapper: err0,
|
|
wrapped: nil,
|
|
contained: nil,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "nil wraps err0",
|
|
wrapper: nil,
|
|
wrapped: err0,
|
|
contained: err0,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "err0 wraps native error",
|
|
wrapper: err0,
|
|
wrapped: nat,
|
|
contained: nat,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "nil wraps native error",
|
|
wrapper: nil,
|
|
wrapped: nat,
|
|
contained: nat,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "native error wraps err0",
|
|
wrapper: nat,
|
|
wrapped: err0,
|
|
contained: err0,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "native error wraps nil",
|
|
wrapper: nat,
|
|
wrapped: nil,
|
|
contained: nil,
|
|
contains: false,
|
|
},
|
|
{
|
|
desc: "err0 wraps err1 wraps native error",
|
|
wrapper: err0,
|
|
wrapped: errors.Wrap(err1, nat),
|
|
contained: nat,
|
|
contains: true,
|
|
},
|
|
{
|
|
desc: "native error wraps err1 wraps err0",
|
|
wrapper: nat,
|
|
wrapped: errors.Wrap(err1, err0),
|
|
contained: err0,
|
|
contains: true,
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.desc, func(t *testing.T) {
|
|
err := errors.Wrap(c.wrapper, c.wrapped)
|
|
contains := errors.Contains(err, c.contained)
|
|
assert.Equal(t, c.contains, contains)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnwrap(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
err error
|
|
wrapper error
|
|
wrapped error
|
|
}{
|
|
{
|
|
desc: "err 1 wraped err 2",
|
|
err: errors.Wrap(err1, err2),
|
|
wrapper: err1,
|
|
wrapped: err2,
|
|
},
|
|
{
|
|
desc: "err2 wraps err1 wraps err0",
|
|
err: errors.Wrap(err2, errors.Wrap(err1, err0)),
|
|
wrapper: err2,
|
|
wrapped: errors.Wrap(err1, err0),
|
|
},
|
|
{
|
|
desc: "nil wraps nil",
|
|
err: errors.Wrap(nil, nil),
|
|
wrapper: nil,
|
|
wrapped: nil,
|
|
},
|
|
{
|
|
desc: "err0 wraps nil",
|
|
err: errors.Wrap(err0, nil),
|
|
wrapper: nil,
|
|
wrapped: err0,
|
|
},
|
|
{
|
|
desc: "nil wraps err0",
|
|
err: errors.Wrap(nil, err0),
|
|
wrapper: nil,
|
|
wrapped: nil,
|
|
},
|
|
{
|
|
desc: "nil wraps native error",
|
|
err: errors.Wrap(nil, nat),
|
|
wrapper: nil,
|
|
wrapped: nil,
|
|
},
|
|
{
|
|
desc: "native error wraps nil",
|
|
err: errors.Wrap(nat, nil),
|
|
wrapper: nil,
|
|
wrapped: nat,
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
t.Run(c.desc, func(t *testing.T) {
|
|
wrapper, wrapped := errors.Unwrap(c.err)
|
|
assert.Equal(t, c.wrapper, wrapper)
|
|
assert.Equal(t, c.wrapped, wrapped)
|
|
})
|
|
}
|
|
}
|
|
|
|
func wrap(level int) error {
|
|
if level == 0 {
|
|
return errors.New(strconv.Itoa(level))
|
|
}
|
|
return errors.Wrap(errors.New(strconv.Itoa(level)), wrap(level-1))
|
|
}
|
|
|
|
// message generates error message of wrap() generated wrapper error.
|
|
func message(level int) string {
|
|
if level == 0 {
|
|
return "0"
|
|
}
|
|
return strconv.Itoa(level) + " : " + message(level-1)
|
|
}
|