Files
magistrala/alarms/postgres/alarms_test.go
T
Arvindh 16ba29cf4a
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
MG-3537 - Migrate Magistrala to ATOM for identity & authorization (#3532)
Signed-off-by: Arvindh <arvindh91@gmail.com>
Signed-off-by: dusan <borovcanindusan1@gmail.com>
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
Co-authored-by: Dušan Borovčanin <dusan.borovcanin@absmach.eu>
Co-authored-by: Rodney Osodo <socials@rodneyosodo.com>
Co-authored-by: dusan <borovcanindusan1@gmail.com>
2026-06-26 22:06:57 +02:00

482 lines
12 KiB
Go

// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package postgres_test
import (
"context"
"fmt"
"strings"
"testing"
"time"
"github.com/0x6flab/namegenerator"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/alarms/postgres"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
"github.com/absmach/magistrala/pkg/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
namegen = namegenerator.NewGenerator()
idProvider = uuid.New()
)
func TestCreateAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Subtopic: namegen.Generate(),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarm,
err: nil,
},
{
desc: "duplicate alarm",
alarm: alarm,
err: repoerr.ErrNotFound,
},
{
desc: "missing rule id",
alarm: alarms.Alarm{
ID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Subtopic: namegen.Generate(),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
},
err: repoerr.ErrCreateEntity,
},
{
desc: "invalid alarm",
alarm: alarms.Alarm{
ID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Subtopic: namegen.Generate(),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": make(chan int),
},
},
err: repoerr.ErrCreateEntity,
},
{
desc: "empty alarm",
alarm: alarms.Alarm{},
err: repoerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarm, err := repo.CreateAlarm(context.Background(), tc.alarm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.NotEmpty(t, alarm.ID)
assert.Equal(t, tc.alarm.RuleID, alarm.RuleID)
assert.Equal(t, tc.alarm.Measurement, alarm.Measurement)
assert.Equal(t, tc.alarm.Value, alarm.Value)
assert.Equal(t, tc.alarm.Unit, alarm.Unit)
assert.Equal(t, tc.alarm.Cause, alarm.Cause)
assert.Equal(t, tc.alarm.Status, alarm.Status)
assert.Equal(t, tc.alarm.DomainID, alarm.DomainID)
assert.Equal(t, tc.alarm.AssigneeID, alarm.AssigneeID)
assert.Equal(t, tc.alarm.Metadata, alarm.Metadata)
})
}
}
func TestUpdateAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarms.Alarm{
ID: alarm.ID,
Status: alarms.ClearedStatus,
DomainID: alarm.DomainID,
AssigneeID: generateUUID(t),
AssignedBy: generateUUID(t),
AssignedAt: time.Now().UTC(),
AcknowledgedBy: generateUUID(t),
AcknowledgedAt: time.Now().UTC(),
CreatedAt: alarm.CreatedAt,
UpdatedAt: time.Now().UTC(),
UpdatedBy: generateUUID(t),
ResolvedAt: time.Now().UTC(),
ResolvedBy: generateUUID(t),
Metadata: map[string]any{
"key": "value",
},
},
err: nil,
},
{
desc: "non existing alarm",
alarm: alarms.Alarm{
ID: generateUUID(t),
},
err: repoerr.ErrNotFound,
},
{
desc: "invalid alarm",
alarm: alarms.Alarm{
ID: alarm.ID,
RuleID: generateUUID(t),
Status: 0,
DomainID: generateUUID(t),
AssigneeID: strings.Repeat("a", 40),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
},
err: repoerr.ErrMalformedEntity,
},
{
desc: "empty alarm",
alarm: alarms.Alarm{},
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarm, err := repo.UpdateAlarm(context.Background(), tc.alarm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.NotEmpty(t, alarm.ID)
assert.Equal(t, tc.alarm.Status, alarm.Status)
assert.Equal(t, tc.alarm.DomainID, alarm.DomainID)
assert.Equal(t, tc.alarm.AssigneeID, alarm.AssigneeID)
assert.Equal(t, tc.alarm.UpdatedBy, alarm.UpdatedBy)
assert.Equal(t, tc.alarm.ResolvedBy, alarm.ResolvedBy)
assert.Equal(t, tc.alarm.AcknowledgedBy, alarm.AcknowledgedBy)
assert.Equal(t, tc.alarm.Metadata, alarm.Metadata)
})
}
}
func TestViewAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
cases := []struct {
desc string
id string
domainID string
err error
}{
{
desc: "valid alarm",
id: alarm.ID,
domainID: alarm.DomainID,
err: nil,
},
{
desc: "non existing alarm id",
id: generateUUID(t),
domainID: alarm.DomainID,
err: repoerr.ErrNotFound,
},
{
desc: "non existing domain id",
id: alarm.ID,
domainID: generateUUID(t),
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarm, err := repo.ViewAlarm(context.Background(), tc.id, tc.domainID)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.NotEmpty(t, alarm.ID)
assert.Equal(t, tc.id, alarm.ID)
})
}
}
func TestListAlarms(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
items := make([]alarms.Alarm, 1000)
for i := range 1000 {
items[i] = alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), items[i])
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
items[i].ID = alarm.ID
}
cases := []struct {
desc string
pm alarms.PageMetadata
response []alarms.Alarm
err error
}{
{
desc: "valid page",
pm: alarms.PageMetadata{
Offset: 0,
Limit: 10,
},
response: items[:10],
err: nil,
},
{
desc: "offset and limit",
pm: alarms.PageMetadata{
Offset: 10,
Limit: 50,
},
response: items[10:60],
err: nil,
},
{
desc: "empty page",
pm: alarms.PageMetadata{},
response: []alarms.Alarm{},
err: nil,
},
{
desc: "invalid page",
pm: alarms.PageMetadata{
Offset: 1000,
Limit: 10,
},
response: []alarms.Alarm{},
err: nil,
},
{
desc: "invalid assignee id",
pm: alarms.PageMetadata{
Offset: 0,
Limit: 10,
AssigneeID: generateUUID(t),
},
response: []alarms.Alarm{},
err: nil,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarms, err := repo.ListAllAlarms(context.Background(), tc.pm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.Equal(t, len(tc.response), len(alarms.Alarms))
})
}
}
func TestDeleteAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
cases := []struct {
desc string
id string
err error
}{
{
desc: "valid alarm",
id: alarm.ID,
err: nil,
},
{
desc: "non existing alarm",
id: generateUUID(t),
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
err := repo.DeleteAlarm(context.Background(), tc.id)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
})
}
}
func generateUUID(t *testing.T) string {
ulid, err := idProvider.ID()
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
return ulid
}