SMQ-3036 - Add events tests for channels,clients, domains and groups (#3279)

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
This commit is contained in:
Felix Gateru
2025-12-23 14:18:39 +03:00
committed by GitHub
parent cb337a38fd
commit e23555ee2a
12 changed files with 2925 additions and 246 deletions
+669
View File
@@ -0,0 +1,669 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package events_test
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/absmach/supermq/channels"
"github.com/absmach/supermq/channels/events"
"github.com/absmach/supermq/channels/mocks"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/connections"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/absmach/supermq/pkg/roles"
"github.com/go-chi/chi/v5/middleware"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
storeClient *redis.Client
storeURL string
validSession = authn.Session{
DomainID: testsutil.GenerateUUID(&testing.T{}),
UserID: testsutil.GenerateUUID(&testing.T{}),
}
validChannel = generateTestChannel(&testing.T{})
validChannelsPage = channels.ChannelsPage{
Page: channels.Page{
Limit: 10,
Offset: 0,
Total: 1,
},
Channels: []channels.Channel{validChannel},
}
)
func newEventStoreMiddleware(t *testing.T) (*mocks.Service, channels.Service) {
svc := new(mocks.Service)
nsvc, err := events.NewEventStoreMiddleware(context.Background(), svc, storeURL)
require.Nil(t, err, fmt.Sprintf("create events store middleware failed with unexpected error: %s", err))
return svc, nsvc
}
func TestMain(m *testing.M) {
code := testsutil.RunRedisTest(m, &storeClient, &storeURL)
os.Exit(code)
}
func TestCreateChannels(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validID := testsutil.GenerateUUID(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, validID)
cases := []struct {
desc string
session authn.Session
channels []channels.Channel
svcRes []channels.Channel
svcRoleRes []roles.RoleProvision
svcErr error
resp []channels.Channel
respRoleRes []roles.RoleProvision
err error
}{
{
desc: "publish successfully",
session: validSession,
channels: []channels.Channel{validChannel},
svcRes: []channels.Channel{validChannel},
svcRoleRes: []roles.RoleProvision{},
svcErr: nil,
resp: []channels.Channel{validChannel},
respRoleRes: []roles.RoleProvision{},
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channels: []channels.Channel{validChannel},
svcRes: []channels.Channel{},
svcRoleRes: []roles.RoleProvision{},
svcErr: svcerr.ErrCreateEntity,
resp: []channels.Channel{},
respRoleRes: []roles.RoleProvision{},
err: svcerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("CreateChannels", validCtx, tc.session, tc.channels).Return(tc.svcRes, tc.svcRoleRes, tc.svcErr)
resp, respRoleRes, err := nsvc.CreateChannels(validCtx, tc.session, tc.channels...)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
assert.Equal(t, tc.respRoleRes, respRoleRes, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.respRoleRes, respRoleRes))
svcCall.Unset()
})
}
}
func TestViewChannel(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
channelID string
withRoles bool
svcRes channels.Channel
svcErr error
resp channels.Channel
err error
}{
{
desc: "publish successfully",
session: validSession,
channelID: validChannel.ID,
withRoles: false,
svcRes: validChannel,
svcErr: nil,
resp: validChannel,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channelID: validChannel.ID,
withRoles: false,
svcRes: channels.Channel{},
svcErr: svcerr.ErrViewEntity,
resp: channels.Channel{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ViewChannel", validCtx, tc.session, tc.channelID, tc.withRoles).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ViewChannel(validCtx, tc.session, tc.channelID, tc.withRoles)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateChannel(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedChannel := validChannel
updatedChannel.Name = "updatedName"
cases := []struct {
desc string
session authn.Session
channel channels.Channel
svcRes channels.Channel
svcErr error
resp channels.Channel
err error
}{
{
desc: "publish successfully",
session: validSession,
channel: updatedChannel,
svcRes: updatedChannel,
svcErr: nil,
resp: updatedChannel,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channel: updatedChannel,
svcRes: channels.Channel{},
svcErr: svcerr.ErrUpdateEntity,
resp: channels.Channel{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateChannel", validCtx, tc.session, tc.channel).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateChannel(validCtx, tc.session, tc.channel)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateChannelTags(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedChannel := validChannel
updatedChannel.Tags = []string{"newTag1", "newTag2"}
cases := []struct {
desc string
session authn.Session
channel channels.Channel
svcRes channels.Channel
svcErr error
resp channels.Channel
err error
}{
{
desc: "publish successfully",
session: validSession,
channel: updatedChannel,
svcRes: updatedChannel,
svcErr: nil,
resp: updatedChannel,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channel: updatedChannel,
svcRes: channels.Channel{},
svcErr: svcerr.ErrUpdateEntity,
resp: channels.Channel{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateChannelTags", validCtx, tc.session, tc.channel).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateChannelTags(validCtx, tc.session, tc.channel)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestEnableChannel(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
channelID string
svcRes channels.Channel
svcErr error
resp channels.Channel
err error
}{
{
desc: "publish successfully",
session: validSession,
channelID: validChannel.ID,
svcRes: validChannel,
svcErr: nil,
resp: validChannel,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channelID: validChannel.ID,
svcRes: channels.Channel{},
svcErr: svcerr.ErrUpdateEntity,
resp: channels.Channel{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("EnableChannel", validCtx, tc.session, tc.channelID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.EnableChannel(validCtx, tc.session, tc.channelID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDisableChannel(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
channelID string
svcRes channels.Channel
svcErr error
resp channels.Channel
err error
}{
{
desc: "publish successfully",
session: validSession,
channelID: validChannel.ID,
svcRes: validChannel,
svcErr: nil,
resp: validChannel,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channelID: validChannel.ID,
svcRes: channels.Channel{},
svcErr: svcerr.ErrUpdateEntity,
resp: channels.Channel{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("DisableChannel", validCtx, tc.session, tc.channelID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.DisableChannel(validCtx, tc.session, tc.channelID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListChannels(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
pageMeta channels.Page
svcRes channels.ChannelsPage
svcErr error
resp channels.ChannelsPage
err error
}{
{
desc: "publish successfully",
session: validSession,
pageMeta: channels.Page{
Limit: 10,
Offset: 0,
},
svcRes: validChannelsPage,
svcErr: nil,
resp: validChannelsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
pageMeta: channels.Page{
Limit: 10,
Offset: 0,
},
svcRes: channels.ChannelsPage{},
svcErr: svcerr.ErrViewEntity,
resp: channels.ChannelsPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListChannels", validCtx, tc.session, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListChannels(validCtx, tc.session, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListUserChannels(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
userID string
pageMeta channels.Page
svcRes channels.ChannelsPage
svcErr error
resp channels.ChannelsPage
err error
}{
{
desc: "publish successfully",
session: validSession,
userID: validSession.UserID,
pageMeta: channels.Page{
Limit: 10,
Offset: 0,
},
svcRes: validChannelsPage,
svcErr: nil,
resp: validChannelsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
userID: validSession.UserID,
pageMeta: channels.Page{
Limit: 10,
Offset: 0,
},
svcRes: channels.ChannelsPage{},
svcErr: svcerr.ErrViewEntity,
resp: channels.ChannelsPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListUserChannels", validCtx, tc.session, tc.userID, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListUserChannels(validCtx, tc.session, tc.userID, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestRemoveChannel(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
channelID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
channelID: validChannel.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channelID: validChannel.ID,
svcErr: svcerr.ErrRemoveEntity,
err: svcerr.ErrRemoveEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RemoveChannel", validCtx, tc.session, tc.channelID).Return(tc.svcErr)
err := nsvc.RemoveChannel(validCtx, tc.session, tc.channelID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestConnect(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
chIDs []string
clIDs []string
connTypes []connections.ConnType
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
chIDs: []string{validChannel.ID},
clIDs: []string{testsutil.GenerateUUID(t)},
connTypes: []connections.ConnType{connections.Publish},
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
chIDs: []string{validChannel.ID},
clIDs: []string{testsutil.GenerateUUID(t)},
connTypes: []connections.ConnType{connections.Publish},
svcErr: svcerr.ErrCreateEntity,
err: svcerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Connect", validCtx, tc.session, tc.chIDs, tc.clIDs, tc.connTypes).Return(tc.svcErr)
err := nsvc.Connect(validCtx, tc.session, tc.chIDs, tc.clIDs, tc.connTypes)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestDisconnect(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
chIDs []string
clIDs []string
connTypes []connections.ConnType
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
chIDs: []string{validChannel.ID},
clIDs: []string{testsutil.GenerateUUID(t)},
connTypes: []connections.ConnType{connections.Publish},
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
chIDs: []string{validChannel.ID},
clIDs: []string{testsutil.GenerateUUID(t)},
connTypes: []connections.ConnType{connections.Publish},
svcErr: svcerr.ErrRemoveEntity,
err: svcerr.ErrRemoveEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Disconnect", validCtx, tc.session, tc.chIDs, tc.clIDs, tc.connTypes).Return(tc.svcErr)
err := nsvc.Disconnect(validCtx, tc.session, tc.chIDs, tc.clIDs, tc.connTypes)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestSetParentGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
parentGroupID string
channelID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
parentGroupID: testsutil.GenerateUUID(t),
channelID: validChannel.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
parentGroupID: testsutil.GenerateUUID(t),
channelID: validChannel.ID,
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("SetParentGroup", validCtx, tc.session, tc.parentGroupID, tc.channelID).Return(tc.svcErr)
err := nsvc.SetParentGroup(validCtx, tc.session, tc.parentGroupID, tc.channelID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRemoveParentGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
channelID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
channelID: validChannel.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
channelID: validChannel.ID,
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RemoveParentGroup", validCtx, tc.session, tc.channelID).Return(tc.svcErr)
err := nsvc.RemoveParentGroup(validCtx, tc.session, tc.channelID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func generateTestChannel(t *testing.T) channels.Channel {
createdAt, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z")
assert.Nil(t, err, fmt.Sprintf("Unexpected error parsing time: %v", err))
return channels.Channel{
ID: testsutil.GenerateUUID(t),
Name: "channelname",
Domain: testsutil.GenerateUUID(t),
Tags: []string{"tag1", "tag2"},
Metadata: channels.Metadata{"key1": "value1"},
CreatedAt: createdAt,
UpdatedAt: createdAt,
Status: channels.EnabledStatus,
}
}
+3 -144
View File
@@ -22,12 +22,8 @@ const (
clientDisable = clientPrefix + "disable"
clientRemove = clientPrefix + "remove"
clientView = clientPrefix + "view"
clientViewPerms = clientPrefix + "view_perms"
clientList = clientPrefix + "list"
clientListByGroup = clientPrefix + "list_by_channel"
clientListByUser = clientPrefix + "list_by_user"
clientIdentify = clientPrefix + "identify"
clientAuthorize = clientPrefix + "authorize"
clientSetParent = clientPrefix + "set_parent"
clientRemoveParent = clientPrefix + "remove_parent"
)
@@ -37,13 +33,11 @@ var (
_ events.Event = (*updateClientEvent)(nil)
_ events.Event = (*changeClientStatusEvent)(nil)
_ events.Event = (*viewClientEvent)(nil)
_ events.Event = (*viewClientPermsEvent)(nil)
_ events.Event = (*listClientEvent)(nil)
_ events.Event = (*listClientByGroupEvent)(nil)
_ events.Event = (*identifyClientEvent)(nil)
_ events.Event = (*authorizeClientEvent)(nil)
_ events.Event = (*shareClientEvent)(nil)
_ events.Event = (*listUserClientEvent)(nil)
_ events.Event = (*removeClientEvent)(nil)
_ events.Event = (*setParentGroupEvent)(nil)
_ events.Event = (*removeParentGroupEvent)(nil)
)
type createClientEvent struct {
@@ -196,25 +190,6 @@ func (vce viewClientEvent) Encode() (map[string]any, error) {
return val, nil
}
type viewClientPermsEvent struct {
permissions []string
authn.Session
requestID string
}
func (vcpe viewClientPermsEvent) Encode() (map[string]any, error) {
val := map[string]any{
"operation": clientViewPerms,
"permissions": vcpe.permissions,
"domain": vcpe.DomainID,
"user_id": vcpe.UserID,
"token_type": vcpe.Type.String(),
"super_admin": vcpe.SuperAdmin,
"request_id": vcpe.requestID,
}
return val, nil
}
type listClientEvent struct {
clients.Page
authn.Session
@@ -310,122 +285,6 @@ func (lce listUserClientEvent) Encode() (map[string]any, error) {
return val, nil
}
type listClientByGroupEvent struct {
clients.Page
channelID string
authn.Session
requestID string
}
func (lcge listClientByGroupEvent) Encode() (map[string]any, error) {
val := map[string]any{
"operation": clientListByGroup,
"total": lcge.Total,
"offset": lcge.Offset,
"limit": lcge.Limit,
"channel_id": lcge.channelID,
"domain": lcge.DomainID,
"user_id": lcge.UserID,
"token_type": lcge.Type.String(),
"super_admin": lcge.SuperAdmin,
"request_id": lcge.requestID,
}
if lcge.Name != "" {
val["name"] = lcge.Name
}
if lcge.Order != "" {
val["order"] = lcge.Order
}
if lcge.Dir != "" {
val["dir"] = lcge.Dir
}
if lcge.Metadata != nil {
val["metadata"] = lcge.Metadata
}
if lcge.Tag != "" {
val["tag"] = lcge.Tag
}
if lcge.Status.String() != "" {
val["status"] = lcge.Status.String()
}
if lcge.Identity != "" {
val["identity"] = lcge.Identity
}
return val, nil
}
type identifyClientEvent struct {
clientID string
authn.Session
requestID string
}
func (ice identifyClientEvent) Encode() (map[string]any, error) {
return map[string]any{
"operation": clientIdentify,
"id": ice.clientID,
"domain": ice.DomainID,
"user_id": ice.UserID,
"token_type": ice.Type.String(),
"super_admin": ice.SuperAdmin,
"request_id": ice.requestID,
}, nil
}
type authorizeClientEvent struct {
clientID string
channelID string
permission string
authn.Session
requestID string
}
func (ice authorizeClientEvent) Encode() (map[string]any, error) {
val := map[string]any{
"operation": clientAuthorize,
"id": ice.clientID,
"domain": ice.DomainID,
"user_id": ice.UserID,
"token_type": ice.Type.String(),
"super_admin": ice.SuperAdmin,
"request_id": ice.requestID,
}
if ice.permission != "" {
val["permission"] = ice.permission
}
if ice.channelID != "" {
val["channelID"] = ice.channelID
}
return val, nil
}
type shareClientEvent struct {
action string
id string
relation string
userIDs []string
authn.Session
requestID string
}
func (sce shareClientEvent) Encode() (map[string]any, error) {
return map[string]any{
"operation": clientPrefix + sce.action,
"id": sce.id,
"relation": sce.relation,
"user_ids": sce.userIDs,
"domain": sce.DomainID,
"user_id": sce.UserID,
"token_type": sce.Type.String(),
"super_admin": sce.SuperAdmin,
"request_id": sce.requestID,
}, nil
}
type removeClientEvent struct {
id string
authn.Session
-4
View File
@@ -25,12 +25,8 @@ const (
disableStream = supermqPrefix + clientDisable
removeStream = supermqPrefix + clientRemove
viewStream = supermqPrefix + clientView
viewPermsStream = supermqPrefix + clientViewPerms
listStream = supermqPrefix + clientList
listByUserStream = supermqPrefix + clientListByUser
listByGroupStream = supermqPrefix + clientListByGroup
identifyStream = supermqPrefix + clientIdentify
authorizeStream = supermqPrefix + clientAuthorize
setParentStream = supermqPrefix + clientSetParent
removeParentStream = supermqPrefix + clientRemoveParent
)
+635
View File
@@ -0,0 +1,635 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package events_test
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/absmach/supermq/clients"
"github.com/absmach/supermq/clients/events"
"github.com/absmach/supermq/clients/mocks"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/absmach/supermq/pkg/roles"
"github.com/go-chi/chi/v5/middleware"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
storeClient *redis.Client
storeURL string
validSession = authn.Session{
DomainID: testsutil.GenerateUUID(&testing.T{}),
UserID: testsutil.GenerateUUID(&testing.T{}),
}
validClient = generateTestClient(&testing.T{})
validClientsPage = clients.ClientsPage{
Page: clients.Page{
Limit: 10,
Offset: 0,
Total: 1,
},
Clients: []clients.Client{validClient},
}
)
func newEventStoreMiddleware(t *testing.T) (*mocks.Service, clients.Service) {
svc := new(mocks.Service)
nsvc, err := events.NewEventStoreMiddleware(context.Background(), svc, storeURL)
require.Nil(t, err, fmt.Sprintf("create events store middleware failed with unexpected error: %s", err))
return svc, nsvc
}
func TestMain(m *testing.M) {
code := testsutil.RunRedisTest(m, &storeClient, &storeURL)
os.Exit(code)
}
func TestCreateClients(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validID := testsutil.GenerateUUID(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, validID)
cases := []struct {
desc string
session authn.Session
clients []clients.Client
svcRes []clients.Client
svcRoleRes []roles.RoleProvision
svcErr error
resp []clients.Client
respRoleRes []roles.RoleProvision
err error
}{
{
desc: "publish successfully",
session: validSession,
clients: []clients.Client{validClient},
svcRes: []clients.Client{validClient},
svcRoleRes: []roles.RoleProvision{},
svcErr: nil,
resp: []clients.Client{validClient},
respRoleRes: []roles.RoleProvision{},
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clients: []clients.Client{validClient},
svcRes: []clients.Client{},
svcRoleRes: []roles.RoleProvision{},
svcErr: svcerr.ErrCreateEntity,
resp: []clients.Client{},
respRoleRes: []roles.RoleProvision{},
err: svcerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("CreateClients", validCtx, tc.session, tc.clients).Return(tc.svcRes, tc.svcRoleRes, tc.svcErr)
resp, respRoleRes, err := nsvc.CreateClients(validCtx, tc.session, tc.clients...)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
assert.Equal(t, tc.respRoleRes, respRoleRes, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.respRoleRes, respRoleRes))
svcCall.Unset()
})
}
}
func TestView(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
clientID string
withRoles bool
svcRes clients.Client
svcErr error
resp clients.Client
err error
}{
{
desc: "publish successfully",
session: validSession,
clientID: validClient.ID,
withRoles: false,
svcRes: validClient,
svcErr: nil,
resp: validClient,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clientID: validClient.ID,
withRoles: false,
svcRes: clients.Client{},
svcErr: svcerr.ErrViewEntity,
resp: clients.Client{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("View", validCtx, tc.session, tc.clientID, tc.withRoles).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.View(validCtx, tc.session, tc.clientID, tc.withRoles)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdate(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedClient := validClient
updatedClient.Name = "updatedName"
cases := []struct {
desc string
session authn.Session
client clients.Client
svcRes clients.Client
svcErr error
resp clients.Client
err error
}{
{
desc: "publish successfully",
session: validSession,
client: updatedClient,
svcRes: updatedClient,
svcErr: nil,
resp: updatedClient,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
client: updatedClient,
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
resp: clients.Client{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Update", validCtx, tc.session, tc.client).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.Update(validCtx, tc.session, tc.client)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateTags(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedClient := validClient
updatedClient.Tags = []string{"newTag1", "newTag2"}
cases := []struct {
desc string
session authn.Session
client clients.Client
svcRes clients.Client
svcErr error
resp clients.Client
err error
}{
{
desc: "publish successfully",
session: validSession,
client: updatedClient,
svcRes: updatedClient,
svcErr: nil,
resp: updatedClient,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
client: updatedClient,
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
resp: clients.Client{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateTags", validCtx, tc.session, tc.client).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateTags(validCtx, tc.session, tc.client)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateSecret(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedClient := validClient
updatedClient.Credentials.Secret = "newSecret"
cases := []struct {
desc string
session authn.Session
clientID string
newSecret string
svcRes clients.Client
svcErr error
resp clients.Client
err error
}{
{
desc: "publish successfully",
session: validSession,
clientID: validClient.ID,
newSecret: "newSecret",
svcRes: updatedClient,
svcErr: nil,
resp: updatedClient,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clientID: validClient.ID,
newSecret: "newSecret",
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
resp: clients.Client{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateSecret", validCtx, tc.session, tc.clientID, tc.newSecret).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateSecret(validCtx, tc.session, tc.clientID, tc.newSecret)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestEnable(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
clientID string
svcRes clients.Client
svcErr error
resp clients.Client
err error
}{
{
desc: "publish successfully",
session: validSession,
clientID: validClient.ID,
svcRes: validClient,
svcErr: nil,
resp: validClient,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clientID: validClient.ID,
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
resp: clients.Client{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Enable", validCtx, tc.session, tc.clientID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.Enable(validCtx, tc.session, tc.clientID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDisable(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
clientID string
svcRes clients.Client
svcErr error
resp clients.Client
err error
}{
{
desc: "publish successfully",
session: validSession,
clientID: validClient.ID,
svcRes: validClient,
svcErr: nil,
resp: validClient,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clientID: validClient.ID,
svcRes: clients.Client{},
svcErr: svcerr.ErrUpdateEntity,
resp: clients.Client{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Disable", validCtx, tc.session, tc.clientID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.Disable(validCtx, tc.session, tc.clientID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListClients(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
pageMeta clients.Page
svcRes clients.ClientsPage
svcErr error
resp clients.ClientsPage
err error
}{
{
desc: "publish successfully",
session: validSession,
pageMeta: clients.Page{
Limit: 10,
Offset: 0,
},
svcRes: validClientsPage,
svcErr: nil,
resp: validClientsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
pageMeta: clients.Page{
Limit: 10,
Offset: 0,
},
svcRes: clients.ClientsPage{},
svcErr: svcerr.ErrViewEntity,
resp: clients.ClientsPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListClients", validCtx, tc.session, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListClients(validCtx, tc.session, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListUserClients(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
userID string
pageMeta clients.Page
svcRes clients.ClientsPage
svcErr error
resp clients.ClientsPage
err error
}{
{
desc: "publish successfully",
session: validSession,
userID: validSession.UserID,
pageMeta: clients.Page{
Limit: 10,
Offset: 0,
},
svcRes: validClientsPage,
svcErr: nil,
resp: validClientsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
userID: validSession.UserID,
pageMeta: clients.Page{
Limit: 10,
Offset: 0,
},
svcRes: clients.ClientsPage{},
svcErr: svcerr.ErrViewEntity,
resp: clients.ClientsPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListUserClients", validCtx, tc.session, tc.userID, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListUserClients(validCtx, tc.session, tc.userID, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDelete(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
clientID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
clientID: validClient.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clientID: validClient.ID,
svcErr: svcerr.ErrRemoveEntity,
err: svcerr.ErrRemoveEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Delete", validCtx, tc.session, tc.clientID).Return(tc.svcErr)
err := nsvc.Delete(validCtx, tc.session, tc.clientID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestSetParentGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
parentGroupID string
clientID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
parentGroupID: testsutil.GenerateUUID(t),
clientID: validClient.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
parentGroupID: testsutil.GenerateUUID(t),
clientID: validClient.ID,
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("SetParentGroup", validCtx, tc.session, tc.parentGroupID, tc.clientID).Return(tc.svcErr)
err := nsvc.SetParentGroup(validCtx, tc.session, tc.parentGroupID, tc.clientID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRemoveParentGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
clientID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
clientID: validClient.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
clientID: validClient.ID,
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RemoveParentGroup", validCtx, tc.session, tc.clientID).Return(tc.svcErr)
err := nsvc.RemoveParentGroup(validCtx, tc.session, tc.clientID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func generateTestClient(t *testing.T) clients.Client {
createdAt, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z")
assert.Nil(t, err, fmt.Sprintf("Unexpected error parsing time: %v", err))
return clients.Client{
ID: testsutil.GenerateUUID(t),
Name: "clientname",
Domain: testsutil.GenerateUUID(t),
Tags: []string{"tag1", "tag2"},
Credentials: clients.Credentials{
Identity: "clientidentity",
Secret: "clientsecret",
},
Metadata: clients.Metadata{"key1": "value1"},
CreatedAt: createdAt,
UpdatedAt: createdAt,
Status: clients.EnabledStatus,
}
}
-22
View File
@@ -33,7 +33,6 @@ const (
var (
_ events.Event = (*createDomainEvent)(nil)
_ events.Event = (*retrieveDomainEvent)(nil)
_ events.Event = (*retrieveDomainStatusEvent)(nil)
_ events.Event = (*updateDomainEvent)(nil)
_ events.Event = (*enableDomainEvent)(nil)
_ events.Event = (*disableDomainEvent)(nil)
@@ -120,27 +119,6 @@ func (rde retrieveDomainEvent) Encode() (map[string]any, error) {
return val, nil
}
type retrieveDomainStatusEvent struct {
id string
status domains.Status
authn.Session
requestID string
}
func (rdse retrieveDomainStatusEvent) Encode() (map[string]any, error) {
val := map[string]any{
"operation": domainRetrieve,
"id": rdse.id,
"status": rdse.status.String(),
"user_id": rdse.UserID,
"token_type": rdse.Type.String(),
"super_admin": rdse.SuperAdmin,
"request_id": rdse.requestID,
}
return val, nil
}
type updateDomainEvent struct {
domain domains.Domain
Session authn.Session
+709
View File
@@ -0,0 +1,709 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package events_test
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/absmach/supermq/domains"
"github.com/absmach/supermq/domains/events"
"github.com/absmach/supermq/domains/mocks"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/absmach/supermq/pkg/roles"
"github.com/go-chi/chi/v5/middleware"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
storeClient *redis.Client
storeURL string
validSession = authn.Session{
DomainID: testsutil.GenerateUUID(&testing.T{}),
UserID: testsutil.GenerateUUID(&testing.T{}),
}
validDomain = generateTestDomain(&testing.T{})
validDomainsPage = domains.DomainsPage{
Limit: 10,
Offset: 0,
Total: 1,
Domains: []domains.Domain{validDomain},
}
validInvitation = generateTestInvitation(&testing.T{})
validInvitationsPage = domains.InvitationPage{
Total: 1,
Offset: 0,
Limit: 10,
Invitations: []domains.Invitation{validInvitation},
}
)
func newEventStoreMiddleware(t *testing.T) (*mocks.Service, domains.Service) {
svc := new(mocks.Service)
nsvc, err := events.NewEventStoreMiddleware(context.Background(), svc, storeURL)
require.Nil(t, err, fmt.Sprintf("create events store middleware failed with unexpected error: %s", err))
return svc, nsvc
}
func TestMain(m *testing.M) {
code := testsutil.RunRedisTest(m, &storeClient, &storeURL)
os.Exit(code)
}
func TestCreateDomain(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validID := testsutil.GenerateUUID(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, validID)
cases := []struct {
desc string
session authn.Session
domain domains.Domain
svcRes domains.Domain
svcRoleRes []roles.RoleProvision
svcErr error
resp domains.Domain
respRoleRes []roles.RoleProvision
err error
}{
{
desc: "publish successfully",
session: validSession,
domain: validDomain,
svcRes: validDomain,
svcRoleRes: []roles.RoleProvision{},
svcErr: nil,
resp: validDomain,
respRoleRes: []roles.RoleProvision{},
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domain: validDomain,
svcRes: domains.Domain{},
svcRoleRes: []roles.RoleProvision{},
svcErr: svcerr.ErrCreateEntity,
resp: domains.Domain{},
respRoleRes: []roles.RoleProvision{},
err: svcerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("CreateDomain", validCtx, tc.session, tc.domain).Return(tc.svcRes, tc.svcRoleRes, tc.svcErr)
resp, respRoleRes, err := nsvc.CreateDomain(validCtx, tc.session, tc.domain)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
assert.Equal(t, tc.respRoleRes, respRoleRes, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.respRoleRes, respRoleRes))
svcCall.Unset()
})
}
}
func TestRetrieveDomain(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
domainID string
withRoles bool
svcRes domains.Domain
svcErr error
resp domains.Domain
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
withRoles: false,
svcRes: validDomain,
svcErr: nil,
resp: validDomain,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
withRoles: false,
svcRes: domains.Domain{},
svcErr: svcerr.ErrViewEntity,
resp: domains.Domain{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RetrieveDomain", validCtx, tc.session, tc.domainID, tc.withRoles).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.RetrieveDomain(validCtx, tc.session, tc.domainID, tc.withRoles)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateDomain(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedDomain := validDomain
updatedDomain.Name = "updatedName"
domainReq := domains.DomainReq{
Name: &updatedDomain.Name,
}
cases := []struct {
desc string
session authn.Session
domainID string
domainReq domains.DomainReq
svcRes domains.Domain
svcErr error
resp domains.Domain
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
domainReq: domainReq,
svcRes: updatedDomain,
svcErr: nil,
resp: updatedDomain,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
domainReq: domainReq,
svcRes: domains.Domain{},
svcErr: svcerr.ErrUpdateEntity,
resp: domains.Domain{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateDomain", validCtx, tc.session, tc.domainID, tc.domainReq).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateDomain(validCtx, tc.session, tc.domainID, tc.domainReq)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestEnableDomain(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
domainID string
svcRes domains.Domain
svcErr error
resp domains.Domain
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
svcRes: validDomain,
svcErr: nil,
resp: validDomain,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
svcRes: domains.Domain{},
svcErr: svcerr.ErrUpdateEntity,
resp: domains.Domain{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("EnableDomain", validCtx, tc.session, tc.domainID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.EnableDomain(validCtx, tc.session, tc.domainID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDisableDomain(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
domainID string
svcRes domains.Domain
svcErr error
resp domains.Domain
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
svcRes: validDomain,
svcErr: nil,
resp: validDomain,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
svcRes: domains.Domain{},
svcErr: svcerr.ErrUpdateEntity,
resp: domains.Domain{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("DisableDomain", validCtx, tc.session, tc.domainID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.DisableDomain(validCtx, tc.session, tc.domainID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestFreezeDomain(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
domainID string
svcRes domains.Domain
svcErr error
resp domains.Domain
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
svcRes: validDomain,
svcErr: nil,
resp: validDomain,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
svcRes: domains.Domain{},
svcErr: svcerr.ErrUpdateEntity,
resp: domains.Domain{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("FreezeDomain", validCtx, tc.session, tc.domainID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.FreezeDomain(validCtx, tc.session, tc.domainID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListDomains(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
pageMeta domains.Page
svcRes domains.DomainsPage
svcErr error
resp domains.DomainsPage
err error
}{
{
desc: "publish successfully",
session: validSession,
pageMeta: domains.Page{
Limit: 10,
Offset: 0,
},
svcRes: validDomainsPage,
svcErr: nil,
resp: validDomainsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
pageMeta: domains.Page{
Limit: 10,
Offset: 0,
},
svcRes: domains.DomainsPage{},
svcErr: svcerr.ErrViewEntity,
resp: domains.DomainsPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListDomains", validCtx, tc.session, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListDomains(validCtx, tc.session, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestSendInvitation(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
invitation domains.Invitation
svcRes domains.Invitation
svcErr error
resp domains.Invitation
err error
}{
{
desc: "publish successfully",
session: validSession,
invitation: validInvitation,
svcRes: validInvitation,
svcErr: nil,
resp: validInvitation,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
invitation: validInvitation,
svcRes: domains.Invitation{},
svcErr: svcerr.ErrCreateEntity,
resp: domains.Invitation{},
err: svcerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("SendInvitation", validCtx, tc.session, tc.invitation).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.SendInvitation(validCtx, tc.session, tc.invitation)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListInvitations(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
pageMeta domains.InvitationPageMeta
svcRes domains.InvitationPage
svcErr error
resp domains.InvitationPage
err error
}{
{
desc: "publish successfully",
session: validSession,
pageMeta: domains.InvitationPageMeta{
Limit: 10,
Offset: 0,
},
svcRes: validInvitationsPage,
svcErr: nil,
resp: validInvitationsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
pageMeta: domains.InvitationPageMeta{
Limit: 10,
Offset: 0,
},
svcRes: domains.InvitationPage{},
svcErr: svcerr.ErrViewEntity,
resp: domains.InvitationPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListInvitations", validCtx, tc.session, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListInvitations(validCtx, tc.session, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListDomainInvitations(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
pageMeta domains.InvitationPageMeta
svcRes domains.InvitationPage
svcErr error
resp domains.InvitationPage
err error
}{
{
desc: "publish successfully",
session: validSession,
pageMeta: domains.InvitationPageMeta{
Limit: 10,
Offset: 0,
DomainID: validDomain.ID,
},
svcRes: validInvitationsPage,
svcErr: nil,
resp: validInvitationsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
pageMeta: domains.InvitationPageMeta{
Limit: 10,
Offset: 0,
DomainID: validDomain.ID,
},
svcRes: domains.InvitationPage{},
svcErr: svcerr.ErrViewEntity,
resp: domains.InvitationPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListDomainInvitations", validCtx, tc.session, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListDomainInvitations(validCtx, tc.session, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestAcceptInvitation(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
domainID string
svcRes domains.Invitation
svcErr error
resp domains.Invitation
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
svcRes: validInvitation,
svcErr: nil,
resp: validInvitation,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
svcRes: domains.Invitation{},
svcErr: svcerr.ErrUpdateEntity,
resp: domains.Invitation{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("AcceptInvitation", validCtx, tc.session, tc.domainID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.AcceptInvitation(validCtx, tc.session, tc.domainID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDeleteInvitation(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
inviteeUserID string
domainID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
inviteeUserID: validInvitation.InvitedBy,
domainID: validDomain.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
inviteeUserID: validInvitation.InvitedBy,
domainID: validDomain.ID,
svcErr: svcerr.ErrRemoveEntity,
err: svcerr.ErrRemoveEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("DeleteInvitation", validCtx, tc.session, tc.inviteeUserID, tc.domainID).Return(tc.svcErr)
err := nsvc.DeleteInvitation(validCtx, tc.session, tc.inviteeUserID, tc.domainID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRejectInvitation(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
domainID string
svcRes domains.Invitation
svcErr error
resp domains.Invitation
err error
}{
{
desc: "publish successfully",
session: validSession,
domainID: validDomain.ID,
svcRes: validInvitation,
svcErr: nil,
resp: validInvitation,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
domainID: validDomain.ID,
svcRes: domains.Invitation{},
svcErr: svcerr.ErrUpdateEntity,
resp: domains.Invitation{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RejectInvitation", validCtx, tc.session, tc.domainID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.RejectInvitation(validCtx, tc.session, tc.domainID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func generateTestDomain(t *testing.T) domains.Domain {
createdAt, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z")
assert.Nil(t, err, fmt.Sprintf("Unexpected error parsing time: %v", err))
return domains.Domain{
ID: testsutil.GenerateUUID(t),
Name: "domainname",
Tags: []string{"tag1", "tag2"},
Metadata: domains.Metadata{"key1": "value1"},
CreatedAt: createdAt,
UpdatedAt: createdAt,
Status: domains.EnabledStatus,
}
}
func generateTestInvitation(t *testing.T) domains.Invitation {
createdAt, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z")
assert.Nil(t, err, fmt.Sprintf("Unexpected error parsing time: %v", err))
return domains.Invitation{
InvitedBy: testsutil.GenerateUUID(t),
InviteeUserID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
RoleID: testsutil.GenerateUUID(t),
CreatedAt: createdAt,
UpdatedAt: createdAt,
}
}
-17
View File
@@ -26,7 +26,6 @@ const (
groupRetrieveGroupHierarchy = groupPrefix + "retrieve_group_hierarchy"
groupAddParentGroup = groupPrefix + "add_parent_group"
groupRemoveParentGroup = groupPrefix + "remove_parent_group"
groupViewParentGroup = groupPrefix + "view_parent_group"
groupAddChildrenGroups = groupPrefix + "add_children_groups"
groupRemoveChildrenGroups = groupPrefix + "remove_children_groups"
groupRemoveAllChildrenGroups = groupPrefix + "remove_all_children_groups"
@@ -43,7 +42,6 @@ var (
_ events.Event = (*listGroupEvent)(nil)
_ events.Event = (*addParentGroupEvent)(nil)
_ events.Event = (*removeParentGroupEvent)(nil)
_ events.Event = (*viewParentGroupEvent)(nil)
_ events.Event = (*addChildrenGroupsEvent)(nil)
_ events.Event = (*removeChildrenGroupsEvent)(nil)
_ events.Event = (*removeAllChildrenGroupsEvent)(nil)
@@ -361,21 +359,6 @@ func (rpge removeParentGroupEvent) Encode() (map[string]any, error) {
}, nil
}
type viewParentGroupEvent struct {
id string
domainID string
requestID string
}
func (vpge viewParentGroupEvent) Encode() (map[string]any, error) {
return map[string]any{
"operation": groupViewParentGroup,
"id": vpge.id,
"domain": vpge.domainID,
"request_id": vpge.requestID,
}, nil
}
type addChildrenGroupsEvent struct {
id string
childrenIDs []string
-1
View File
@@ -29,7 +29,6 @@ const (
retrieveHierarchyStream = supermqPrefix + groupRetrieveGroupHierarchy
addParentStream = supermqPrefix + groupAddParentGroup
removeParentStream = supermqPrefix + groupRemoveParentGroup
viewParentStream = supermqPrefix + groupViewParentGroup
addChildrenStream = supermqPrefix + groupAddChildrenGroups
removeChildrenStream = supermqPrefix + groupRemoveChildrenGroups
removeAllChildrenStream = supermqPrefix + groupRemoveAllChildrenGroups
+825
View File
@@ -0,0 +1,825 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package events_test
import (
"context"
"fmt"
"os"
"testing"
"time"
"github.com/absmach/supermq/groups"
"github.com/absmach/supermq/groups/events"
"github.com/absmach/supermq/groups/mocks"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/absmach/supermq/pkg/roles"
"github.com/go-chi/chi/v5/middleware"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
storeClient *redis.Client
storeURL string
validSession = authn.Session{
DomainID: testsutil.GenerateUUID(&testing.T{}),
UserID: testsutil.GenerateUUID(&testing.T{}),
}
validGroup = generateTestGroup(&testing.T{})
validGroupsPage = groups.Page{
PageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
Total: 1,
},
Groups: []groups.Group{validGroup},
}
validHierarchyPage = groups.HierarchyPage{
HierarchyPageMeta: groups.HierarchyPageMeta{
Level: 1,
Direction: -1,
Tree: false,
},
Groups: []groups.Group{validGroup},
}
)
func newEventStoreMiddleware(t *testing.T) (*mocks.Service, groups.Service) {
svc := new(mocks.Service)
nsvc, err := events.New(context.Background(), svc, storeURL)
require.Nil(t, err, fmt.Sprintf("create events store middleware failed with unexpected error: %s", err))
return svc, nsvc
}
func TestMain(m *testing.M) {
code := testsutil.RunRedisTest(m, &storeClient, &storeURL)
os.Exit(code)
}
func TestCreateGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validID := testsutil.GenerateUUID(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, validID)
cases := []struct {
desc string
session authn.Session
group groups.Group
svcRes groups.Group
svcRoleRes []roles.RoleProvision
svcErr error
resp groups.Group
respRoleRes []roles.RoleProvision
err error
}{
{
desc: "publish successfully",
session: validSession,
group: validGroup,
svcRes: validGroup,
svcRoleRes: []roles.RoleProvision{},
svcErr: nil,
resp: validGroup,
respRoleRes: []roles.RoleProvision{},
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
group: validGroup,
svcRes: groups.Group{},
svcRoleRes: []roles.RoleProvision{},
svcErr: svcerr.ErrCreateEntity,
resp: groups.Group{},
respRoleRes: []roles.RoleProvision{},
err: svcerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("CreateGroup", validCtx, tc.session, tc.group).Return(tc.svcRes, tc.svcRoleRes, tc.svcErr)
resp, respRoleRes, err := nsvc.CreateGroup(validCtx, tc.session, tc.group)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
assert.Equal(t, tc.respRoleRes, respRoleRes, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.respRoleRes, respRoleRes))
svcCall.Unset()
})
}
}
func TestViewGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
withRoles bool
svcRes groups.Group
svcErr error
resp groups.Group
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
withRoles: false,
svcRes: validGroup,
svcErr: nil,
resp: validGroup,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
withRoles: false,
svcRes: groups.Group{},
svcErr: svcerr.ErrViewEntity,
resp: groups.Group{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ViewGroup", validCtx, tc.session, tc.groupID, tc.withRoles).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ViewGroup(validCtx, tc.session, tc.groupID, tc.withRoles)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedGroup := validGroup
updatedGroup.Name = "updatedName"
cases := []struct {
desc string
session authn.Session
group groups.Group
svcRes groups.Group
svcErr error
resp groups.Group
err error
}{
{
desc: "publish successfully",
session: validSession,
group: updatedGroup,
svcRes: updatedGroup,
svcErr: nil,
resp: updatedGroup,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
group: updatedGroup,
svcRes: groups.Group{},
svcErr: svcerr.ErrUpdateEntity,
resp: groups.Group{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateGroup", validCtx, tc.session, tc.group).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateGroup(validCtx, tc.session, tc.group)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestUpdateGroupTags(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
updatedGroup := validGroup
updatedGroup.Tags = []string{"newTag1", "newTag2"}
cases := []struct {
desc string
session authn.Session
group groups.Group
svcRes groups.Group
svcErr error
resp groups.Group
err error
}{
{
desc: "publish successfully",
session: validSession,
group: updatedGroup,
svcRes: updatedGroup,
svcErr: nil,
resp: updatedGroup,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
group: updatedGroup,
svcRes: groups.Group{},
svcErr: svcerr.ErrUpdateEntity,
resp: groups.Group{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("UpdateGroupTags", validCtx, tc.session, tc.group).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.UpdateGroupTags(validCtx, tc.session, tc.group)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestEnableGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
svcRes groups.Group
svcErr error
resp groups.Group
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
svcRes: validGroup,
svcErr: nil,
resp: validGroup,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
svcRes: groups.Group{},
svcErr: svcerr.ErrUpdateEntity,
resp: groups.Group{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("EnableGroup", validCtx, tc.session, tc.groupID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.EnableGroup(validCtx, tc.session, tc.groupID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDisableGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
svcRes groups.Group
svcErr error
resp groups.Group
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
svcRes: validGroup,
svcErr: nil,
resp: validGroup,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
svcRes: groups.Group{},
svcErr: svcerr.ErrUpdateEntity,
resp: groups.Group{},
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("DisableGroup", validCtx, tc.session, tc.groupID).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.DisableGroup(validCtx, tc.session, tc.groupID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListGroups(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
pageMeta groups.PageMeta
svcRes groups.Page
svcErr error
resp groups.Page
err error
}{
{
desc: "publish successfully",
session: validSession,
pageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
},
svcRes: validGroupsPage,
svcErr: nil,
resp: validGroupsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
pageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
},
svcRes: groups.Page{},
svcErr: svcerr.ErrViewEntity,
resp: groups.Page{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListGroups", validCtx, tc.session, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListGroups(validCtx, tc.session, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestListUserGroups(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
userID string
pageMeta groups.PageMeta
svcRes groups.Page
svcErr error
resp groups.Page
err error
}{
{
desc: "publish successfully",
session: validSession,
userID: validSession.UserID,
pageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
},
svcRes: validGroupsPage,
svcErr: nil,
resp: validGroupsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
userID: validSession.UserID,
pageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
},
svcRes: groups.Page{},
svcErr: svcerr.ErrViewEntity,
resp: groups.Page{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListUserGroups", validCtx, tc.session, tc.userID, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListUserGroups(validCtx, tc.session, tc.userID, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestDeleteGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
svcErr: svcerr.ErrRemoveEntity,
err: svcerr.ErrRemoveEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("DeleteGroup", validCtx, tc.session, tc.groupID).Return(tc.svcErr)
err := nsvc.DeleteGroup(validCtx, tc.session, tc.groupID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRetrieveGroupHierarchy(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
pageMeta groups.HierarchyPageMeta
svcRes groups.HierarchyPage
svcErr error
resp groups.HierarchyPage
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
pageMeta: groups.HierarchyPageMeta{
Level: 1,
Direction: -1,
Tree: false,
},
svcRes: validHierarchyPage,
svcErr: nil,
resp: validHierarchyPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
pageMeta: groups.HierarchyPageMeta{
Level: 1,
Direction: -1,
Tree: false,
},
svcRes: groups.HierarchyPage{},
svcErr: svcerr.ErrViewEntity,
resp: groups.HierarchyPage{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RetrieveGroupHierarchy", validCtx, tc.session, tc.groupID, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.RetrieveGroupHierarchy(validCtx, tc.session, tc.groupID, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func TestAddParentGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
parentID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
parentID: testsutil.GenerateUUID(t),
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
parentID: testsutil.GenerateUUID(t),
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("AddParentGroup", validCtx, tc.session, tc.groupID, tc.parentID).Return(tc.svcErr)
err := nsvc.AddParentGroup(validCtx, tc.session, tc.groupID, tc.parentID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRemoveParentGroup(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RemoveParentGroup", validCtx, tc.session, tc.groupID).Return(tc.svcErr)
err := nsvc.RemoveParentGroup(validCtx, tc.session, tc.groupID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestAddChildrenGroups(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
childrenGroupIDs []string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
childrenGroupIDs: []string{testsutil.GenerateUUID(t)},
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
childrenGroupIDs: []string{testsutil.GenerateUUID(t)},
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("AddChildrenGroups", validCtx, tc.session, tc.groupID, tc.childrenGroupIDs).Return(tc.svcErr)
err := nsvc.AddChildrenGroups(validCtx, tc.session, tc.groupID, tc.childrenGroupIDs)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRemoveChildrenGroups(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
childrenGroupIDs []string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
childrenGroupIDs: []string{testsutil.GenerateUUID(t)},
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
childrenGroupIDs: []string{testsutil.GenerateUUID(t)},
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RemoveChildrenGroups", validCtx, tc.session, tc.groupID, tc.childrenGroupIDs).Return(tc.svcErr)
err := nsvc.RemoveChildrenGroups(validCtx, tc.session, tc.groupID, tc.childrenGroupIDs)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRemoveAllChildrenGroups(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
svcErr error
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
svcErr: nil,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
svcErr: svcerr.ErrUpdateEntity,
err: svcerr.ErrUpdateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("RemoveAllChildrenGroups", validCtx, tc.session, tc.groupID).Return(tc.svcErr)
err := nsvc.RemoveAllChildrenGroups(validCtx, tc.session, tc.groupID)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestListChildrenGroups(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)
validCtx := context.WithValue(context.Background(), middleware.RequestIDKey, testsutil.GenerateUUID(t))
cases := []struct {
desc string
session authn.Session
groupID string
startLevel int64
endLevel int64
pageMeta groups.PageMeta
svcRes groups.Page
svcErr error
resp groups.Page
err error
}{
{
desc: "publish successfully",
session: validSession,
groupID: validGroup.ID,
startLevel: 1,
endLevel: 5,
pageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
},
svcRes: validGroupsPage,
svcErr: nil,
resp: validGroupsPage,
err: nil,
},
{
desc: "failed to publish with service error",
session: validSession,
groupID: validGroup.ID,
startLevel: 1,
endLevel: 5,
pageMeta: groups.PageMeta{
Limit: 10,
Offset: 0,
},
svcRes: groups.Page{},
svcErr: svcerr.ErrViewEntity,
resp: groups.Page{},
err: svcerr.ErrViewEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("ListChildrenGroups", validCtx, tc.session, tc.groupID, tc.startLevel, tc.endLevel, tc.pageMeta).Return(tc.svcRes, tc.svcErr)
resp, err := nsvc.ListChildrenGroups(validCtx, tc.session, tc.groupID, tc.startLevel, tc.endLevel, tc.pageMeta)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
assert.Equal(t, tc.resp, resp, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.resp, resp))
svcCall.Unset()
})
}
}
func generateTestGroup(t *testing.T) groups.Group {
createdAt, err := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z")
assert.Nil(t, err, fmt.Sprintf("Unexpected error parsing time: %v", err))
return groups.Group{
ID: testsutil.GenerateUUID(t),
Name: "groupname",
Domain: testsutil.GenerateUUID(t),
Tags: []string{"tag1", "tag2"},
Metadata: groups.Metadata{"key1": "value1"},
CreatedAt: createdAt,
UpdatedAt: createdAt,
Status: groups.EnabledStatus,
Level: 1,
}
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package testsutil
import (
"context"
"fmt"
"log"
"testing"
"github.com/ory/dockertest/v3"
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/v9/maintnotifications"
)
type redisContainer struct {
Client *redis.Client
URL string
}
func SetupRedis() (*redisContainer, func(), error) {
pool, err := dockertest.NewPool("")
if err != nil {
return nil, nil, fmt.Errorf("could not connect to docker: %w", err)
}
container, err := pool.Run("docker.io/redis", "8.2.2-alpine3.22", nil)
if err != nil {
return nil, nil, fmt.Errorf("could not start container: %w", err)
}
storeURL := fmt.Sprintf("redis://localhost:%s/0", container.GetPort("6379/tcp"))
opts, err := redis.ParseURL(storeURL)
if err != nil {
_ = pool.Purge(container)
return nil, nil, fmt.Errorf("could not parse redis URL: %w", err)
}
opts.MaintNotificationsConfig = &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
}
var storeClient *redis.Client
if err := pool.Retry(func() error {
storeClient = redis.NewClient(opts)
return storeClient.Ping(context.Background()).Err()
}); err != nil {
_ = pool.Purge(container)
return nil, nil, fmt.Errorf("could not connect to docker: %w", err)
}
cleanup := func() {
if err := pool.Purge(container); err != nil {
log.Fatalf("Could not purge container: %s", err)
}
}
return &redisContainer{
Client: storeClient,
URL: storeURL,
}, cleanup, nil
}
func RunRedisTest(m *testing.M, storeClient **redis.Client, storeURL *string) int {
container, cleanup, err := SetupRedis()
if err != nil {
log.Fatalf("Failed to setup Redis: %s", err)
}
defer cleanup()
*storeClient = container.Client
*storeURL = container.URL
return m.Run()
}
-58
View File
@@ -1,58 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package events_test
import (
"context"
"fmt"
"log"
"os"
"testing"
"github.com/ory/dockertest/v3"
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/v9/maintnotifications"
)
var (
storeClient *redis.Client
storeURL string
)
func TestMain(m *testing.M) {
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("Could not connect to docker: %s", err)
}
container, err := pool.Run("docker.io/redis", "8.2.2-alpine3.22", nil)
if err != nil {
log.Fatalf("Could not start container: %s", err)
}
storeURL = fmt.Sprintf("redis://localhost:%s/0", container.GetPort("6379/tcp"))
opts, err := redis.ParseURL(storeURL)
if err != nil {
log.Fatalf("Could not parse redis URL: %s", err)
}
opts.MaintNotificationsConfig = &maintnotifications.Config{
Mode: maintnotifications.ModeDisabled,
}
if err := pool.Retry(func() error {
storeClient = redis.NewClient(opts)
return storeClient.Ping(context.Background()).Err()
}); err != nil {
log.Fatalf("Could not connect to docker: %s", err)
}
code := m.Run()
if err := pool.Purge(container); err != nil {
log.Fatalf("Could not purge container: %s", err)
}
os.Exit(code)
}
+9
View File
@@ -6,6 +6,7 @@ package events_test
import (
"context"
"fmt"
"os"
"testing"
"time"
@@ -18,11 +19,14 @@ import (
"github.com/absmach/supermq/users/events"
"github.com/absmach/supermq/users/mocks"
"github.com/go-chi/chi/v5/middleware"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
storeClient *redis.Client
storeURL string
validSession = authn.Session{
UserID: testsutil.GenerateUUID(&testing.T{}),
}
@@ -45,6 +49,11 @@ func newEventStoreMiddleware(t *testing.T) (*mocks.Service, users.Service) {
return svc, nsvc
}
func TestMain(m *testing.M) {
code := testsutil.RunRedisTest(m, &storeClient, &storeURL)
os.Exit(code)
}
func TestRegister(t *testing.T) {
svc, nsvc := newEventStoreMiddleware(t)