63 lines
2.2 KiB
Go
63 lines
2.2 KiB
Go
package orchestrator
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kandev/kandev/internal/agent/runtime/lifecycle"
|
|
)
|
|
|
|
// TestErrorsAreClassifiable verifies that the orchestrator's error
|
|
// classification helpers rely exclusively on errors.Is + wrapped sentinels,
|
|
// not substring matches on the formatted message. A library upgrade that
|
|
// changes wording must not silently break these checks.
|
|
func TestErrorsAreClassifiable(t *testing.T) {
|
|
t.Run("isAgentPromptInProgressError requires the sentinel", func(t *testing.T) {
|
|
if !isAgentPromptInProgressError(ErrAgentPromptInProgress) {
|
|
t.Errorf("exact sentinel must classify")
|
|
}
|
|
if !isAgentPromptInProgressError(fmt.Errorf("wrap: %w", ErrAgentPromptInProgress)) {
|
|
t.Errorf("wrapped sentinel must classify")
|
|
}
|
|
if isAgentPromptInProgressError(errors.New("agent is currently processing a prompt")) {
|
|
t.Errorf("untyped lookalike must no longer classify")
|
|
}
|
|
})
|
|
|
|
t.Run("isSessionResetInProgressError requires the sentinel", func(t *testing.T) {
|
|
if !isSessionResetInProgressError(ErrSessionResetInProgress) {
|
|
t.Errorf("exact sentinel must classify")
|
|
}
|
|
if !isSessionResetInProgressError(fmt.Errorf("wrap: %w", ErrSessionResetInProgress)) {
|
|
t.Errorf("wrapped sentinel must classify")
|
|
}
|
|
if isSessionResetInProgressError(errors.New("session reset in progress")) {
|
|
t.Errorf("untyped lookalike must no longer classify")
|
|
}
|
|
})
|
|
|
|
t.Run("isAgentAlreadyRunningError uses lifecycle.ErrAgentAlreadyRunning", func(t *testing.T) {
|
|
if !isAgentAlreadyRunningError(lifecycle.ErrAgentAlreadyRunning) {
|
|
t.Errorf("exact sentinel must classify")
|
|
}
|
|
if !isAgentAlreadyRunningError(fmt.Errorf("LaunchAgent: %w", lifecycle.ErrAgentAlreadyRunning)) {
|
|
t.Errorf("wrapped sentinel must classify")
|
|
}
|
|
if isAgentAlreadyRunningError(errors.New("session already has an agent running somewhere")) {
|
|
t.Errorf("untyped lookalike must no longer classify")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestIsTransientPromptError_PendingCompletionTimeout(t *testing.T) {
|
|
err := fmt.Errorf("prompt admission: %w", &lifecycle.PendingDispatchedPromptTimeoutError{
|
|
ExecutionID: "execution-1",
|
|
Timeout: time.Second,
|
|
})
|
|
if !isTransientPromptError(err) {
|
|
t.Fatal("pending dispatched prompt timeout must be transient")
|
|
}
|
|
}
|