mirror of
https://github.com/hanzoai/agents.git
synced 2026-10-30 18:48:36 +00:00
897 lines
31 KiB
Go
897 lines
31 KiB
Go
//go:build integration
|
|
// +build integration
|
|
|
|
package ui
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hanzoai/agents/control-plane/internal/events"
|
|
"github.com/hanzoai/agents/control-plane/internal/storage"
|
|
"github.com/hanzoai/agents/control-plane/pkg/types"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
// MockStorageProvider is a mock implementation of storage.StorageProvider
|
|
type MockStorageProvider struct {
|
|
mock.Mock
|
|
}
|
|
|
|
func (m *MockStorageProvider) Initialize(ctx context.Context, config storage.StorageConfig) error {
|
|
args := m.Called(ctx, config)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) Close(ctx context.Context) error {
|
|
args := m.Called(ctx)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) HealthCheck(ctx context.Context) error {
|
|
args := m.Called(ctx)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreExecution(ctx context.Context, execution *types.AgentExecution) error {
|
|
args := m.Called(ctx, execution)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetExecution(ctx context.Context, id int64) (*types.AgentExecution, error) {
|
|
args := m.Called(ctx, id)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.AgentExecution), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QueryExecutions(ctx context.Context, filters types.ExecutionFilters) ([]*types.AgentExecution, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.AgentExecution), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreWorkflowExecution(ctx context.Context, execution *types.WorkflowExecution) error {
|
|
args := m.Called(ctx, execution)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) RegisterExecutionWebhook(ctx context.Context, webhook *types.ExecutionWebhook) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetExecutionWebhook(ctx context.Context, executionID string) (*types.ExecutionWebhook, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListDueExecutionWebhooks(ctx context.Context, limit int) ([]*types.ExecutionWebhook, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) TryMarkExecutionWebhookInFlight(ctx context.Context, executionID string, now time.Time) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateExecutionWebhookState(ctx context.Context, executionID string, update types.ExecutionWebhookStateUpdate) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) HasExecutionWebhook(ctx context.Context, executionID string) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListExecutionWebhooksRegistered(ctx context.Context, executionIDs []string) (map[string]bool, error) {
|
|
return map[string]bool{}, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreExecutionWebhookEvent(ctx context.Context, event *types.ExecutionWebhookEvent) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListExecutionWebhookEvents(ctx context.Context, executionID string) ([]*types.ExecutionWebhookEvent, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListExecutionWebhookEventsBatch(ctx context.Context, executionIDs []string) (map[string][]*types.ExecutionWebhookEvent, error) {
|
|
return map[string][]*types.ExecutionWebhookEvent{}, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreWorkflowExecutionEvent(ctx context.Context, event *types.WorkflowExecutionEvent) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListWorkflowExecutionEvents(ctx context.Context, executionID string, afterSeq *int64, limit int) ([]*types.WorkflowExecutionEvent, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreWorkflowRunEvent(ctx context.Context, event *types.WorkflowRunEvent) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListWorkflowRunEvents(ctx context.Context, runID string, afterSeq *int64, limit int) ([]*types.WorkflowRunEvent, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetWorkflowExecution(ctx context.Context, executionID string) (*types.WorkflowExecution, error) {
|
|
args := m.Called(ctx, executionID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.WorkflowExecution), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateWorkflowExecution(ctx context.Context, executionID string, updateFunc func(execution *types.WorkflowExecution) (*types.WorkflowExecution, error)) error {
|
|
args := m.Called(ctx, executionID, updateFunc)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QueryWorkflowExecutions(ctx context.Context, filters types.WorkflowExecutionFilters) ([]*types.WorkflowExecution, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.WorkflowExecution), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetWorkflowStep(ctx context.Context, stepID string) (*types.WorkflowStep, error) {
|
|
args := m.Called(ctx, stepID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.WorkflowStep), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QueryWorkflowDAG(ctx context.Context, rootWorkflowID string) ([]*types.WorkflowExecution, error) {
|
|
args := m.Called(ctx, rootWorkflowID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.WorkflowExecution), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) CreateOrUpdateWorkflow(ctx context.Context, workflow *types.Workflow) error {
|
|
args := m.Called(ctx, workflow)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetWorkflow(ctx context.Context, workflowID string) (*types.Workflow, error) {
|
|
args := m.Called(ctx, workflowID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.Workflow), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QueryWorkflows(ctx context.Context, filters types.WorkflowFilters) ([]*types.Workflow, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.Workflow), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) CreateOrUpdateSession(ctx context.Context, session *types.Session) error {
|
|
args := m.Called(ctx, session)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetSession(ctx context.Context, sessionID string) (*types.Session, error) {
|
|
args := m.Called(ctx, sessionID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.Session), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QuerySessions(ctx context.Context, filters types.SessionFilters) ([]*types.Session, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.Session), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) SetMemory(ctx context.Context, memory *types.Memory) error {
|
|
args := m.Called(ctx, memory)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetMemory(ctx context.Context, scope, scopeID, key string) (*types.Memory, error) {
|
|
args := m.Called(ctx, scope, scopeID, key)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.Memory), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) DeleteMemory(ctx context.Context, scope, scopeID, key string) error {
|
|
args := m.Called(ctx, scope, scopeID, key)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListMemory(ctx context.Context, scope, scopeID string) ([]*types.Memory, error) {
|
|
args := m.Called(ctx, scope, scopeID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.Memory), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) RegisterAgent(ctx context.Context, agent *types.AgentNode) error {
|
|
args := m.Called(ctx, agent)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetAgent(ctx context.Context, id string) (*types.AgentNode, error) {
|
|
args := m.Called(ctx, id)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.AgentNode), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListAgents(ctx context.Context, filters types.AgentFilters) ([]*types.AgentNode, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.AgentNode), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateAgentHealth(ctx context.Context, id string, status types.HealthStatus) error {
|
|
args := m.Called(ctx, id, status)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateAgentHealthAtomic(ctx context.Context, id string, status types.HealthStatus, expectedLastHeartbeat *time.Time) error {
|
|
args := m.Called(ctx, id, status, expectedLastHeartbeat)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateAgentHeartbeat(ctx context.Context, id string, heartbeatTime time.Time) error {
|
|
args := m.Called(ctx, id, heartbeatTime)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateAgentLifecycleStatus(ctx context.Context, id string, status types.AgentLifecycleStatus) error {
|
|
args := m.Called(ctx, id, status)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) SetConfig(ctx context.Context, key string, value interface{}) error {
|
|
args := m.Called(ctx, key, value)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetConfig(ctx context.Context, key string) (interface{}, error) {
|
|
args := m.Called(ctx, key)
|
|
return args.Get(0), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetReasonerPerformanceMetrics(ctx context.Context, reasonerID string) (*types.ReasonerPerformanceMetrics, error) {
|
|
args := m.Called(ctx, reasonerID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.ReasonerPerformanceMetrics), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetReasonerExecutionHistory(ctx context.Context, reasonerID string, page, limit int) (*types.ReasonerExecutionHistory, error) {
|
|
args := m.Called(ctx, reasonerID, page, limit)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.ReasonerExecutionHistory), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreAgentConfiguration(ctx context.Context, config *types.AgentConfiguration) error {
|
|
args := m.Called(ctx, config)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetAgentConfiguration(ctx context.Context, agentID, packageID string) (*types.AgentConfiguration, error) {
|
|
args := m.Called(ctx, agentID, packageID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.AgentConfiguration), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QueryAgentConfigurations(ctx context.Context, filters types.ConfigurationFilters) ([]*types.AgentConfiguration, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.AgentConfiguration), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateAgentConfiguration(ctx context.Context, config *types.AgentConfiguration) error {
|
|
args := m.Called(ctx, config)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) DeleteAgentConfiguration(ctx context.Context, agentID, packageID string) error {
|
|
args := m.Called(ctx, agentID, packageID)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ValidateAgentConfiguration(ctx context.Context, agentID, packageID string, config map[string]interface{}) (*types.ConfigurationValidationResult, error) {
|
|
args := m.Called(ctx, agentID, packageID, config)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.ConfigurationValidationResult), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) StoreAgentPackage(ctx context.Context, pkg *types.AgentPackage) error {
|
|
args := m.Called(ctx, pkg)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetAgentPackage(ctx context.Context, packageID string) (*types.AgentPackage, error) {
|
|
args := m.Called(ctx, packageID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.AgentPackage), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) QueryAgentPackages(ctx context.Context, filters types.PackageFilters) ([]*types.AgentPackage, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.AgentPackage), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) UpdateAgentPackage(ctx context.Context, pkg *types.AgentPackage) error {
|
|
args := m.Called(ctx, pkg)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) DeleteAgentPackage(ctx context.Context, packageID string) error {
|
|
args := m.Called(ctx, packageID)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) SubscribeToMemoryChanges(ctx context.Context, scope, scopeID string) (<-chan types.MemoryChangeEvent, error) {
|
|
args := m.Called(ctx, scope, scopeID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(<-chan types.MemoryChangeEvent), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) PublishMemoryChange(ctx context.Context, event types.MemoryChangeEvent) error {
|
|
args := m.Called(ctx, event)
|
|
return args.Error(0)
|
|
}
|
|
|
|
// Event operations
|
|
func (m *MockStorageProvider) StoreEvent(ctx context.Context, event *types.MemoryChangeEvent) error {
|
|
args := m.Called(ctx, event)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetEventHistory(ctx context.Context, filter types.EventFilter) ([]*types.MemoryChangeEvent, error) {
|
|
args := m.Called(ctx, filter)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.MemoryChangeEvent), args.Error(1)
|
|
}
|
|
|
|
// Distributed Lock operations
|
|
func (m *MockStorageProvider) AcquireLock(ctx context.Context, key string, timeout time.Duration) (*types.DistributedLock, error) {
|
|
args := m.Called(ctx, key, timeout)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.DistributedLock), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ReleaseLock(ctx context.Context, lockID string) error {
|
|
args := m.Called(ctx, lockID)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) RenewLock(ctx context.Context, lockID string) (*types.DistributedLock, error) {
|
|
args := m.Called(ctx, lockID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.DistributedLock), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetLockStatus(ctx context.Context, key string) (*types.DistributedLock, error) {
|
|
args := m.Called(ctx, key)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.DistributedLock), args.Error(1)
|
|
}
|
|
|
|
// Execution event bus
|
|
func (m *MockStorageProvider) GetExecutionEventBus() *events.ExecutionEventBus {
|
|
args := m.Called()
|
|
if args.Get(0) == nil {
|
|
return nil
|
|
}
|
|
return args.Get(0).(*events.ExecutionEventBus)
|
|
}
|
|
|
|
// DID Registry operations
|
|
func (m *MockStorageProvider) StoreDID(ctx context.Context, did string, didDocument, publicKey, privateKeyRef, derivationPath string) error {
|
|
args := m.Called(ctx, did, didDocument, publicKey, privateKeyRef, derivationPath)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetDID(ctx context.Context, did string) (*types.DIDRegistryEntry, error) {
|
|
args := m.Called(ctx, did)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.DIDRegistryEntry), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListDIDs(ctx context.Context) ([]*types.DIDRegistryEntry, error) {
|
|
args := m.Called(ctx)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.DIDRegistryEntry), args.Error(1)
|
|
}
|
|
|
|
// HanzoAgents Server DID operations
|
|
func (m *MockStorageProvider) StoreHanzoAgentsServerDID(ctx context.Context, hanzoAgentsServerID, rootDID string, masterSeed []byte, createdAt, lastKeyRotation time.Time) error {
|
|
args := m.Called(ctx, hanzoAgentsServerID, rootDID, masterSeed, createdAt, lastKeyRotation)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetHanzoAgentsServerDID(ctx context.Context, hanzoAgentsServerID string) (*types.HanzoAgentsServerDIDInfo, error) {
|
|
args := m.Called(ctx, hanzoAgentsServerID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.HanzoAgentsServerDIDInfo), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListHanzoAgentsServerDIDs(ctx context.Context) ([]*types.HanzoAgentsServerDIDInfo, error) {
|
|
args := m.Called(ctx)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.HanzoAgentsServerDIDInfo), args.Error(1)
|
|
}
|
|
|
|
// Agent DID operations
|
|
func (m *MockStorageProvider) StoreAgentDID(ctx context.Context, agentID, agentDID, hanzoAgentsServerDID, publicKeyJWK string, derivationIndex int) error {
|
|
args := m.Called(ctx, agentID, agentDID, hanzoAgentsServerDID, publicKeyJWK, derivationIndex)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetAgentDID(ctx context.Context, agentID string) (*types.AgentDIDInfo, error) {
|
|
args := m.Called(ctx, agentID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.AgentDIDInfo), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListAgentDIDs(ctx context.Context) ([]*types.AgentDIDInfo, error) {
|
|
args := m.Called(ctx)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.AgentDIDInfo), args.Error(1)
|
|
}
|
|
|
|
// Component DID operations
|
|
func (m *MockStorageProvider) StoreComponentDID(ctx context.Context, componentID, componentDID, agentDID, componentType, componentName string, derivationIndex int) error {
|
|
args := m.Called(ctx, componentID, componentDID, agentDID, componentType, componentName, derivationIndex)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetComponentDID(ctx context.Context, componentID string) (*types.ComponentDIDInfo, error) {
|
|
args := m.Called(ctx, componentID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.ComponentDIDInfo), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListComponentDIDs(ctx context.Context, agentDID string) ([]*types.ComponentDIDInfo, error) {
|
|
args := m.Called(ctx, agentDID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.ComponentDIDInfo), args.Error(1)
|
|
}
|
|
|
|
// Execution VC operations
|
|
func (m *MockStorageProvider) StoreExecutionVC(ctx context.Context, vcID, executionID, workflowID, sessionID, issuerDID, targetDID, callerDID, inputHash, outputHash, status string, vcDocument []byte, signature string, storageURI string, documentSizeBytes int64) error {
|
|
args := m.Called(ctx, vcID, executionID, workflowID, sessionID, issuerDID, targetDID, callerDID, inputHash, outputHash, status, vcDocument, signature)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetExecutionVC(ctx context.Context, vcID string) (*types.ExecutionVCInfo, error) {
|
|
args := m.Called(ctx, vcID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.ExecutionVCInfo), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListExecutionVCs(ctx context.Context, filters types.VCFilters) ([]*types.ExecutionVCInfo, error) {
|
|
args := m.Called(ctx, filters)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.ExecutionVCInfo), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) CountExecutionVCs(ctx context.Context, filters types.VCFilters) (int, error) {
|
|
args := m.Called(ctx, filters)
|
|
return args.Int(0), args.Error(1)
|
|
}
|
|
|
|
// Workflow VC operations
|
|
func (m *MockStorageProvider) StoreWorkflowVC(ctx context.Context, workflowVCID, workflowID, sessionID string, componentVCIDs []string, status string, startTime, endTime *time.Time, totalSteps, completedSteps int, storageURI string, documentSizeBytes int64) error {
|
|
args := m.Called(ctx, workflowVCID, workflowID, sessionID, componentVCIDs, status, startTime, endTime, totalSteps, completedSteps)
|
|
return args.Error(0)
|
|
}
|
|
|
|
func (m *MockStorageProvider) GetWorkflowVC(ctx context.Context, workflowVCID string) (*types.WorkflowVCInfo, error) {
|
|
args := m.Called(ctx, workflowVCID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).(*types.WorkflowVCInfo), args.Error(1)
|
|
}
|
|
|
|
func (m *MockStorageProvider) ListWorkflowVCs(ctx context.Context, workflowID string) ([]*types.WorkflowVCInfo, error) {
|
|
args := m.Called(ctx, workflowID)
|
|
if args.Get(0) == nil {
|
|
return nil, args.Error(1)
|
|
}
|
|
return args.Get(0).([]*types.WorkflowVCInfo), args.Error(1)
|
|
}
|
|
|
|
func setupTestRouter() (*gin.Engine, *MockStorageProvider) {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.New()
|
|
mockStorage := &MockStorageProvider{}
|
|
configHandler := NewConfigHandler(mockStorage)
|
|
|
|
v1 := router.Group("/v1/ui")
|
|
{
|
|
agents := v1.Group("/agents")
|
|
{
|
|
agents.GET("/:agentId/config/schema", configHandler.GetConfigSchemaHandler)
|
|
agents.GET("/:agentId/config", configHandler.GetConfigHandler)
|
|
agents.POST("/:agentId/config", configHandler.SetConfigHandler)
|
|
}
|
|
}
|
|
|
|
return router, mockStorage
|
|
}
|
|
|
|
func TestGetConfigSchemaHandler(t *testing.T) {
|
|
t.Run("Success", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
// Setup mock data
|
|
schema := map[string]interface{}{
|
|
"type": "object",
|
|
"properties": map[string]interface{}{
|
|
"api_key": map[string]interface{}{
|
|
"type": "string",
|
|
"description": "API key for authentication",
|
|
},
|
|
},
|
|
}
|
|
schemaBytes, _ := json.Marshal(schema)
|
|
|
|
agentPackage := &types.AgentPackage{
|
|
ID: "test-package",
|
|
Name: "Test Package",
|
|
Version: "1.0.0",
|
|
Description: stringPtr("Test package description"),
|
|
ConfigurationSchema: schemaBytes,
|
|
}
|
|
|
|
mockStorage.On("GetAgentPackage", "test-package").Return(agentPackage, nil)
|
|
|
|
// Make request
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents/test-agent/config/schema?packageId=test-package", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
// Assert response
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "test-agent", response["agent_id"])
|
|
assert.Equal(t, "test-package", response["package_id"])
|
|
assert.NotNil(t, response["schema"])
|
|
assert.NotNil(t, response["metadata"])
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("Missing AgentId", func(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents//config/schema?packageId=test-package", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code) // Empty agentId should return 400
|
|
})
|
|
|
|
t.Run("Missing PackageId", func(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents/test-agent/config/schema", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
|
|
var response ErrorResponse
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "packageId query parameter is required", response.Error)
|
|
})
|
|
|
|
t.Run("Package Not Found", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
mockStorage.On("GetAgentPackage", "nonexistent-package").Return(nil, fmt.Errorf("package not found"))
|
|
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents/test-agent/config/schema?packageId=nonexistent-package", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusNotFound, w.Code)
|
|
|
|
var response ErrorResponse
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "package not found", response.Error)
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
}
|
|
|
|
func TestGetConfigHandler(t *testing.T) {
|
|
t.Run("Success - Existing Configuration", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
config := &types.AgentConfiguration{
|
|
ID: 1,
|
|
AgentID: "test-agent",
|
|
PackageID: "test-package",
|
|
Configuration: map[string]interface{}{"api_key": "test-key"},
|
|
Status: types.ConfigurationStatusActive,
|
|
Version: 1,
|
|
CreatedAt: time.Now(),
|
|
UpdatedAt: time.Now(),
|
|
}
|
|
|
|
mockStorage.On("GetAgentConfiguration", "test-agent", "test-package").Return(config, nil)
|
|
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents/test-agent/config?packageId=test-package", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "test-agent", response["agent_id"])
|
|
assert.Equal(t, "test-package", response["package_id"])
|
|
assert.NotNil(t, response["configuration"])
|
|
assert.Equal(t, "active", response["status"])
|
|
assert.Equal(t, float64(1), response["version"])
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("Success - No Existing Configuration", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
// Create a fresh mock for this test
|
|
mockStorage.On("GetAgentConfiguration", "test-agent", "test-package").Return(nil, fmt.Errorf("configuration not found"))
|
|
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents/test-agent/config?packageId=test-package", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "test-agent", response["agent_id"])
|
|
assert.Equal(t, "test-package", response["package_id"])
|
|
assert.Equal(t, map[string]interface{}{}, response["configuration"])
|
|
assert.Equal(t, "draft", response["status"])
|
|
assert.Equal(t, float64(0), response["version"])
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("Missing PackageId", func(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
req, _ := http.NewRequest("GET", "/v1/ui/agents/test-agent/config", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
|
|
var response ErrorResponse
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "packageId query parameter is required", response.Error)
|
|
})
|
|
}
|
|
|
|
func TestSetConfigHandler(t *testing.T) {
|
|
t.Run("Success - Create New Configuration", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
requestBody := SetConfigRequest{
|
|
Configuration: map[string]interface{}{"api_key": "new-key"},
|
|
Status: stringPtr("active"),
|
|
}
|
|
bodyBytes, _ := json.Marshal(requestBody)
|
|
|
|
validationResult := &types.ConfigurationValidationResult{
|
|
Valid: true,
|
|
Errors: []string{},
|
|
}
|
|
|
|
mockStorage.On("ValidateAgentConfiguration", "test-agent", "test-package", requestBody.Configuration).Return(validationResult, nil)
|
|
mockStorage.On("GetAgentConfiguration", "test-agent", "test-package").Return(nil, fmt.Errorf("configuration not found"))
|
|
mockStorage.On("StoreAgentConfiguration", mock.AnythingOfType("*types.AgentConfiguration")).Return(nil)
|
|
|
|
req, _ := http.NewRequest("POST", "/v1/ui/agents/test-agent/config?packageId=test-package", bytes.NewBuffer(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusCreated, w.Code)
|
|
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "test-agent", response["agent_id"])
|
|
assert.Equal(t, "test-package", response["package_id"])
|
|
assert.Equal(t, "configuration created successfully", response["message"])
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("Success - Update Existing Configuration", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
requestBody := SetConfigRequest{
|
|
Configuration: map[string]interface{}{"api_key": "updated-key"},
|
|
}
|
|
bodyBytes, _ := json.Marshal(requestBody)
|
|
|
|
existingConfig := &types.AgentConfiguration{
|
|
ID: 1,
|
|
AgentID: "test-agent",
|
|
PackageID: "test-package",
|
|
Configuration: map[string]interface{}{"api_key": "old-key"},
|
|
Status: types.ConfigurationStatusActive,
|
|
Version: 1,
|
|
}
|
|
|
|
validationResult := &types.ConfigurationValidationResult{
|
|
Valid: true,
|
|
Errors: []string{},
|
|
}
|
|
|
|
mockStorage.On("ValidateAgentConfiguration", "test-agent", "test-package", requestBody.Configuration).Return(validationResult, nil)
|
|
mockStorage.On("GetAgentConfiguration", "test-agent", "test-package").Return(existingConfig, nil)
|
|
mockStorage.On("UpdateAgentConfiguration", mock.AnythingOfType("*types.AgentConfiguration")).Return(nil)
|
|
|
|
req, _ := http.NewRequest("POST", "/v1/ui/agents/test-agent/config?packageId=test-package", bytes.NewBuffer(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "test-agent", response["agent_id"])
|
|
assert.Equal(t, "test-package", response["package_id"])
|
|
assert.Equal(t, "configuration updated successfully", response["message"])
|
|
assert.Equal(t, float64(2), response["version"]) // Version should be incremented
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("Validation Failed", func(t *testing.T) {
|
|
router, mockStorage := setupTestRouter()
|
|
requestBody := SetConfigRequest{
|
|
Configuration: map[string]interface{}{"invalid_field": "value"},
|
|
}
|
|
bodyBytes, _ := json.Marshal(requestBody)
|
|
|
|
validationResult := &types.ConfigurationValidationResult{
|
|
Valid: false,
|
|
Errors: []string{"invalid_field is not allowed"},
|
|
}
|
|
|
|
mockStorage.On("ValidateAgentConfiguration", "test-agent", "test-package", requestBody.Configuration).Return(validationResult, nil)
|
|
|
|
req, _ := http.NewRequest("POST", "/v1/ui/agents/test-agent/config?packageId=test-package", bytes.NewBuffer(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
|
|
var response map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "configuration validation failed", response["error"])
|
|
assert.NotNil(t, response["validation_errors"])
|
|
|
|
mockStorage.AssertExpectations(t)
|
|
})
|
|
|
|
t.Run("Invalid Request Body", func(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
req, _ := http.NewRequest("POST", "/v1/ui/agents/test-agent/config?packageId=test-package", bytes.NewBuffer([]byte("invalid json")))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
|
|
var response ErrorResponse
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Contains(t, response.Error, "invalid request body")
|
|
})
|
|
|
|
t.Run("Missing PackageId", func(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
requestBody := SetConfigRequest{
|
|
Configuration: map[string]interface{}{"api_key": "test-key"},
|
|
}
|
|
bodyBytes, _ := json.Marshal(requestBody)
|
|
|
|
req, _ := http.NewRequest("POST", "/v1/ui/agents/test-agent/config", bytes.NewBuffer(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusBadRequest, w.Code)
|
|
|
|
var response ErrorResponse
|
|
err := json.Unmarshal(w.Body.Bytes(), &response)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "packageId query parameter is required", response.Error)
|
|
})
|
|
}
|
|
|
|
// Helper function to create string pointers
|
|
func stringPtr(s string) *string {
|
|
return &s
|
|
}
|