758 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			758 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build slurp_full
 | |
| // +build slurp_full
 | |
| 
 | |
| package temporal
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	slurpContext "chorus/pkg/slurp/context"
 | |
| 	"chorus/pkg/slurp/storage"
 | |
| 	"chorus/pkg/ucxl"
 | |
| )
 | |
| 
 | |
| // Integration tests for the complete temporal graph system
 | |
| 
 | |
| func TestTemporalGraphSystem_FullIntegration(t *testing.T) {
 | |
| 	// Create a complete temporal graph system
 | |
| 	system := createTestSystem(t)
 | |
| 	ctx := context.Background()
 | |
| 
 | |
| 	// Test scenario: E-commerce platform evolution
 | |
| 	// Services: user-service, product-service, order-service, payment-service, notification-service
 | |
| 
 | |
| 	services := []string{
 | |
| 		"user-service",
 | |
| 		"product-service",
 | |
| 		"order-service",
 | |
| 		"payment-service",
 | |
| 		"notification-service",
 | |
| 	}
 | |
| 
 | |
| 	addresses := make([]ucxl.Address, len(services))
 | |
| 
 | |
| 	// Phase 1: Initial architecture setup
 | |
| 	t.Log("Phase 1: Creating initial microservices architecture")
 | |
| 
 | |
| 	for i, service := range services {
 | |
| 		addresses[i] = createTestAddress(fmt.Sprintf("ecommerce/%s", service))
 | |
| 
 | |
| 		initialContext := &slurpContext.ContextNode{
 | |
| 			Path:          fmt.Sprintf("ecommerce/%s", service),
 | |
| 			UCXLAddress:   addresses[i],
 | |
| 			Summary:       fmt.Sprintf("%s handles %s functionality", service, service[:len(service)-8]),
 | |
| 			Purpose:       fmt.Sprintf("Manage %s operations in e-commerce platform", service[:len(service)-8]),
 | |
| 			Technologies:  []string{"go", "grpc", "postgres"},
 | |
| 			Tags:          []string{"microservice", "ecommerce"},
 | |
| 			Insights:      []string{fmt.Sprintf("Core service for %s management", service[:len(service)-8])},
 | |
| 			GeneratedAt:   time.Now(),
 | |
| 			RAGConfidence: 0.8,
 | |
| 		}
 | |
| 
 | |
| 		_, err := system.Graph.CreateInitialContext(ctx, addresses[i], initialContext, "architect")
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("Failed to create %s: %v", service, err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Phase 2: Establish service dependencies
 | |
| 	t.Log("Phase 2: Establishing service dependencies")
 | |
| 
 | |
| 	dependencies := []struct {
 | |
| 		from, to int
 | |
| 		reason   string
 | |
| 	}{
 | |
| 		{2, 0, "Order service needs user validation"},         // order -> user
 | |
| 		{2, 1, "Order service needs product information"},     // order -> product
 | |
| 		{2, 3, "Order service needs payment processing"},      // order -> payment
 | |
| 		{2, 4, "Order service triggers notifications"},        // order -> notification
 | |
| 		{3, 4, "Payment service sends payment confirmations"}, // payment -> notification
 | |
| 	}
 | |
| 
 | |
| 	for _, dep := range dependencies {
 | |
| 		err := system.Graph.AddInfluenceRelationship(ctx, addresses[dep.from], addresses[dep.to])
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("Failed to add dependency %s -> %s: %v",
 | |
| 				services[dep.from], services[dep.to], err)
 | |
| 		}
 | |
| 		t.Logf("Added dependency: %s -> %s (%s)",
 | |
| 			services[dep.from], services[dep.to], dep.reason)
 | |
| 	}
 | |
| 
 | |
| 	// Phase 3: System evolution - Add caching layer
 | |
| 	t.Log("Phase 3: Adding Redis caching to improve performance")
 | |
| 
 | |
| 	for i, service := range []string{"user-service", "product-service"} {
 | |
| 		addr := addresses[i]
 | |
| 
 | |
| 		updatedContext := &slurpContext.ContextNode{
 | |
| 			Path:         fmt.Sprintf("ecommerce/%s", service),
 | |
| 			UCXLAddress:  addr,
 | |
| 			Summary:      fmt.Sprintf("%s with Redis caching layer", service),
 | |
| 			Purpose:      fmt.Sprintf("Manage %s with improved performance", service[:len(service)-8]),
 | |
| 			Technologies: []string{"go", "grpc", "postgres", "redis"},
 | |
| 			Tags:         []string{"microservice", "ecommerce", "cached"},
 | |
| 			Insights: []string{
 | |
| 				fmt.Sprintf("Core service for %s management", service[:len(service)-8]),
 | |
| 				"Improved response times with Redis caching",
 | |
| 				"Reduced database load",
 | |
| 			},
 | |
| 			GeneratedAt:   time.Now(),
 | |
| 			RAGConfidence: 0.85,
 | |
| 		}
 | |
| 
 | |
| 		decision := &DecisionMetadata{
 | |
| 			ID:                   fmt.Sprintf("perf-cache-%d", i+1),
 | |
| 			Maker:                "performance-team",
 | |
| 			Rationale:            "Add Redis caching to improve response times and reduce database load",
 | |
| 			Scope:                ImpactModule,
 | |
| 			ConfidenceLevel:      0.9,
 | |
| 			ExternalRefs:         []string{"PERF-123", "https://wiki/caching-strategy"},
 | |
| 			CreatedAt:            time.Now(),
 | |
| 			ImplementationStatus: "completed",
 | |
| 			Metadata:             map[string]interface{}{"performance_improvement": "40%"},
 | |
| 		}
 | |
| 
 | |
| 		_, err := system.Graph.EvolveContext(ctx, addr, updatedContext, ReasonPerformanceInsight, decision)
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("Failed to add caching to %s: %v", service, err)
 | |
| 		}
 | |
| 
 | |
| 		t.Logf("Added Redis caching to %s", service)
 | |
| 	}
 | |
| 
 | |
| 	// Phase 4: Security enhancement - Payment service PCI compliance
 | |
| 	t.Log("Phase 4: Implementing PCI compliance for payment service")
 | |
| 
 | |
| 	paymentAddr := addresses[3] // payment-service
 | |
| 	securePaymentContext := &slurpContext.ContextNode{
 | |
| 		Path:         "ecommerce/payment-service",
 | |
| 		UCXLAddress:  paymentAddr,
 | |
| 		Summary:      "PCI-compliant payment service with end-to-end encryption",
 | |
| 		Purpose:      "Securely process payments with PCI DSS compliance",
 | |
| 		Technologies: []string{"go", "grpc", "postgres", "vault", "encryption"},
 | |
| 		Tags:         []string{"microservice", "ecommerce", "secure", "pci-compliant"},
 | |
| 		Insights: []string{
 | |
| 			"Core service for payment management",
 | |
| 			"PCI DSS Level 1 compliant",
 | |
| 			"End-to-end encryption implemented",
 | |
| 			"Secure key management with HashiCorp Vault",
 | |
| 		},
 | |
| 		GeneratedAt:   time.Now(),
 | |
| 		RAGConfidence: 0.95,
 | |
| 	}
 | |
| 
 | |
| 	securityDecision := &DecisionMetadata{
 | |
| 		ID:                   "sec-pci-001",
 | |
| 		Maker:                "security-team",
 | |
| 		Rationale:            "Implement PCI DSS compliance for handling credit card data",
 | |
| 		Scope:                ImpactProject,
 | |
| 		ConfidenceLevel:      0.95,
 | |
| 		ExternalRefs:         []string{"SEC-456", "https://pcisecuritystandards.org"},
 | |
| 		CreatedAt:            time.Now(),
 | |
| 		ImplementationStatus: "completed",
 | |
| 		Metadata: map[string]interface{}{
 | |
| 			"compliance_level": "PCI DSS Level 1",
 | |
| 			"audit_date":       time.Now().Format("2006-01-02"),
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	_, err := system.Graph.EvolveContext(ctx, paymentAddr, securePaymentContext, ReasonSecurityReview, securityDecision)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to implement PCI compliance: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Phase 5: Analyze impact and relationships
 | |
| 	t.Log("Phase 5: Analyzing system impact and relationships")
 | |
| 
 | |
| 	// Test influence analysis
 | |
| 	analysis, err := system.InfluenceAnalyzer.AnalyzeInfluenceNetwork(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to analyze influence network: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Network analysis: %d nodes, %d edges, density: %.3f",
 | |
| 		analysis.TotalNodes, analysis.TotalEdges, analysis.NetworkDensity)
 | |
| 
 | |
| 	// Order service should be central (influences most other services)
 | |
| 	if len(analysis.CentralNodes) > 0 {
 | |
| 		t.Logf("Most central nodes:")
 | |
| 		for i, node := range analysis.CentralNodes {
 | |
| 			if i >= 3 { // Limit output
 | |
| 				break
 | |
| 			}
 | |
| 			t.Logf("  %s (influence score: %.3f)", node.Address.String(), node.InfluenceScore)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Test decision impact analysis
 | |
| 	paymentEvolution, err := system.Graph.GetEvolutionHistory(ctx, paymentAddr)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to get payment service evolution: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	if len(paymentEvolution) < 2 {
 | |
| 		t.Fatalf("Expected at least 2 versions in payment service evolution, got %d", len(paymentEvolution))
 | |
| 	}
 | |
| 
 | |
| 	latestVersion := paymentEvolution[len(paymentEvolution)-1]
 | |
| 	impact, err := system.InfluenceAnalyzer.AnalyzeDecisionImpact(ctx, paymentAddr, latestVersion.Version)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to analyze payment service impact: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Payment service security impact: %d direct impacts, strength: %.3f",
 | |
| 		len(impact.DirectImpact), impact.ImpactStrength)
 | |
| 
 | |
| 	// Test staleness detection
 | |
| 	staleContexts, err := system.StalenessDetector.DetectStaleContexts(ctx, 0.3)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to detect stale contexts: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Found %d potentially stale contexts", len(staleContexts))
 | |
| 
 | |
| 	// Phase 6: Query system testing
 | |
| 	t.Log("Phase 6: Testing decision-hop queries")
 | |
| 
 | |
| 	// Find all services within 2 hops of order service
 | |
| 	orderAddr := addresses[2] // order-service
 | |
| 	hopQuery := &HopQuery{
 | |
| 		StartAddress: orderAddr,
 | |
| 		MaxHops:      2,
 | |
| 		Direction:    "both",
 | |
| 		FilterCriteria: &HopFilter{
 | |
| 			MinConfidence: 0.7,
 | |
| 		},
 | |
| 		SortCriteria: &HopSort{
 | |
| 			SortBy:        "hops",
 | |
| 			SortDirection: "asc",
 | |
| 		},
 | |
| 		Limit:           10,
 | |
| 		IncludeMetadata: true,
 | |
| 	}
 | |
| 
 | |
| 	queryResult, err := system.QuerySystem.ExecuteHopQuery(ctx, hopQuery)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to execute hop query: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Hop query found %d related decisions in %v",
 | |
| 		len(queryResult.Results), queryResult.ExecutionTime)
 | |
| 
 | |
| 	for _, result := range queryResult.Results {
 | |
| 		t.Logf("  %s at %d hops (relevance: %.3f)",
 | |
| 			result.Address.String(), result.HopDistance, result.RelevanceScore)
 | |
| 	}
 | |
| 
 | |
| 	// Test decision genealogy
 | |
| 	genealogy, err := system.QuerySystem.AnalyzeDecisionGenealogy(ctx, paymentAddr)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to analyze payment service genealogy: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Payment service genealogy: %d ancestors, %d descendants, depth: %d",
 | |
| 		len(genealogy.AllAncestors), len(genealogy.AllDescendants), genealogy.GenealogyDepth)
 | |
| 
 | |
| 	// Phase 7: Persistence and synchronization testing
 | |
| 	t.Log("Phase 7: Testing persistence and synchronization")
 | |
| 
 | |
| 	// Test backup
 | |
| 	err = system.PersistenceManager.BackupGraph(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to backup graph: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Test synchronization
 | |
| 	syncResult, err := system.PersistenceManager.SynchronizeGraph(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to synchronize graph: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Synchronization completed: %d nodes processed, %d conflicts resolved",
 | |
| 		syncResult.NodesProcessed, syncResult.ConflictsResolved)
 | |
| 
 | |
| 	// Phase 8: System validation
 | |
| 	t.Log("Phase 8: Validating system integrity")
 | |
| 
 | |
| 	// Validate temporal integrity
 | |
| 	err = system.Graph.ValidateTemporalIntegrity(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Temporal integrity validation failed: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Collect metrics
 | |
| 	metrics, err := system.MetricsCollector.CollectTemporalMetrics(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to collect temporal metrics: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("System metrics: %d total nodes, %d decisions, %d active contexts",
 | |
| 		metrics.TotalNodes, metrics.TotalDecisions, metrics.ActiveContexts)
 | |
| 
 | |
| 	// Final verification: Check that all expected relationships exist
 | |
| 	expectedConnections := []struct {
 | |
| 		from, to int
 | |
| 	}{
 | |
| 		{2, 0}, {2, 1}, {2, 3}, {2, 4}, {3, 4}, // Dependencies we created
 | |
| 	}
 | |
| 
 | |
| 	for _, conn := range expectedConnections {
 | |
| 		influences, _, err := system.Graph.GetInfluenceRelationships(ctx, addresses[conn.from])
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("Failed to get influence relationships: %v", err)
 | |
| 		}
 | |
| 
 | |
| 		found := false
 | |
| 		for _, influenced := range influences {
 | |
| 			if influenced.String() == addresses[conn.to].String() {
 | |
| 				found = true
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if !found {
 | |
| 			t.Errorf("Expected influence relationship %s -> %s not found",
 | |
| 				services[conn.from], services[conn.to])
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	t.Log("Integration test completed successfully!")
 | |
| }
 | |
| 
 | |
| func TestTemporalGraphSystem_PerformanceUnderLoad(t *testing.T) {
 | |
| 	system := createTestSystem(t)
 | |
| 	ctx := context.Background()
 | |
| 
 | |
| 	t.Log("Creating large-scale system for performance testing")
 | |
| 
 | |
| 	// Create 100 contexts representing a complex microservices architecture
 | |
| 	numServices := 100
 | |
| 	addresses := make([]ucxl.Address, numServices)
 | |
| 
 | |
| 	// Create services in batches to simulate realistic growth
 | |
| 	batchSize := 10
 | |
| 	for batch := 0; batch < numServices/batchSize; batch++ {
 | |
| 		start := batch * batchSize
 | |
| 		end := start + batchSize
 | |
| 
 | |
| 		for i := start; i < end; i++ {
 | |
| 			addresses[i] = createTestAddress(fmt.Sprintf("services/service-%03d", i))
 | |
| 
 | |
| 			context := &slurpContext.ContextNode{
 | |
| 				Path:          fmt.Sprintf("services/service-%03d", i),
 | |
| 				UCXLAddress:   addresses[i],
 | |
| 				Summary:       fmt.Sprintf("Microservice %d in large-scale system", i),
 | |
| 				Purpose:       fmt.Sprintf("Handle business logic for domain %d", i%10),
 | |
| 				Technologies:  []string{"go", "grpc", "postgres"},
 | |
| 				Tags:          []string{"microservice", fmt.Sprintf("domain-%d", i%10)},
 | |
| 				Insights:      []string{"Auto-generated service"},
 | |
| 				GeneratedAt:   time.Now(),
 | |
| 				RAGConfidence: 0.7 + float64(i%3)*0.1,
 | |
| 			}
 | |
| 
 | |
| 			_, err := system.Graph.CreateInitialContext(ctx, addresses[i], context, "automation")
 | |
| 			if err != nil {
 | |
| 				t.Fatalf("Failed to create service %d: %v", i, err)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		t.Logf("Created batch %d (%d-%d)", batch+1, start, end-1)
 | |
| 	}
 | |
| 
 | |
| 	// Create realistic dependency patterns
 | |
| 	t.Log("Creating dependency relationships")
 | |
| 
 | |
| 	dependencyCount := 0
 | |
| 	for i := 0; i < numServices; i++ {
 | |
| 		// Each service depends on 2-5 other services
 | |
| 		numDeps := 2 + (i % 4)
 | |
| 		for j := 0; j < numDeps && dependencyCount < numServices*3; j++ {
 | |
| 			depIndex := (i + j + 1) % numServices
 | |
| 			if depIndex != i {
 | |
| 				err := system.Graph.AddInfluenceRelationship(ctx, addresses[i], addresses[depIndex])
 | |
| 				if err == nil {
 | |
| 					dependencyCount++
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Created %d dependency relationships", dependencyCount)
 | |
| 
 | |
| 	// Performance test: Large-scale evolution
 | |
| 	t.Log("Testing large-scale context evolution")
 | |
| 
 | |
| 	startTime := time.Now()
 | |
| 	evolutionCount := 0
 | |
| 
 | |
| 	for i := 0; i < 50; i++ { // Evolve 50 services
 | |
| 		service := i * 2 % numServices // Distribute evenly
 | |
| 
 | |
| 		updatedContext := &slurpContext.ContextNode{
 | |
| 			Path:          fmt.Sprintf("services/service-%03d", service),
 | |
| 			UCXLAddress:   addresses[service],
 | |
| 			Summary:       fmt.Sprintf("Updated microservice %d with new features", service),
 | |
| 			Purpose:       fmt.Sprintf("Enhanced business logic for domain %d", service%10),
 | |
| 			Technologies:  []string{"go", "grpc", "postgres", "redis"},
 | |
| 			Tags:          []string{"microservice", fmt.Sprintf("domain-%d", service%10), "updated"},
 | |
| 			Insights:      []string{"Auto-generated service", "Performance improvements added"},
 | |
| 			GeneratedAt:   time.Now(),
 | |
| 			RAGConfidence: 0.8,
 | |
| 		}
 | |
| 
 | |
| 		decision := &DecisionMetadata{
 | |
| 			ID:                   fmt.Sprintf("auto-update-%03d", service),
 | |
| 			Maker:                "automation",
 | |
| 			Rationale:            "Automated performance improvement",
 | |
| 			Scope:                ImpactModule,
 | |
| 			ConfidenceLevel:      0.8,
 | |
| 			CreatedAt:            time.Now(),
 | |
| 			ImplementationStatus: "completed",
 | |
| 		}
 | |
| 
 | |
| 		_, err := system.Graph.EvolveContext(ctx, addresses[service], updatedContext, ReasonPerformanceInsight, decision)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Failed to evolve service %d: %v", service, err)
 | |
| 		} else {
 | |
| 			evolutionCount++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	evolutionTime := time.Since(startTime)
 | |
| 	t.Logf("Evolved %d services in %v (%.2f ops/sec)",
 | |
| 		evolutionCount, evolutionTime, float64(evolutionCount)/evolutionTime.Seconds())
 | |
| 
 | |
| 	// Performance test: Large-scale analysis
 | |
| 	t.Log("Testing large-scale influence analysis")
 | |
| 
 | |
| 	analysisStart := time.Now()
 | |
| 	analysis, err := system.InfluenceAnalyzer.AnalyzeInfluenceNetwork(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to analyze large network: %v", err)
 | |
| 	}
 | |
| 	analysisTime := time.Since(analysisStart)
 | |
| 
 | |
| 	t.Logf("Analyzed network (%d nodes, %d edges) in %v",
 | |
| 		analysis.TotalNodes, analysis.TotalEdges, analysisTime)
 | |
| 
 | |
| 	// Performance test: Bulk queries
 | |
| 	t.Log("Testing bulk decision-hop queries")
 | |
| 
 | |
| 	queryStart := time.Now()
 | |
| 	queryCount := 0
 | |
| 
 | |
| 	for i := 0; i < 20; i++ { // Test 20 queries
 | |
| 		startService := i * 5 % numServices
 | |
| 
 | |
| 		hopQuery := &HopQuery{
 | |
| 			StartAddress: addresses[startService],
 | |
| 			MaxHops:      3,
 | |
| 			Direction:    "both",
 | |
| 			FilterCriteria: &HopFilter{
 | |
| 				MinConfidence: 0.6,
 | |
| 			},
 | |
| 			Limit: 50,
 | |
| 		}
 | |
| 
 | |
| 		_, err := system.QuerySystem.ExecuteHopQuery(ctx, hopQuery)
 | |
| 		if err != nil {
 | |
| 			t.Errorf("Failed to execute query %d: %v", i, err)
 | |
| 		} else {
 | |
| 			queryCount++
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	queryTime := time.Since(queryStart)
 | |
| 	t.Logf("Executed %d queries in %v (%.2f queries/sec)",
 | |
| 		queryCount, queryTime, float64(queryCount)/queryTime.Seconds())
 | |
| 
 | |
| 	// Memory usage check
 | |
| 	metrics, err := system.MetricsCollector.CollectTemporalMetrics(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to collect final metrics: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Logf("Final system state: %d nodes, %d decisions, %d connections",
 | |
| 		metrics.TotalNodes, metrics.TotalDecisions, metrics.InfluenceConnections)
 | |
| 
 | |
| 	// Verify system integrity under load
 | |
| 	err = system.Graph.ValidateTemporalIntegrity(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("System integrity compromised under load: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Log("Performance test completed successfully!")
 | |
| }
 | |
| 
 | |
| func TestTemporalGraphSystem_ErrorRecovery(t *testing.T) {
 | |
| 	system := createTestSystem(t)
 | |
| 	ctx := context.Background()
 | |
| 
 | |
| 	t.Log("Testing error recovery and resilience")
 | |
| 
 | |
| 	// Create some contexts
 | |
| 	addresses := make([]ucxl.Address, 5)
 | |
| 	for i := 0; i < 5; i++ {
 | |
| 		addresses[i] = createTestAddress(fmt.Sprintf("test/resilience-%d", i))
 | |
| 		context := createTestContext(fmt.Sprintf("test/resilience-%d", i), []string{"go"})
 | |
| 
 | |
| 		_, err := system.Graph.CreateInitialContext(ctx, addresses[i], context, "test")
 | |
| 		if err != nil {
 | |
| 			t.Fatalf("Failed to create context %d: %v", i, err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Test recovery from invalid operations
 | |
| 	t.Log("Testing recovery from invalid operations")
 | |
| 
 | |
| 	// Try to evolve non-existent context
 | |
| 	invalidAddr := createTestAddress("test/non-existent")
 | |
| 	invalidContext := createTestContext("test/non-existent", []string{"go"})
 | |
| 	invalidDecision := createTestDecision("invalid-001", "test", "Invalid", ImpactLocal)
 | |
| 
 | |
| 	_, err := system.Graph.EvolveContext(ctx, invalidAddr, invalidContext, ReasonCodeChange, invalidDecision)
 | |
| 	if err == nil {
 | |
| 		t.Error("Expected error when evolving non-existent context")
 | |
| 	}
 | |
| 
 | |
| 	// Try to add influence to non-existent context
 | |
| 	err = system.Graph.AddInfluenceRelationship(ctx, addresses[0], invalidAddr)
 | |
| 	if err == nil {
 | |
| 		t.Error("Expected error when adding influence to non-existent context")
 | |
| 	}
 | |
| 
 | |
| 	// System should still be functional after errors
 | |
| 	_, err = system.Graph.GetLatestVersion(ctx, addresses[0])
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("System became non-functional after errors: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	// Test integrity validation detects and reports issues
 | |
| 	t.Log("Testing integrity validation")
 | |
| 
 | |
| 	err = system.Graph.ValidateTemporalIntegrity(ctx)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Integrity validation failed: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Log("Error recovery test completed successfully!")
 | |
| }
 | |
| 
 | |
| // Helper function to create a complete test system
 | |
| func createTestSystem(t *testing.T) *TemporalGraphSystem {
 | |
| 	// Create mock storage layers
 | |
| 	contextStore := newMockStorage()
 | |
| 	localStorage := &mockLocalStorage{}
 | |
| 	distributedStorage := &mockDistributedStorage{}
 | |
| 	encryptedStorage := &mockEncryptedStorage{}
 | |
| 	backupManager := &mockBackupManager{}
 | |
| 
 | |
| 	// Create factory with test configuration
 | |
| 	config := DefaultTemporalConfig()
 | |
| 	config.EnableDebugLogging = true
 | |
| 	config.EnableValidation = true
 | |
| 
 | |
| 	factory := NewTemporalGraphFactory(contextStore, config)
 | |
| 
 | |
| 	// Create complete system
 | |
| 	system, err := factory.CreateTemporalGraphSystem(
 | |
| 		localStorage,
 | |
| 		distributedStorage,
 | |
| 		encryptedStorage,
 | |
| 		backupManager,
 | |
| 	)
 | |
| 	if err != nil {
 | |
| 		t.Fatalf("Failed to create temporal graph system: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	return system
 | |
| }
 | |
| 
 | |
| // Mock implementations for testing
 | |
| 
 | |
| type mockLocalStorage struct {
 | |
| 	data map[string]interface{}
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) Store(ctx context.Context, key string, data interface{}, options *storage.StoreOptions) error {
 | |
| 	if m.data == nil {
 | |
| 		m.data = make(map[string]interface{})
 | |
| 	}
 | |
| 	m.data[key] = data
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) Retrieve(ctx context.Context, key string) (interface{}, error) {
 | |
| 	if m.data == nil {
 | |
| 		return nil, storage.ErrNotFound
 | |
| 	}
 | |
| 	if data, exists := m.data[key]; exists {
 | |
| 		return data, nil
 | |
| 	}
 | |
| 	return nil, storage.ErrNotFound
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) Delete(ctx context.Context, key string) error {
 | |
| 	if m.data != nil {
 | |
| 		delete(m.data, key)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) Exists(ctx context.Context, key string) (bool, error) {
 | |
| 	if m.data == nil {
 | |
| 		return false, nil
 | |
| 	}
 | |
| 	_, exists := m.data[key]
 | |
| 	return exists, nil
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) List(ctx context.Context, pattern string) ([]string, error) {
 | |
| 	keys := make([]string, 0)
 | |
| 	if m.data != nil {
 | |
| 		for key := range m.data {
 | |
| 			keys = append(keys, key)
 | |
| 		}
 | |
| 	}
 | |
| 	return keys, nil
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) Size(ctx context.Context, key string) (int64, error) {
 | |
| 	return 0, nil
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) Compact(ctx context.Context) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockLocalStorage) GetLocalStats() (*storage.LocalStorageStats, error) {
 | |
| 	return &storage.LocalStorageStats{}, nil
 | |
| }
 | |
| 
 | |
| type mockDistributedStorage struct {
 | |
| 	data map[string]interface{}
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) Store(ctx context.Context, key string, data interface{}, options *storage.DistributedStoreOptions) error {
 | |
| 	if m.data == nil {
 | |
| 		m.data = make(map[string]interface{})
 | |
| 	}
 | |
| 	m.data[key] = data
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) Retrieve(ctx context.Context, key string) (interface{}, error) {
 | |
| 	if m.data == nil {
 | |
| 		return nil, storage.ErrNotFound
 | |
| 	}
 | |
| 	if data, exists := m.data[key]; exists {
 | |
| 		return data, nil
 | |
| 	}
 | |
| 	return nil, storage.ErrNotFound
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) Delete(ctx context.Context, key string) error {
 | |
| 	if m.data != nil {
 | |
| 		delete(m.data, key)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) Exists(ctx context.Context, key string) (bool, error) {
 | |
| 	if m.data == nil {
 | |
| 		return false, nil
 | |
| 	}
 | |
| 	_, exists := m.data[key]
 | |
| 	return exists, nil
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) Replicate(ctx context.Context, key string, replicationFactor int) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) FindReplicas(ctx context.Context, key string) ([]string, error) {
 | |
| 	return []string{}, nil
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) Sync(ctx context.Context) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockDistributedStorage) GetDistributedStats() (*storage.DistributedStorageStats, error) {
 | |
| 	return &storage.DistributedStorageStats{}, nil
 | |
| }
 | |
| 
 | |
| type mockEncryptedStorage struct{}
 | |
| 
 | |
| func (m *mockEncryptedStorage) StoreEncrypted(ctx context.Context, key string, data interface{}, roles []string) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) RetrieveDecrypted(ctx context.Context, key string, role string) (interface{}, error) {
 | |
| 	return nil, storage.ErrNotFound
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) CanAccess(ctx context.Context, key string, role string) (bool, error) {
 | |
| 	return true, nil
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) ListAccessibleKeys(ctx context.Context, role string) ([]string, error) {
 | |
| 	return []string{}, nil
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) ReEncryptForRoles(ctx context.Context, key string, newRoles []string) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) GetAccessRoles(ctx context.Context, key string) ([]string, error) {
 | |
| 	return []string{}, nil
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) RotateKeys(ctx context.Context, maxAge time.Duration) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockEncryptedStorage) ValidateEncryption(ctx context.Context, key string) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type mockBackupManager struct{}
 | |
| 
 | |
| func (m *mockBackupManager) CreateBackup(ctx context.Context, config *storage.BackupConfig) (*storage.BackupInfo, error) {
 | |
| 	return &storage.BackupInfo{
 | |
| 		ID:        "test-backup-1",
 | |
| 		CreatedAt: time.Now(),
 | |
| 		Size:      1024,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func (m *mockBackupManager) RestoreBackup(ctx context.Context, backupID string, config *storage.RestoreConfig) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockBackupManager) ListBackups(ctx context.Context) ([]*storage.BackupInfo, error) {
 | |
| 	return []*storage.BackupInfo{}, nil
 | |
| }
 | |
| 
 | |
| func (m *mockBackupManager) DeleteBackup(ctx context.Context, backupID string) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockBackupManager) ValidateBackup(ctx context.Context, backupID string) (*storage.BackupValidation, error) {
 | |
| 	return &storage.BackupValidation{
 | |
| 		Valid: true,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func (m *mockBackupManager) ScheduleBackup(ctx context.Context, schedule *storage.BackupSchedule) error {
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *mockBackupManager) GetBackupStats(ctx context.Context) (*storage.BackupStatistics, error) {
 | |
| 	return &storage.BackupStatistics{}, nil
 | |
| }
 | 
