Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
plugin_test.go15.5 kB
package heimdall import ( "context" "sync" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // MockHeimdallPlugin implements HeimdallPlugin for testing type MockHeimdallPlugin struct { mu sync.RWMutex name string version string description string status SubsystemStatus initialized bool started bool stopped bool shutdown bool ctx SubsystemContext configMap map[string]interface{} events []SubsystemEvent } func NewMockPlugin(name string) *MockHeimdallPlugin { return &MockHeimdallPlugin{ name: name, version: "1.0.0", description: "Mock plugin for testing", status: StatusUninitialized, configMap: make(map[string]interface{}), events: make([]SubsystemEvent, 0), } } func (m *MockHeimdallPlugin) Name() string { return m.name } func (m *MockHeimdallPlugin) Version() string { return m.version } func (m *MockHeimdallPlugin) Type() string { return PluginTypeHeimdall } func (m *MockHeimdallPlugin) Description() string { return m.description } func (m *MockHeimdallPlugin) Initialize(ctx SubsystemContext) error { m.mu.Lock() defer m.mu.Unlock() m.ctx = ctx m.initialized = true m.status = StatusReady return nil } func (m *MockHeimdallPlugin) Start() error { m.mu.Lock() defer m.mu.Unlock() m.started = true m.status = StatusRunning return nil } func (m *MockHeimdallPlugin) Stop() error { m.mu.Lock() defer m.mu.Unlock() m.stopped = true m.status = StatusStopped return nil } func (m *MockHeimdallPlugin) Shutdown() error { m.mu.Lock() defer m.mu.Unlock() m.shutdown = true m.status = StatusUninitialized return nil } func (m *MockHeimdallPlugin) Status() SubsystemStatus { m.mu.RLock() defer m.mu.RUnlock() return m.status } func (m *MockHeimdallPlugin) Health() SubsystemHealth { m.mu.RLock() defer m.mu.RUnlock() return SubsystemHealth{ Status: m.status, Healthy: m.status == StatusRunning, Message: "Mock health", LastCheck: time.Now(), } } func (m *MockHeimdallPlugin) Metrics() map[string]interface{} { return map[string]interface{}{ "mock_metric": 42, } } func (m *MockHeimdallPlugin) Config() map[string]interface{} { m.mu.RLock() defer m.mu.RUnlock() result := make(map[string]interface{}) for k, v := range m.configMap { result[k] = v } return result } func (m *MockHeimdallPlugin) Configure(settings map[string]interface{}) error { m.mu.Lock() defer m.mu.Unlock() for k, v := range settings { m.configMap[k] = v } return nil } func (m *MockHeimdallPlugin) ConfigSchema() map[string]interface{} { return map[string]interface{}{ "type": "object", } } func (m *MockHeimdallPlugin) Actions() map[string]ActionFunc { return map[string]ActionFunc{ "test_action": { Name: "test_action", Description: "A test action", Category: "testing", Handler: func(ctx ActionContext) (*ActionResult, error) { return &ActionResult{ Success: true, Message: "Test action executed", Data: map[string]interface{}{ "user_message": ctx.UserMessage, }, }, nil }, }, "bifrost_action": { Name: "bifrost_action", Description: "Tests Bifrost bridge", Category: "testing", Handler: func(ctx ActionContext) (*ActionResult, error) { if ctx.Bifrost != nil { ctx.Bifrost.SendMessage("Test message via Bifrost") } return &ActionResult{ Success: true, Message: "Bifrost action executed", }, nil }, }, } } func (m *MockHeimdallPlugin) Summary() string { return "Mock plugin summary" } func (m *MockHeimdallPlugin) RecentEvents(limit int) []SubsystemEvent { m.mu.RLock() defer m.mu.RUnlock() if limit > len(m.events) { limit = len(m.events) } return m.events[:limit] } func (m *MockHeimdallPlugin) PrePrompt(ctx *PromptContext) error { // No-op for mock return nil } func (m *MockHeimdallPlugin) PreExecute(ctx *PreExecuteContext, done func(PreExecuteResult)) { // Default: continue with execution done(PreExecuteResult{Continue: true}) } func (m *MockHeimdallPlugin) PostExecute(ctx *PostExecuteContext) { // No-op for mock } // MockBifrost implements BifrostBridge for testing type MockBifrost struct { mu sync.Mutex messages []string notifications []struct { Type, Title, Message string } broadcasts []string confirmations bool connected bool connCount int } func NewMockBifrost() *MockBifrost { return &MockBifrost{ messages: make([]string, 0), broadcasts: make([]string, 0), confirmations: true, connected: true, connCount: 1, } } func (b *MockBifrost) SendMessage(msg string) error { b.mu.Lock() defer b.mu.Unlock() b.messages = append(b.messages, msg) return nil } func (b *MockBifrost) SendNotification(notifType, title, message string) error { b.mu.Lock() defer b.mu.Unlock() b.notifications = append(b.notifications, struct{ Type, Title, Message string }{notifType, title, message}) return nil } func (b *MockBifrost) Broadcast(msg string) error { b.mu.Lock() defer b.mu.Unlock() b.broadcasts = append(b.broadcasts, msg) return nil } func (b *MockBifrost) RequestConfirmation(action string) (bool, error) { return b.confirmations, nil } func (b *MockBifrost) IsConnected() bool { return b.connected } func (b *MockBifrost) ConnectionCount() int { return b.connCount } // Tests func TestPluginTypeHeimdall(t *testing.T) { assert.Equal(t, "heimdall", PluginTypeHeimdall) } func TestSubsystemManager_Singleton(t *testing.T) { // Reset global manager for test globalManager = nil m1 := GetSubsystemManager() m2 := GetSubsystemManager() assert.Same(t, m1, m2, "GetSubsystemManager should return same instance") } func TestSubsystemManager_RegisterPlugin(t *testing.T) { // Create fresh manager for test manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test_plugin") err := manager.RegisterPlugin(plugin, "", true) require.NoError(t, err) // Verify plugin is registered registered, ok := manager.GetPlugin("test_plugin") assert.True(t, ok) assert.Equal(t, "test_plugin", registered.Name()) // Verify plugin was initialized assert.True(t, plugin.initialized) assert.Equal(t, StatusReady, plugin.Status()) } func TestSubsystemManager_RegisterPlugin_WrongType(t *testing.T) { manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } ctx := SubsystemContext{Config: DefaultConfig()} manager.SetContext(ctx) // Plugin that returns wrong type plugin := &wrongTypePlugin{} err := manager.RegisterPlugin(plugin, "", true) assert.Error(t, err) assert.Contains(t, err.Error(), "expected") } // wrongTypePlugin returns wrong type type wrongTypePlugin struct { MockHeimdallPlugin } func (w *wrongTypePlugin) Type() string { return "wrong_type" } func TestSubsystemManager_RegisterActions(t *testing.T) { manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test_plugin") err := manager.RegisterPlugin(plugin, "", true) require.NoError(t, err) // Verify actions are registered with full names action, ok := manager.GetAction("heimdall.test_plugin.test_action") assert.True(t, ok) assert.Equal(t, "A test action", action.Description) } func TestSubsystemManager_StartAll(t *testing.T) { manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test_plugin") err := manager.RegisterPlugin(plugin, "", true) require.NoError(t, err) err = manager.StartAll() require.NoError(t, err) assert.True(t, plugin.started) assert.Equal(t, StatusRunning, plugin.Status()) } func TestSubsystemManager_StopAll(t *testing.T) { manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test_plugin") _ = manager.RegisterPlugin(plugin, "", true) _ = manager.StartAll() err := manager.StopAll() require.NoError(t, err) assert.True(t, plugin.stopped) assert.Equal(t, StatusStopped, plugin.Status()) } func TestSubsystemManager_ShutdownAll(t *testing.T) { manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test_plugin") _ = manager.RegisterPlugin(plugin, "", true) _ = manager.StartAll() err := manager.ShutdownAll() require.NoError(t, err) assert.True(t, plugin.shutdown) assert.Equal(t, StatusUninitialized, plugin.Status()) } func TestNoOpBifrost(t *testing.T) { bifrost := &NoOpBifrost{} // All operations should succeed silently assert.NoError(t, bifrost.SendMessage("test")) assert.NoError(t, bifrost.SendNotification("info", "title", "msg")) assert.NoError(t, bifrost.Broadcast("broadcast")) confirmed, err := bifrost.RequestConfirmation("action") assert.NoError(t, err) assert.False(t, confirmed) assert.False(t, bifrost.IsConnected()) assert.Equal(t, 0, bifrost.ConnectionCount()) } func TestMockBifrost(t *testing.T) { bifrost := NewMockBifrost() // Test SendMessage err := bifrost.SendMessage("Hello") require.NoError(t, err) assert.Len(t, bifrost.messages, 1) assert.Equal(t, "Hello", bifrost.messages[0]) // Test SendNotification err = bifrost.SendNotification("warning", "Alert", "Something happened") require.NoError(t, err) assert.Len(t, bifrost.notifications, 1) assert.Equal(t, "warning", bifrost.notifications[0].Type) // Test Broadcast err = bifrost.Broadcast("System message") require.NoError(t, err) assert.Len(t, bifrost.broadcasts, 1) // Test RequestConfirmation confirmed, err := bifrost.RequestConfirmation("delete") require.NoError(t, err) assert.True(t, confirmed) // Test connection status assert.True(t, bifrost.IsConnected()) assert.Equal(t, 1, bifrost.ConnectionCount()) } func TestActionContext_WithBifrost(t *testing.T) { bifrost := NewMockBifrost() ctx := ActionContext{ Context: context.Background(), UserMessage: "Test message", Params: map[string]interface{}{"key": "value"}, Bifrost: bifrost, } // Simulate action using Bifrost ctx.Bifrost.SendMessage("Action started") ctx.Bifrost.SendNotification("info", "Progress", "50% complete") ctx.Bifrost.Broadcast("Action finished") assert.Len(t, bifrost.messages, 1) assert.Len(t, bifrost.notifications, 1) assert.Len(t, bifrost.broadcasts, 1) } func TestSubsystemStatus_Constants(t *testing.T) { statuses := []SubsystemStatus{ StatusUninitialized, StatusInitializing, StatusReady, StatusRunning, StatusStopping, StatusStopped, StatusError, } // All should be distinct strings seen := make(map[SubsystemStatus]bool) for _, s := range statuses { assert.False(t, seen[s], "Duplicate status: %s", s) seen[s] = true } } func TestSubsystemHealth(t *testing.T) { health := SubsystemHealth{ Status: StatusRunning, Healthy: true, Message: "All systems operational", LastCheck: time.Now(), Details: map[string]interface{}{ "uptime": 3600, }, } assert.True(t, health.Healthy) assert.Equal(t, StatusRunning, health.Status) assert.Equal(t, int(3600), health.Details["uptime"]) } func TestSubsystemEvent(t *testing.T) { event := SubsystemEvent{ Time: time.Now(), Type: "info", Message: "Something happened", Data: map[string]interface{}{ "count": 42, }, } assert.Equal(t, "info", event.Type) assert.Equal(t, 42, event.Data["count"]) } func TestActionFunc(t *testing.T) { action := ActionFunc{ Name: "heimdall.test.action", Description: "Test action", Category: "testing", Handler: func(ctx ActionContext) (*ActionResult, error) { return &ActionResult{ Success: true, Message: "Done", }, nil }, } assert.Equal(t, "heimdall.test.action", action.Name) assert.Equal(t, "testing", action.Category) // Execute the handler result, err := action.Handler(ActionContext{}) require.NoError(t, err) assert.True(t, result.Success) } func TestActionResult(t *testing.T) { result := ActionResult{ Success: true, Message: "Operation completed", Data: map[string]interface{}{ "items_processed": 100, }, } assert.True(t, result.Success) assert.Equal(t, 100, result.Data["items_processed"]) } func TestListHeimdallPlugins(t *testing.T) { // Reset global manager globalManager = nil manager := GetSubsystemManager() ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin1 := NewMockPlugin("plugin1") plugin2 := NewMockPlugin("plugin2") _ = manager.RegisterPlugin(plugin1, "", true) _ = manager.RegisterPlugin(plugin2, "/path/to/plugin2.so", false) plugins := ListHeimdallPlugins() assert.Len(t, plugins, 2) // Find by name names := make(map[string]bool) for _, p := range plugins { names[p.Plugin.Name()] = true } assert.True(t, names["plugin1"]) assert.True(t, names["plugin2"]) } func TestListHeimdallActions(t *testing.T) { // Reset global manager globalManager = nil manager := GetSubsystemManager() ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test") _ = manager.RegisterPlugin(plugin, "", true) actions := ListHeimdallActions() // Should have actions from the mock plugin found := false for _, name := range actions { if name == "heimdall.test.test_action" { found = true break } } assert.True(t, found, "Should find heimdall.test.test_action in actions list") } func TestGetHeimdallAction(t *testing.T) { // Reset global manager globalManager = nil manager := GetSubsystemManager() ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test") _ = manager.RegisterPlugin(plugin, "", true) action, ok := GetHeimdallAction("heimdall.test.test_action") assert.True(t, ok) assert.Equal(t, "A test action", action.Description) _, ok = GetHeimdallAction("heimdall.nonexistent.action") assert.False(t, ok) } func TestHeimdallPluginsInitialized(t *testing.T) { // Create a fresh manager for this test (don't use global) manager := &SubsystemManager{ plugins: make(map[string]*LoadedHeimdallPlugin), actions: make(map[string]ActionFunc), } // Not initialized yet assert.False(t, manager.initialized) ctx := SubsystemContext{ Config: DefaultConfig(), Bifrost: &NoOpBifrost{}, } manager.SetContext(ctx) plugin := NewMockPlugin("test_init") _ = manager.RegisterPlugin(plugin, "", true) // After registering a plugin, should be initialized assert.True(t, manager.initialized) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server