Files
2026-09-14 09:28:11 +01:00

86 lines
2.7 KiB
Go

package lifecycle
import (
"context"
"testing"
"testing/synctest"
"time"
"github.com/stretchr/testify/require"
agentctl "github.com/kandev/kandev/internal/agent/runtime/agentctl"
"github.com/kandev/kandev/internal/agentctl/types/streams"
"github.com/kandev/kandev/internal/common/constants"
)
func TestCoalescedExecutionContextDoesNotConsumeLaunchBudgetDuringPreparation(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
manager := &Manager{stopCh: make(chan struct{})}
sharedCtx, cancel := manager.coalescedExecutionContext(context.Background())
defer cancel()
if _, ok := sharedCtx.Deadline(); ok {
t.Fatal("coalesced execution context must not have a launch deadline")
}
// Simulate environment creation before the runtime launch phase begins.
<-time.After(constants.SetupScriptTimeout)
launchCtx, launchCancel := withLaunchPhaseTimeout(sharedCtx)
defer launchCancel()
deadline, ok := launchCtx.Deadline()
if !ok {
t.Fatal("launch phase context must have a deadline")
}
if got := time.Until(deadline); got != constants.AgentLaunchTimeout {
t.Fatalf("launch phase budget = %s, want %s", got, constants.AgentLaunchTimeout)
}
})
}
func TestPreparationContextRetainsItsIndependentBudget(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
base := context.Background()
launchCtx, launchCancel := withLaunchPhaseTimeout(base)
defer launchCancel()
prepareParent := preparationContext(launchCtx)
if _, ok := prepareParent.Deadline(); ok {
t.Fatal("preparation parent must not inherit the launch deadline")
}
prepareCtx, prepareCancel := context.WithTimeout(prepareParent, constants.SetupScriptTimeout)
defer prepareCancel()
deadline, ok := prepareCtx.Deadline()
if !ok {
t.Fatal("preparation context must have a deadline")
}
if got := time.Until(deadline); got != constants.SetupScriptTimeout {
t.Fatalf("preparation budget = %s, want %s", got, constants.SetupScriptTimeout)
}
})
}
func TestFinishContextResetReturnsEventsBufferedDuringFinalization(t *testing.T) {
execution := &AgentExecution{}
require.NoError(t, execution.beginContextReset())
buffered := agentctl.AgentEvent{
Type: streams.EventTypeSessionModels,
SessionID: "new-session",
}
stale := agentctl.AgentEvent{
Type: streams.EventTypeSessionStatus,
SessionID: "old-session",
}
require.True(t, execution.bufferOrDropContextResetEvent(buffered))
require.True(t, execution.bufferOrDropContextResetEvent(stale))
final := execution.finishContextReset("new-session")
require.Equal(t, []agentctl.AgentEvent{buffered}, final)
require.False(t, execution.bufferOrDropContextResetEvent(agentctl.AgentEvent{
Type: streams.EventTypeSessionStatus,
SessionID: "new-session",
}))
}