mirror of
https://github.com/lukaszraczylo/claude-mnemonic.git
synced 2026-06-24 04:01:08 +00:00
Further improvements to the coverage.
This commit is contained in:
@@ -0,0 +1,615 @@
|
||||
// Package session provides session lifecycle management for claude-mnemonic.
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lukaszraczylo/claude-mnemonic/internal/db/sqlite"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
// Import sqlite driver
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
// hasFTS5 checks if FTS5 is available in the SQLite build.
|
||||
func hasFTS5(t *testing.T) bool {
|
||||
t.Helper()
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "fts5-check-*")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||
|
||||
store, err := sqlite.NewStore(sqlite.StoreConfig{
|
||||
Path: tmpDir + "/check.db",
|
||||
MaxConns: 1,
|
||||
WALMode: true,
|
||||
})
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_ = store.Close()
|
||||
return true
|
||||
}
|
||||
|
||||
// testStore creates a sqlite.Store with a temporary database for testing.
|
||||
func testStore(t *testing.T) (*sqlite.Store, func()) {
|
||||
t.Helper()
|
||||
|
||||
if !hasFTS5(t) {
|
||||
t.Skip("FTS5 not available in this SQLite build")
|
||||
}
|
||||
|
||||
tmpDir, err := os.MkdirTemp("", "session-integration-test-*")
|
||||
require.NoError(t, err)
|
||||
|
||||
dbPath := tmpDir + "/test.db"
|
||||
|
||||
store, err := sqlite.NewStore(sqlite.StoreConfig{
|
||||
Path: dbPath,
|
||||
MaxConns: 1,
|
||||
WALMode: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
cleanup := func() {
|
||||
_ = store.Close()
|
||||
_ = os.RemoveAll(tmpDir)
|
||||
}
|
||||
|
||||
return store, cleanup
|
||||
}
|
||||
|
||||
// SessionIntegrationSuite tests session manager with real SQLite stores.
|
||||
type SessionIntegrationSuite struct {
|
||||
suite.Suite
|
||||
store *sqlite.Store
|
||||
sessionStore *sqlite.SessionStore
|
||||
cleanup func()
|
||||
manager *Manager
|
||||
}
|
||||
|
||||
func (s *SessionIntegrationSuite) SetupTest() {
|
||||
if !hasFTS5(s.T()) {
|
||||
s.T().Skip("FTS5 not available in this SQLite build")
|
||||
}
|
||||
|
||||
s.store, s.cleanup = testStore(s.T())
|
||||
s.sessionStore = sqlite.NewSessionStore(s.store)
|
||||
s.manager = NewManager(s.sessionStore)
|
||||
}
|
||||
|
||||
func (s *SessionIntegrationSuite) TearDownTest() {
|
||||
if s.manager != nil {
|
||||
s.manager.ShutdownAll(context.Background())
|
||||
}
|
||||
if s.cleanup != nil {
|
||||
s.cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionIntegrationSuite(t *testing.T) {
|
||||
suite.Run(t, new(SessionIntegrationSuite))
|
||||
}
|
||||
|
||||
// TestNewManager_WithRealStore tests manager creation with real store.
|
||||
func (s *SessionIntegrationSuite) TestNewManager_WithRealStore() {
|
||||
s.NotNil(s.manager)
|
||||
s.NotNil(s.manager.sessionStore)
|
||||
s.NotNil(s.manager.sessions)
|
||||
s.NotNil(s.manager.ProcessNotify)
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestInitializeSession_WithRealStore tests session initialization.
|
||||
func (s *SessionIntegrationSuite) TestInitializeSession_WithRealStore() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a session in the database first
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-test-123", "test-project", "initial prompt")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Greater(sessionID, int64(0))
|
||||
|
||||
// Initialize in manager
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "user prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(session)
|
||||
|
||||
// Verify session properties
|
||||
s.Equal(sessionID, session.SessionDBID)
|
||||
s.Equal("claude-test-123", session.ClaudeSessionID)
|
||||
s.Equal("test-project", session.Project)
|
||||
s.Equal("user prompt", session.UserPrompt)
|
||||
s.Equal(1, session.LastPromptNumber)
|
||||
|
||||
// Verify manager state
|
||||
s.Equal(1, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestInitializeSession_ReuseExisting tests that existing sessions are reused.
|
||||
func (s *SessionIntegrationSuite) TestInitializeSession_ReuseExisting() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create session in database
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-reuse-123", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Initialize first time
|
||||
session1, err := s.manager.InitializeSession(ctx, sessionID, "prompt 1", 1)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(session1)
|
||||
|
||||
// Initialize second time - should reuse
|
||||
session2, err := s.manager.InitializeSession(ctx, sessionID, "prompt 2", 2)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(session2)
|
||||
|
||||
// Should be the same session pointer
|
||||
s.Same(session1, session2)
|
||||
|
||||
// Should have updated user prompt
|
||||
s.Equal("prompt 2", session2.UserPrompt)
|
||||
s.Equal(2, session2.LastPromptNumber)
|
||||
|
||||
// Still only 1 active session
|
||||
s.Equal(1, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestInitializeSession_NonExistentSession tests initializing non-existent session.
|
||||
func (s *SessionIntegrationSuite) TestInitializeSession_NonExistentSession() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Try to initialize non-existent session
|
||||
session, err := s.manager.InitializeSession(ctx, 999999, "prompt", 1)
|
||||
s.NoError(err) // No error, just nil session
|
||||
s.Nil(session)
|
||||
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestInitializeSession_EmptyUserPrompt tests initialization with empty user prompt.
|
||||
func (s *SessionIntegrationSuite) TestInitializeSession_EmptyUserPrompt() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create session with initial prompt in database
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-empty-prompt", "test-project", "db prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Initialize with empty user prompt - should use database prompt
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "", 0)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(session)
|
||||
|
||||
// Should use database prompt
|
||||
s.Equal("db prompt", session.UserPrompt)
|
||||
}
|
||||
|
||||
// TestQueueObservation_WithRealStore tests observation queuing.
|
||||
func (s *SessionIntegrationSuite) TestQueueObservation_WithRealStore() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-queue-obs", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Queue an observation
|
||||
err = s.manager.QueueObservation(ctx, sessionID, ObservationData{
|
||||
ToolName: "Read",
|
||||
ToolInput: map[string]string{"path": "/test.go"},
|
||||
ToolResponse: "file content",
|
||||
PromptNumber: 1,
|
||||
CWD: "/project",
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Check queue depth
|
||||
s.Equal(1, s.manager.GetTotalQueueDepth())
|
||||
s.True(s.manager.IsAnySessionProcessing())
|
||||
|
||||
// Drain messages
|
||||
messages := s.manager.DrainMessages(sessionID)
|
||||
s.Len(messages, 1)
|
||||
s.Equal(MessageTypeObservation, messages[0].Type)
|
||||
s.Equal("Read", messages[0].Observation.ToolName)
|
||||
}
|
||||
|
||||
// TestQueueObservation_AutoInitialize tests auto-initialization on queue.
|
||||
func (s *SessionIntegrationSuite) TestQueueObservation_AutoInitialize() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create session in database but don't initialize in manager
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-auto-init", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Queue observation without explicit initialization
|
||||
err = s.manager.QueueObservation(ctx, sessionID, ObservationData{
|
||||
ToolName: "Write",
|
||||
ToolInput: "test input",
|
||||
ToolResponse: "success",
|
||||
PromptNumber: 1,
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Session should be auto-initialized
|
||||
s.Equal(1, s.manager.GetActiveSessionCount())
|
||||
s.Equal(1, s.manager.GetTotalQueueDepth())
|
||||
}
|
||||
|
||||
// TestQueueObservation_NonExistentSession tests queuing to non-existent session.
|
||||
func (s *SessionIntegrationSuite) TestQueueObservation_NonExistentSession() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Try to queue to non-existent session
|
||||
err := s.manager.QueueObservation(ctx, 999999, ObservationData{
|
||||
ToolName: "Test",
|
||||
})
|
||||
|
||||
// Should not error, but session won't be created
|
||||
s.NoError(err)
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestQueueSummarize_WithRealStore tests summarize queuing.
|
||||
func (s *SessionIntegrationSuite) TestQueueSummarize_WithRealStore() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-queue-sum", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Queue a summarize request
|
||||
err = s.manager.QueueSummarize(ctx, sessionID, "What did you do?", "I completed the task.")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Check queue depth
|
||||
s.Equal(1, s.manager.GetTotalQueueDepth())
|
||||
s.True(s.manager.IsAnySessionProcessing())
|
||||
|
||||
// Drain messages
|
||||
messages := s.manager.DrainMessages(sessionID)
|
||||
s.Len(messages, 1)
|
||||
s.Equal(MessageTypeSummarize, messages[0].Type)
|
||||
s.Equal("What did you do?", messages[0].Summarize.LastUserMessage)
|
||||
s.Equal("I completed the task.", messages[0].Summarize.LastAssistantMessage)
|
||||
}
|
||||
|
||||
// TestQueueSummarize_AutoInitialize tests auto-initialization on summarize queue.
|
||||
func (s *SessionIntegrationSuite) TestQueueSummarize_AutoInitialize() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create session in database but don't initialize in manager
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-sum-auto", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Queue summarize without explicit initialization
|
||||
err = s.manager.QueueSummarize(ctx, sessionID, "user msg", "assistant msg")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Session should be auto-initialized
|
||||
s.Equal(1, s.manager.GetActiveSessionCount())
|
||||
s.Equal(1, s.manager.GetTotalQueueDepth())
|
||||
}
|
||||
|
||||
// TestQueueSummarize_NonExistentSession tests summarize queuing to non-existent session.
|
||||
func (s *SessionIntegrationSuite) TestQueueSummarize_NonExistentSession() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Try to queue to non-existent session
|
||||
err := s.manager.QueueSummarize(ctx, 999999, "user", "assistant")
|
||||
|
||||
// Should not error, but session won't be created
|
||||
s.NoError(err)
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestMixedQueueOperations tests mixed observation and summarize queuing.
|
||||
func (s *SessionIntegrationSuite) TestMixedQueueOperations() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-mixed", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Queue multiple messages of different types
|
||||
err = s.manager.QueueObservation(ctx, sessionID, ObservationData{ToolName: "Tool1"})
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.manager.QueueSummarize(ctx, sessionID, "user1", "assistant1")
|
||||
s.Require().NoError(err)
|
||||
|
||||
err = s.manager.QueueObservation(ctx, sessionID, ObservationData{ToolName: "Tool2"})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Check total queue depth
|
||||
s.Equal(3, s.manager.GetTotalQueueDepth())
|
||||
|
||||
// Drain and verify order
|
||||
messages := s.manager.DrainMessages(sessionID)
|
||||
s.Len(messages, 3)
|
||||
s.Equal(MessageTypeObservation, messages[0].Type)
|
||||
s.Equal("Tool1", messages[0].Observation.ToolName)
|
||||
s.Equal(MessageTypeSummarize, messages[1].Type)
|
||||
s.Equal(MessageTypeObservation, messages[2].Type)
|
||||
s.Equal("Tool2", messages[2].Observation.ToolName)
|
||||
}
|
||||
|
||||
// TestProcessNotifyChannel tests the process notification channel behavior.
|
||||
func (s *SessionIntegrationSuite) TestProcessNotifyChannel() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-notify", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Drain any existing notifications
|
||||
select {
|
||||
case <-s.manager.ProcessNotify:
|
||||
default:
|
||||
}
|
||||
|
||||
// Queue observation - should trigger notification
|
||||
err = s.manager.QueueObservation(ctx, sessionID, ObservationData{ToolName: "Test"})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Should be able to receive notification
|
||||
select {
|
||||
case <-s.manager.ProcessNotify:
|
||||
// Success
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
s.Fail("Should have received process notification")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSessionCallbacks tests session lifecycle callbacks.
|
||||
func (s *SessionIntegrationSuite) TestSessionCallbacks() {
|
||||
ctx := context.Background()
|
||||
|
||||
var createdID, deletedID int64
|
||||
|
||||
s.manager.SetOnSessionCreated(func(id int64) {
|
||||
createdID = id
|
||||
})
|
||||
s.manager.SetOnSessionDeleted(func(id int64) {
|
||||
deletedID = id
|
||||
})
|
||||
|
||||
// Create session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-callbacks", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Initialize - should trigger created callback
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Equal(sessionID, createdID)
|
||||
|
||||
// Delete - should trigger deleted callback
|
||||
s.manager.DeleteSession(sessionID)
|
||||
|
||||
s.Equal(sessionID, deletedID)
|
||||
}
|
||||
|
||||
// TestMultipleSessions tests managing multiple sessions.
|
||||
func (s *SessionIntegrationSuite) TestMultipleSessions() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create multiple sessions
|
||||
var sessionIDs []int64
|
||||
for i := 0; i < 5; i++ {
|
||||
id, err := s.sessionStore.CreateSDKSession(ctx, "claude-multi-"+string(rune('A'+i)), "project-"+string(rune('a'+i)), "prompt")
|
||||
s.Require().NoError(err)
|
||||
sessionIDs = append(sessionIDs, id)
|
||||
}
|
||||
|
||||
// Initialize all
|
||||
for _, id := range sessionIDs {
|
||||
_, err := s.manager.InitializeSession(ctx, id, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
s.Equal(5, s.manager.GetActiveSessionCount())
|
||||
|
||||
// Queue observations to each
|
||||
for i, id := range sessionIDs {
|
||||
err := s.manager.QueueObservation(ctx, id, ObservationData{
|
||||
ToolName: "Tool" + string(rune('A'+i)),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
s.Equal(5, s.manager.GetTotalQueueDepth())
|
||||
|
||||
// Get all sessions
|
||||
sessions := s.manager.GetAllSessions()
|
||||
s.Len(sessions, 5)
|
||||
|
||||
// Delete all
|
||||
for _, id := range sessionIDs {
|
||||
s.manager.DeleteSession(id)
|
||||
}
|
||||
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestCleanupStaleSessions tests the cleanup of stale sessions.
|
||||
func (s *SessionIntegrationSuite) TestCleanupStaleSessions() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize a session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-stale", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Manually set start time to past (simulate stale session)
|
||||
session.StartTime = time.Now().Add(-SessionTimeout - time.Minute)
|
||||
|
||||
// Run cleanup
|
||||
s.manager.cleanupStaleSessions()
|
||||
|
||||
// Session should be deleted
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestCleanupStaleSessions_WithPendingMessages tests cleanup doesn't delete sessions with pending messages.
|
||||
func (s *SessionIntegrationSuite) TestCleanupStaleSessions_WithPendingMessages() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize a session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-stale-pending", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Make session stale but add pending messages
|
||||
session.StartTime = time.Now().Add(-SessionTimeout - time.Minute)
|
||||
err = s.manager.QueueObservation(ctx, sessionID, ObservationData{ToolName: "Test"})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Run cleanup
|
||||
s.manager.cleanupStaleSessions()
|
||||
|
||||
// Session should NOT be deleted (has pending messages)
|
||||
s.Equal(1, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestCleanupStaleSessions_WithActiveGenerator tests cleanup doesn't delete sessions with active generator.
|
||||
func (s *SessionIntegrationSuite) TestCleanupStaleSessions_WithActiveGenerator() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize a session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-stale-gen", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Make session stale but mark generator as active
|
||||
session.StartTime = time.Now().Add(-SessionTimeout - time.Minute)
|
||||
session.generatorActive.Store(true)
|
||||
|
||||
// Run cleanup
|
||||
s.manager.cleanupStaleSessions()
|
||||
|
||||
// Session should NOT be deleted (generator is active)
|
||||
s.Equal(1, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestConcurrentQueueOperations tests thread-safe queue operations.
|
||||
func (s *SessionIntegrationSuite) TestConcurrentQueueOperations() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-concurrent", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Concurrent queue operations
|
||||
done := make(chan bool)
|
||||
numGoroutines := 50
|
||||
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
go func(idx int) {
|
||||
if idx%2 == 0 {
|
||||
_ = s.manager.QueueObservation(ctx, sessionID, ObservationData{
|
||||
ToolName: "Tool",
|
||||
})
|
||||
} else {
|
||||
_ = s.manager.QueueSummarize(ctx, sessionID, "user", "assistant")
|
||||
}
|
||||
done <- true
|
||||
}(i)
|
||||
}
|
||||
|
||||
// Wait for all goroutines
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
// All messages should be queued
|
||||
s.Equal(numGoroutines, s.manager.GetTotalQueueDepth())
|
||||
}
|
||||
|
||||
// TestShutdownAll_WithRealSessions tests shutdown of all real sessions.
|
||||
func (s *SessionIntegrationSuite) TestShutdownAll_WithRealSessions() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create and initialize multiple sessions
|
||||
for i := 0; i < 3; i++ {
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-shutdown-"+string(rune('A'+i)), "project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
s.Equal(3, s.manager.GetActiveSessionCount())
|
||||
|
||||
// Shutdown all
|
||||
s.manager.ShutdownAll(ctx)
|
||||
|
||||
// All sessions should be deleted
|
||||
s.Equal(0, s.manager.GetActiveSessionCount())
|
||||
}
|
||||
|
||||
// TestSessionSDKSessionID tests SDK session ID handling.
|
||||
func (s *SessionIntegrationSuite) TestSessionSDKSessionID() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create session - SDK session ID is generated
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-sdk-test", "test-project", "prompt")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Initialize in manager
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "prompt", 1)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(session)
|
||||
|
||||
// SDK session ID should be set
|
||||
s.NotEmpty(session.SDKSessionID)
|
||||
}
|
||||
|
||||
// TestPromptNumberTracking tests prompt number tracking across operations.
|
||||
func (s *SessionIntegrationSuite) TestPromptNumberTracking() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Create session
|
||||
sessionID, err := s.sessionStore.CreateSDKSession(ctx, "claude-prompt-num", "test-project", "initial")
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Initialize with prompt 1
|
||||
session, err := s.manager.InitializeSession(ctx, sessionID, "prompt 1", 1)
|
||||
s.Require().NoError(err)
|
||||
s.Equal(1, session.LastPromptNumber)
|
||||
|
||||
// Re-initialize with prompt 2
|
||||
session, err = s.manager.InitializeSession(ctx, sessionID, "prompt 2", 2)
|
||||
s.Require().NoError(err)
|
||||
s.Equal(2, session.LastPromptNumber)
|
||||
|
||||
// Re-initialize with prompt 5
|
||||
session, err = s.manager.InitializeSession(ctx, sessionID, "prompt 5", 5)
|
||||
s.Require().NoError(err)
|
||||
s.Equal(5, session.LastPromptNumber)
|
||||
}
|
||||
Reference in New Issue
Block a user