mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-20 20:04:24 +00:00
refactor: Replace interface{} with any and add comprehensive plugin service tests with benchmarks
- Replace interface{} with any in sendDeactivationRequest method signature in es2_helpers.go
- Add plugin_service_test.go with setupPluginTest helper using in-memory SQLite and gorm.AutoMigrate
- Add TestPluginService_List with test cases for all/enabled/disabled/by-type filtering and no matches
- Add TestPluginService_Install with tests for successful install, duplicate prevention, and missing fields
This commit is contained in:
@@ -39,7 +39,7 @@ func (e *ES2Service) sendActivationRequest(ctx context.Context, req ActivationRe
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ES2Service) sendDeactivationRequest(ctx context.Context, req interface{}) error {
|
||||
func (e *ES2Service) sendDeactivationRequest(ctx context.Context, req any) error {
|
||||
jsonData, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal deactivation request: %w", err)
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/nutcas3/telecom-platform/apps/api-server/internal/database"
|
||||
"github.com/nutcas3/telecom-platform/apps/api-server/internal/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func setupPluginTest(t *testing.T) (*database.Database, *PluginService) {
|
||||
// Use in-memory SQLite for testing
|
||||
gormDB, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Migrate plugin table
|
||||
err = gormDB.AutoMigrate(&models.Plugin{})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create database wrapper
|
||||
db := &database.Database{DB: gormDB}
|
||||
|
||||
// Create service
|
||||
service := NewPluginService(db)
|
||||
|
||||
return db, service
|
||||
}
|
||||
|
||||
func TestPluginService_List(t *testing.T) {
|
||||
db, service := setupPluginTest(t)
|
||||
|
||||
// Create test plugins
|
||||
plugins := []models.Plugin{
|
||||
{
|
||||
Name: "test-plugin-1",
|
||||
Version: "1.0.0",
|
||||
Description: "Test plugin 1",
|
||||
Author: "Test Author",
|
||||
Type: "monitoring",
|
||||
Enabled: true,
|
||||
Status: "installed",
|
||||
},
|
||||
{
|
||||
Name: "test-plugin-2",
|
||||
Version: "2.0.0",
|
||||
Description: "Test plugin 2",
|
||||
Author: "Test Author",
|
||||
Type: "security",
|
||||
Enabled: false,
|
||||
Status: "installed",
|
||||
},
|
||||
}
|
||||
|
||||
for _, plugin := range plugins {
|
||||
err := db.DB.Create(&plugin).Error
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
t.Run("List all plugins", func(t *testing.T) {
|
||||
result, err := service.List(context.Background(), PluginFilter{})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 2)
|
||||
})
|
||||
|
||||
t.Run("List enabled plugins only", func(t *testing.T) {
|
||||
enabled := true
|
||||
result, err := service.List(context.Background(), PluginFilter{
|
||||
Enabled: &enabled,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 1)
|
||||
assert.True(t, result[0].Enabled)
|
||||
})
|
||||
|
||||
t.Run("List disabled plugins only", func(t *testing.T) {
|
||||
enabled := false
|
||||
result, err := service.List(context.Background(), PluginFilter{
|
||||
Enabled: &enabled,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 1)
|
||||
assert.False(t, result[0].Enabled)
|
||||
})
|
||||
|
||||
t.Run("List plugins by type", func(t *testing.T) {
|
||||
result, err := service.List(context.Background(), PluginFilter{
|
||||
Type: "monitoring",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 1)
|
||||
assert.Equal(t, "monitoring", result[0].Type)
|
||||
})
|
||||
|
||||
t.Run("List plugins with no matches", func(t *testing.T) {
|
||||
result, err := service.List(context.Background(), PluginFilter{
|
||||
Type: "nonexistent",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPluginService_Install(t *testing.T) {
|
||||
_, service := setupPluginTest(t)
|
||||
|
||||
t.Run("Install new plugin successfully", func(t *testing.T) {
|
||||
configJSON, _ := json.Marshal(map[string]interface{}{"key": "value"})
|
||||
input := InstallPluginInput{
|
||||
Name: "new-plugin",
|
||||
Version: "1.0.0",
|
||||
Description: "A new plugin",
|
||||
Author: "Test Author",
|
||||
Type: "monitoring",
|
||||
Config: string(configJSON),
|
||||
}
|
||||
|
||||
result, err := service.Install(context.Background(), input)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, input.Name, result.Name)
|
||||
assert.Equal(t, input.Version, result.Version)
|
||||
assert.Equal(t, input.Description, result.Description)
|
||||
assert.Equal(t, input.Author, result.Author)
|
||||
assert.Equal(t, input.Type, result.Type)
|
||||
assert.True(t, result.Enabled)
|
||||
assert.Equal(t, "installed", result.Status)
|
||||
assert.NotZero(t, result.ID)
|
||||
assert.NotZero(t, result.InstalledAt)
|
||||
})
|
||||
|
||||
t.Run("Install duplicate plugin should fail", func(t *testing.T) {
|
||||
input := InstallPluginInput{
|
||||
Name: "duplicate-plugin",
|
||||
Version: "1.0.0",
|
||||
Description: "Duplicate plugin",
|
||||
Author: "Test Author",
|
||||
Type: "monitoring",
|
||||
}
|
||||
|
||||
// First installation should succeed
|
||||
_, err := service.Install(context.Background(), input)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Second installation should fail
|
||||
_, err = service.Install(context.Background(), input)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "UNIQUE constraint failed")
|
||||
})
|
||||
|
||||
t.Run("Install plugin with missing required fields", func(t *testing.T) {
|
||||
input := InstallPluginInput{
|
||||
// Missing name
|
||||
Version: "1.0.0",
|
||||
}
|
||||
|
||||
_, err := service.Install(context.Background(), input)
|
||||
// The service might not validate this, so just check it doesn't panic
|
||||
if err != nil {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPluginService_Get(t *testing.T) {
|
||||
db, service := setupPluginTest(t)
|
||||
|
||||
// Create a plugin
|
||||
plugin := models.Plugin{
|
||||
Name: "test-plugin",
|
||||
Version: "1.0.0",
|
||||
Description: "Test plugin",
|
||||
Author: "Test Author",
|
||||
Type: "monitoring",
|
||||
Enabled: true,
|
||||
Status: "installed",
|
||||
}
|
||||
err := db.DB.Create(&plugin).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Get existing plugin", func(t *testing.T) {
|
||||
result, err := service.Get(context.Background(), plugin.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, plugin.Name, result.Name)
|
||||
assert.Equal(t, plugin.Version, result.Version)
|
||||
assert.Equal(t, plugin.Description, result.Description)
|
||||
})
|
||||
|
||||
t.Run("Get nonexistent plugin", func(t *testing.T) {
|
||||
_, err := service.Get(context.Background(), 999)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "not found")
|
||||
})
|
||||
}
|
||||
|
||||
func TestPluginService_Uninstall(t *testing.T) {
|
||||
db, service := setupPluginTest(t)
|
||||
|
||||
// Create a plugin
|
||||
plugin := models.Plugin{
|
||||
Name: "test-plugin",
|
||||
Version: "1.0.0",
|
||||
Description: "Test plugin",
|
||||
Enabled: true,
|
||||
Status: "installed",
|
||||
}
|
||||
err := db.DB.Create(&plugin).Error
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Uninstall existing plugin", func(t *testing.T) {
|
||||
err := service.Uninstall(context.Background(), plugin.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify plugin is deleted
|
||||
var deletedPlugin models.Plugin
|
||||
err = db.DB.First(&deletedPlugin, plugin.ID).Error
|
||||
assert.Error(t, err) // Should not find the plugin
|
||||
assert.Contains(t, err.Error(), "record not found")
|
||||
})
|
||||
|
||||
t.Run("Uninstall nonexistent plugin", func(t *testing.T) {
|
||||
err := service.Uninstall(context.Background(), 999)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "not found")
|
||||
})
|
||||
}
|
||||
|
||||
// Benchmark tests
|
||||
func BenchmarkPluginService_List(b *testing.B) {
|
||||
db, service := setupPluginTest(&testing.T{})
|
||||
|
||||
// Create test plugins
|
||||
for i := 0; i < 100; i++ {
|
||||
plugin := models.Plugin{
|
||||
Name: fmt.Sprintf("plugin-%d", i),
|
||||
Version: "1.0.0",
|
||||
Description: "Test plugin",
|
||||
Enabled: i%2 == 0,
|
||||
Status: "installed",
|
||||
}
|
||||
db.DB.Create(&plugin)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := service.List(context.Background(), PluginFilter{})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,8 @@ require (
|
||||
|
||||
require (
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.21 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
)
|
||||
|
||||
@@ -4,14 +4,9 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
|
||||
github.com/rs/zerolog v1.35.0 h1:VD0ykx7HMiMJytqINBsKcbLS+BJ4WYjz+05us+LRTdI=
|
||||
github.com/rs/zerolog v1.35.0/go.mod h1:EjML9kdfa/RMA7h/6z6pYmq1ykOuA8/mjWaEvGI+jcw=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
|
||||
Reference in New Issue
Block a user