Files
kandev/apps/backend/internal/backendapp/adapters_test.go
T
2026-06-23 17:28:52 +01:00

135 lines
3.9 KiB
Go

package backendapp
import (
"context"
"errors"
"fmt"
"sync"
"testing"
"github.com/kandev/kandev/internal/common/logger"
githubsvc "github.com/kandev/kandev/internal/github"
taskrepo "github.com/kandev/kandev/internal/task/repository/sqlite"
taskservice "github.com/kandev/kandev/internal/task/service"
)
func newTestLogger() *logger.Logger {
log, _ := logger.NewLogger(logger.LoggingConfig{
Level: "error",
Format: "json",
})
return log
}
func TestGetSessionModel_Caching(t *testing.T) {
// We can't easily instantiate a full taskservice.Service here without a DB,
// so we test the caching mechanism directly on the adapter struct.
adapter := &messageCreatorAdapter{
svc: nil, // Will cause getSessionModel to return "" on cache miss (nil svc panics)
logger: newTestLogger(),
}
// Pre-populate the cache to avoid calling the nil svc
adapter.sessionModelMu.Lock()
adapter.sessionModelCache = map[string]string{
"session-1": "claude-sonnet-4",
"session-2": "gpt-4",
}
adapter.sessionModelMu.Unlock()
// Test cache hit
model := adapter.getSessionModel(context.Background(), "session-1")
if model != "claude-sonnet-4" {
t.Errorf("expected 'claude-sonnet-4', got %q", model)
}
model = adapter.getSessionModel(context.Background(), "session-2")
if model != "gpt-4" {
t.Errorf("expected 'gpt-4', got %q", model)
}
// Test cache miss for unknown session returns ""
// (svc is nil, so DB lookup would fail gracefully)
// We need a non-nil svc to avoid panic - use a minimal mock approach
// Instead, verify the cache was populated for existing entries
adapter.sessionModelMu.RLock()
if len(adapter.sessionModelCache) != 2 {
t.Errorf("expected 2 cached entries, got %d", len(adapter.sessionModelCache))
}
adapter.sessionModelMu.RUnlock()
}
func TestGetSessionModel_ConcurrentAccess(t *testing.T) {
adapter := &messageCreatorAdapter{
svc: nil,
logger: newTestLogger(),
}
// Pre-populate cache
adapter.sessionModelMu.Lock()
adapter.sessionModelCache = map[string]string{
"session-1": "claude-sonnet-4",
}
adapter.sessionModelMu.Unlock()
// Concurrent reads should not race
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
model := adapter.getSessionModel(context.Background(), "session-1")
if model != "claude-sonnet-4" {
t.Errorf("expected 'claude-sonnet-4', got %q", model)
}
}()
}
wg.Wait()
}
func TestGetSessionModel_LazyInit(t *testing.T) {
// Verify that the cache map is lazily initialized (nil initially)
adapter := &messageCreatorAdapter{
svc: nil,
logger: newTestLogger(),
}
// sessionModelCache should be nil initially
adapter.sessionModelMu.RLock()
if adapter.sessionModelCache != nil {
t.Error("expected sessionModelCache to be nil initially")
}
adapter.sessionModelMu.RUnlock()
}
// Verify the adapter compiles with the taskservice.Service field
func TestMessageCreatorAdapter_StructFields(t *testing.T) {
adapter := &messageCreatorAdapter{
svc: (*taskservice.Service)(nil),
logger: newTestLogger(),
}
if adapter.svc != nil {
t.Error("expected nil svc")
}
}
func TestWrapGitHubTaskIssueStoreError(t *testing.T) {
taskErr := fmt.Errorf("load task: %w", taskrepo.ErrTaskNotFound)
wrapped := wrapGitHubTaskIssueStoreError(taskErr)
if !errors.Is(wrapped, githubsvc.ErrTaskNotFound) {
t.Fatalf("wrapped error should match github ErrTaskNotFound: %v", wrapped)
}
if !errors.Is(wrapped, taskrepo.ErrTaskNotFound) {
t.Fatalf("wrapped error should preserve task repo ErrTaskNotFound: %v", wrapped)
}
otherErr := errors.New("database unavailable")
if got := wrapGitHubTaskIssueStoreError(otherErr); got != otherErr {
t.Fatalf("non-not-found error changed: got %v, want %v", got, otherErr)
}
}
// jiraSecretAdapter Set/Exists branching is tested in
// internal/integrations/secretadapter/secretadapter_test.go now that the
// upsert helper lives there.