271 lines
6.9 KiB
Go
Raw Normal View History

package rulebasednotification
import (
"context"
"github.com/prometheus/common/model"
"sync"
"testing"
"time"
"github.com/SigNoz/signoz/pkg/alertmanager/nfmanager"
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
"github.com/prometheus/alertmanager/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func createTestProviderSettings() factory.ProviderSettings {
return instrumentationtest.New().ToProviderSettings()
}
func TestNewFactory(t *testing.T) {
providerFactory := NewFactory()
assert.NotNil(t, providerFactory)
assert.Equal(t, "rulebased", providerFactory.Name().String())
}
func TestNew(t *testing.T) {
ctx := context.Background()
providerSettings := createTestProviderSettings()
config := nfmanager.Config{}
provider, err := New(ctx, providerSettings, config)
require.NoError(t, err)
assert.NotNil(t, provider)
// Verify provider implements the interface correctly
assert.Implements(t, (*nfmanager.NotificationManager)(nil), provider)
}
func TestProvider_SetNotificationConfig(t *testing.T) {
ctx := context.Background()
providerSettings := createTestProviderSettings()
config := nfmanager.Config{}
provider, err := New(ctx, providerSettings, config)
require.NoError(t, err)
tests := []struct {
name string
orgID string
ruleID string
config *alertmanagertypes.NotificationConfig
wantErr bool
}{
{
name: "valid parameters",
orgID: "org1",
ruleID: "rule1",
config: &alertmanagertypes.NotificationConfig{
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: 2 * time.Hour,
NoDataInterval: 2 * time.Hour,
},
},
wantErr: false,
},
{
name: "empty orgID",
orgID: "",
ruleID: "rule1",
config: &alertmanagertypes.NotificationConfig{
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: time.Hour,
NoDataInterval: time.Hour,
},
},
wantErr: true, // Should error due to validation
},
{
name: "empty ruleID",
orgID: "org1",
ruleID: "",
config: &alertmanagertypes.NotificationConfig{
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: time.Hour,
NoDataInterval: time.Hour,
},
},
wantErr: true, // Should error due to validation
},
{
name: "nil config",
orgID: "org1",
ruleID: "rule1",
config: nil,
wantErr: true, // Should error due to nil config
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := provider.SetNotificationConfig(tt.orgID, tt.ruleID, tt.config)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
// If we set a config successfully, we should be able to retrieve it
if tt.orgID != "" && tt.ruleID != "" && tt.config != nil {
retrievedConfig, retrieveErr := provider.GetNotificationConfig(tt.orgID, tt.ruleID)
assert.NoError(t, retrieveErr)
assert.NotNil(t, retrievedConfig)
assert.Equal(t, tt.config.Renotify, retrievedConfig.Renotify)
}
}
})
}
}
func TestProvider_GetNotificationConfig(t *testing.T) {
ctx := context.Background()
providerSettings := createTestProviderSettings()
config := nfmanager.Config{}
provider, err := New(ctx, providerSettings, config)
require.NoError(t, err)
orgID := "test-org"
ruleID := "rule1"
customConfig := &alertmanagertypes.NotificationConfig{
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: 30 * time.Minute,
NoDataInterval: 30 * time.Minute,
},
}
ruleId1 := "rule-1"
customConfig1 := &alertmanagertypes.NotificationConfig{
NotificationGroup: map[model.LabelName]struct{}{
model.LabelName("group1"): {},
model.LabelName("group2"): {},
},
}
// Set config for alert1
err = provider.SetNotificationConfig(orgID, ruleID, customConfig)
require.NoError(t, err)
err = provider.SetNotificationConfig(orgID, ruleId1, customConfig1)
require.NoError(t, err)
tests := []struct {
name string
orgID string
ruleID string
alert *types.Alert
expectedConfig *alertmanagertypes.NotificationConfig
shouldFallback bool
}{
{
name: "existing config",
orgID: orgID,
ruleID: ruleID,
expectedConfig: &alertmanagertypes.NotificationConfig{
NotificationGroup: map[model.LabelName]struct{}{
model.LabelName("ruleId"): {},
},
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: 30 * time.Minute,
NoDataInterval: 30 * time.Minute,
},
},
shouldFallback: false,
},
{
name: "non-existing config - fallback",
orgID: orgID,
ruleID: ruleId1,
expectedConfig: &alertmanagertypes.NotificationConfig{
NotificationGroup: map[model.LabelName]struct{}{
model.LabelName("group1"): {},
model.LabelName("group2"): {},
model.LabelName("ruleId"): {},
},
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: 4 * time.Hour,
NoDataInterval: 4 * time.Hour,
},
}, // Will get fallback from standardnotification
shouldFallback: false,
},
{
name: "empty orgID - fallback",
orgID: "",
ruleID: ruleID,
expectedConfig: nil, // Will get fallback
shouldFallback: true,
},
{
name: "nil alert - fallback",
orgID: orgID,
ruleID: "rule3", // Different ruleID to get fallback
alert: nil,
expectedConfig: nil, // Will get fallback
shouldFallback: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config, err := provider.GetNotificationConfig(tt.orgID, tt.ruleID)
assert.NoError(t, err)
if tt.shouldFallback {
// Should get fallback config (4 hour default)
assert.NotNil(t, config)
assert.Equal(t, 4*time.Hour, config.Renotify.RenotifyInterval)
} else {
// Should get our custom config
assert.NotNil(t, config)
assert.Equal(t, tt.expectedConfig, config)
}
})
}
}
func TestProvider_ConcurrentAccess(t *testing.T) {
ctx := context.Background()
providerSettings := createTestProviderSettings()
config := nfmanager.Config{}
provider, err := New(ctx, providerSettings, config)
require.NoError(t, err)
orgID := "test-org"
var wg sync.WaitGroup
// Writer goroutine
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 50; i++ {
config := &alertmanagertypes.NotificationConfig{
Renotify: alertmanagertypes.ReNotificationConfig{
RenotifyInterval: time.Duration(i+1) * time.Minute,
NoDataInterval: time.Duration(i+1) * time.Minute,
},
}
err := provider.SetNotificationConfig(orgID, "rule1", config)
assert.NoError(t, err)
}
}()
// Reader goroutine
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < 50; i++ {
config, err := provider.GetNotificationConfig(orgID, "rule1")
assert.NoError(t, err)
assert.NotNil(t, config)
}
}()
// Wait for both goroutines to complete
wg.Wait()
}