package database import ( "context" "fmt" "testing" "time" ) func BenchmarkCreateOptions(b *testing.B) { store, err := NewSQLiteStore(":memory:") if err != nil { b.Fatalf("Failed to create store: %v", err) } defer store.Close() //nolint:errcheck // benchmark cleanup ctx := context.Background() if err := store.Initialize(ctx); err != nil { b.Fatalf("Failed to initialize: %v", err) } rev := &Revision{GitHash: "bench123", ChannelName: "bench"} if err := store.CreateRevision(ctx, rev); err != nil { b.Fatalf("Failed to create revision: %v", err) } b.ResetTimer() for i := 0; i < b.N; i++ { opt := &Option{ RevisionID: rev.ID, Name: fmt.Sprintf("services.test%d.enable", i), ParentPath: fmt.Sprintf("services.test%d", i), Type: "boolean", DefaultValue: "false", Description: "Test option", } if err := store.CreateOption(ctx, opt); err != nil { b.Fatalf("Failed to create option: %v", err) } } } func BenchmarkCreateOptionsBatch(b *testing.B) { benchmarkBatch(b, 100) } func BenchmarkCreateOptionsBatch1000(b *testing.B) { benchmarkBatch(b, 1000) } func benchmarkBatch(b *testing.B, batchSize int) { store, err := NewSQLiteStore(":memory:") if err != nil { b.Fatalf("Failed to create store: %v", err) } defer store.Close() //nolint:errcheck // benchmark cleanup ctx := context.Background() if err := store.Initialize(ctx); err != nil { b.Fatalf("Failed to initialize: %v", err) } rev := &Revision{GitHash: "batchbench", ChannelName: "bench"} if err := store.CreateRevision(ctx, rev); err != nil { b.Fatalf("Failed to create revision: %v", err) } opts := make([]*Option, batchSize) for i := 0; i < batchSize; i++ { opts[i] = &Option{ RevisionID: rev.ID, Name: fmt.Sprintf("services.batch%d.enable", i), ParentPath: fmt.Sprintf("services.batch%d", i), Type: "boolean", DefaultValue: "false", Description: "Batch test option", } } b.ResetTimer() for i := 0; i < b.N; i++ { // Reset IDs for next iteration for _, opt := range opts { opt.ID = 0 } if err := store.CreateOptionsBatch(ctx, opts); err != nil { b.Fatalf("Failed to create batch: %v", err) } // Clean up for next iteration _ = store.DeleteRevision(ctx, rev.ID) //nolint:errcheck // benchmark cleanup rev = &Revision{GitHash: fmt.Sprintf("batchbench%d", i), ChannelName: "bench"} _ = store.CreateRevision(ctx, rev) //nolint:errcheck // benchmark setup for _, opt := range opts { opt.RevisionID = rev.ID } } } func BenchmarkSearchOptions(b *testing.B) { store, err := NewSQLiteStore(":memory:") if err != nil { b.Fatalf("Failed to create store: %v", err) } defer store.Close() //nolint:errcheck // benchmark cleanup ctx := context.Background() if err := store.Initialize(ctx); err != nil { b.Fatalf("Failed to initialize: %v", err) } rev := &Revision{GitHash: "searchbench", ChannelName: "bench"} if err := store.CreateRevision(ctx, rev); err != nil { b.Fatalf("Failed to create revision: %v", err) } // Create 1000 options to search through opts := make([]*Option, 1000) for i := 0; i < 1000; i++ { opts[i] = &Option{ RevisionID: rev.ID, Name: fmt.Sprintf("services.service%d.enable", i), ParentPath: fmt.Sprintf("services.service%d", i), Type: "boolean", DefaultValue: "false", Description: fmt.Sprintf("Enable service %d for testing purposes", i), } } if err := store.CreateOptionsBatch(ctx, opts); err != nil { b.Fatalf("Failed to create options: %v", err) } b.ResetTimer() for i := 0; i < b.N; i++ { _, err := store.SearchOptions(ctx, rev.ID, "enable service", SearchFilters{Limit: 50}) if err != nil { b.Fatalf("Search failed: %v", err) } } } func BenchmarkGetChildren(b *testing.B) { store, err := NewSQLiteStore(":memory:") if err != nil { b.Fatalf("Failed to create store: %v", err) } defer store.Close() //nolint:errcheck // benchmark cleanup ctx := context.Background() if err := store.Initialize(ctx); err != nil { b.Fatalf("Failed to initialize: %v", err) } rev := &Revision{GitHash: "childrenbench", ChannelName: "bench"} if err := store.CreateRevision(ctx, rev); err != nil { b.Fatalf("Failed to create revision: %v", err) } // Create parent and 100 children opts := make([]*Option, 101) opts[0] = &Option{ RevisionID: rev.ID, Name: "services", ParentPath: "", Type: "attrsOf", } for i := 1; i <= 100; i++ { opts[i] = &Option{ RevisionID: rev.ID, Name: fmt.Sprintf("services.service%d", i), ParentPath: "services", Type: "submodule", } } if err := store.CreateOptionsBatch(ctx, opts); err != nil { b.Fatalf("Failed to create options: %v", err) } b.ResetTimer() for i := 0; i < b.N; i++ { _, err := store.GetChildren(ctx, rev.ID, "services") if err != nil { b.Fatalf("GetChildren failed: %v", err) } } } func BenchmarkSchemaInitialize(b *testing.B) { for i := 0; i < b.N; i++ { store, err := NewSQLiteStore(":memory:") if err != nil { b.Fatalf("Failed to create store: %v", err) } ctx := context.Background() if err := store.Initialize(ctx); err != nil { b.Fatalf("Failed to initialize: %v", err) } store.Close() //nolint:errcheck // benchmark cleanup } } // BenchmarkRevisionCRUD benchmarks the full CRUD cycle for revisions. func BenchmarkRevisionCRUD(b *testing.B) { store, err := NewSQLiteStore(":memory:") if err != nil { b.Fatalf("Failed to create store: %v", err) } defer store.Close() //nolint:errcheck // benchmark cleanup ctx := context.Background() if err := store.Initialize(ctx); err != nil { b.Fatalf("Failed to initialize: %v", err) } b.ResetTimer() for i := 0; i < b.N; i++ { rev := &Revision{ GitHash: fmt.Sprintf("crud%d", i), ChannelName: "test", CommitDate: time.Now(), } // Create if err := store.CreateRevision(ctx, rev); err != nil { b.Fatalf("Create failed: %v", err) } // Read _, err := store.GetRevision(ctx, rev.GitHash) if err != nil { b.Fatalf("Get failed: %v", err) } // Update if err := store.UpdateRevisionOptionCount(ctx, rev.ID, 100); err != nil { b.Fatalf("Update failed: %v", err) } // Delete if err := store.DeleteRevision(ctx, rev.ID); err != nil { b.Fatalf("Delete failed: %v", err) } } }