Files
supermq/pkg/errors/errors_test.go
T
b1ackd0t 22ecbc24ee NOISSUE - Refactor error handling and SDK error testing (#263)
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>
2024-01-08 11:33:16 +01:00

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)
}