Files
Dušan Borovčanin 168e8b90cb
Property Based Tests / api-test (push) Has been cancelled
Continuous Delivery / lint-and-build (push) Has been cancelled
Deploy GitHub Pages / swagger-ui (push) Has been cancelled
CI Pipeline / Lint Proto (push) Has been cancelled
CI Pipeline / Detect Changes (push) Has been cancelled
Continuous Delivery / Build and Push Docker Images (push) Has been cancelled
CI Pipeline / lint-and-build (push) Has been cancelled
CI Pipeline / Test ${{ matrix.module }} (push) Has been cancelled
CI Pipeline / Upload Coverage (push) Has been cancelled
NOISSUE - Move rules engine, alarms, reports, journal and notifications to EE (#3552)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-07-30 17:55:57 +02:00

142 lines
3.5 KiB
Go

// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package readersclient
import (
"context"
"errors"
"testing"
"time"
grpcReadersV1 "github.com/absmach/magistrala/api/grpc/readers/v1"
mgerrors "github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type readersClientStub struct {
req *grpcReadersV1.ReadMessagesReq
res *grpcReadersV1.ReadMessagesRes
err error
hasDeadline bool
}
func (stub *readersClientStub) ReadMessages(ctx context.Context, req *grpcReadersV1.ReadMessagesReq, _ ...grpc.CallOption) (*grpcReadersV1.ReadMessagesRes, error) {
stub.req = req
_, stub.hasDeadline = ctx.Deadline()
return stub.res, stub.err
}
func TestReadMessages(t *testing.T) {
req := &grpcReadersV1.ReadMessagesReq{
ChannelId: "channel",
DomainId: "domain",
PageMetadata: &grpcReadersV1.PageMetadata{
Publishers: []string{"publisher-1", "publisher-2"},
Order: "time",
Dir: "desc",
},
}
expected := &grpcReadersV1.ReadMessagesRes{
Total: 2,
PageMetadata: &grpcReadersV1.PageMetadata{
Offset: 3,
Limit: 5,
Order: "time",
Dir: "desc",
},
}
stub := &readersClientStub{res: expected}
client := &client{
readers: stub,
timeout: time.Second,
}
actual, err := client.ReadMessages(t.Context(), req)
require.NoError(t, err)
assert.Same(t, req, stub.req)
assert.Same(t, expected, actual)
assert.True(t, stub.hasDeadline)
}
func TestReadMessagesError(t *testing.T) {
stub := &readersClientStub{err: status.Error(codes.NotFound, "missing messages")}
client := &client{
readers: stub,
timeout: time.Second,
}
res, err := client.ReadMessages(t.Context(), &grpcReadersV1.ReadMessagesReq{})
require.Error(t, err)
assert.NotNil(t, res)
assert.True(t, mgerrors.Contains(err, svcerr.ErrNotFound))
}
func TestDecodeError(t *testing.T) {
native := errors.New("native error")
tests := []struct {
name string
input error
expected error
}{
{
name: "unauthenticated",
input: status.Error(codes.Unauthenticated, "missing credentials"),
expected: svcerr.ErrAuthentication,
},
{
name: "permission denied",
input: status.Error(codes.PermissionDenied, "forbidden"),
expected: svcerr.ErrAuthorization,
},
{
name: "invalid argument",
input: status.Error(codes.InvalidArgument, "bad request"),
expected: mgerrors.ErrMalformedEntity,
},
{
name: "failed precondition",
input: status.Error(codes.FailedPrecondition, "bad state"),
expected: mgerrors.ErrMalformedEntity,
},
{
name: "not found",
input: status.Error(codes.NotFound, "missing"),
expected: svcerr.ErrNotFound,
},
{
name: "already exists",
input: status.Error(codes.AlreadyExists, "duplicate"),
expected: svcerr.ErrConflict,
},
{
name: "unknown status",
input: status.Error(codes.Unavailable, "offline"),
expected: errors.New("unexpected gRPC status"),
},
{
name: "native error",
input: native,
expected: native,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
actual := decodeError(tc.input)
if tc.name == "unknown status" {
assert.ErrorContains(t, actual, tc.expected.Error())
return
}
assert.True(t, mgerrors.Contains(actual, tc.expected), "expected %q to contain %q", actual, tc.expected)
})
}
}