diff --git a/internal/config/unknownfields.go b/internal/config/unknownfields.go
index e5c36901d..7341a098a 100644
--- a/internal/config/unknownfields.go
+++ b/internal/config/unknownfields.go
@@ -131,7 +131,7 @@ type knownField struct {
}
func derefType(t reflect.Type) reflect.Type {
- for t != nil && t.Kind() == reflect.Ptr {
+ for t != nil && t.Kind() == reflect.Pointer {
t = t.Elem()
}
return t
diff --git a/internal/providers/anthropic/cache_breakpoints_test.go b/internal/providers/anthropic/cache_breakpoints_test.go
index 40f984233..adbf5f450 100644
--- a/internal/providers/anthropic/cache_breakpoints_test.go
+++ b/internal/providers/anthropic/cache_breakpoints_test.go
@@ -16,6 +16,7 @@ import (
// unmarked (Anthropic caps breakpoints at 4 per request: system, tools, and
// these two).
func TestAnthropicRequestMarksLastTwoMessagesForCaching(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -73,6 +74,7 @@ func TestAnthropicRequestMarksLastTwoMessagesForCaching(t *testing.T) {
// the breakpoint, and thinking blocks must never carry cache_control (the API
// rejects them) — the marker goes on the last cacheable block instead.
func TestApplyMessageCacheBreakpointsSkipsThinkingBlocks(t *testing.T) {
+ t.Parallel()
messages := []anthropicMessage{
{Role: "user", Content: "plain string"},
{Role: "assistant", Content: []map[string]any{
diff --git a/internal/providers/anthropic/dropped_test.go b/internal/providers/anthropic/dropped_test.go
index a5b25fb0b..3c1967e5c 100644
--- a/internal/providers/anthropic/dropped_test.go
+++ b/internal/providers/anthropic/dropped_test.go
@@ -13,6 +13,7 @@ import (
// can ask the model to retry, mirroring the OpenAI provider's behavior, instead
// of silently dropping it.
func TestStreamCompletionEmitsDroppedOnNamelessToolUseBlock(t *testing.T) {
+ t.Parallel()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_start", `{"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"","name":""}}`)
writeSSEEvent(w, "content_block_stop", `{"type":"content_block_stop","index":0}`)
@@ -45,6 +46,7 @@ func TestStreamCompletionEmitsDroppedOnNamelessToolUseBlock(t *testing.T) {
// A well-formed tool_use block must NOT emit a dropped signal.
func TestStreamCompletionDoesNotDropValidToolUseBlock(t *testing.T) {
+ t.Parallel()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_start", `{"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_1","name":"read_file"}}`)
writeSSEEvent(w, "content_block_stop", `{"type":"content_block_stop","index":0}`)
diff --git a/internal/providers/anthropic/finish_reason_test.go b/internal/providers/anthropic/finish_reason_test.go
index 757d9752b..a84f5eea3 100644
--- a/internal/providers/anthropic/finish_reason_test.go
+++ b/internal/providers/anthropic/finish_reason_test.go
@@ -11,6 +11,7 @@ import (
// truncated at the output cap. The provider must surface it on the done event so
// the agent does not treat a clipped answer as complete.
func TestStreamCompletionSurfacesMaxTokensStopReason(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "message_start", `{"type":"message_start","message":{"usage":{"input_tokens":5,"output_tokens":0}}}`)
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"cut"}}`)
@@ -37,6 +38,7 @@ func TestStreamCompletionSurfacesMaxTokensStopReason(t *testing.T) {
// A normal end_turn stop_reason must leave the done event's FinishReason empty.
func TestStreamCompletionNormalStopReasonHasNoFinishReason(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"ok"}}`)
writeSSEEvent(w, "message_delta", `{"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":2}}`)
diff --git a/internal/providers/anthropic/idle_test.go b/internal/providers/anthropic/idle_test.go
index c8c4c90cf..79b1e629d 100644
--- a/internal/providers/anthropic/idle_test.go
+++ b/internal/providers/anthropic/idle_test.go
@@ -15,6 +15,7 @@ import (
// message_stop or closing) must abort on the idle timeout instead of blocking
// the agent forever.
func TestStreamCompletionIdleTimeoutAbortsStalledStream(t *testing.T) {
+ t.Parallel()
released := make(chan struct{})
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"hi"}}`)
diff --git a/internal/providers/anthropic/image_test.go b/internal/providers/anthropic/image_test.go
index 4ecea2b10..96124f821 100644
--- a/internal/providers/anthropic/image_test.go
+++ b/internal/providers/anthropic/image_test.go
@@ -60,6 +60,7 @@ func firstUserContentBlocks(t *testing.T, body map[string]any) []any {
// TestUserTextOnlyTurnUnchanged pins the text-only wire shape: a single
// user message whose content is a one-element text-block array.
func TestUserTextOnlyTurnUnchanged(t *testing.T) {
+ t.Parallel()
body := captureRequestBody(t, zeroruntime.CompletionRequest{
Messages: []zeroruntime.Message{
{Role: zeroruntime.MessageRoleUser, Content: "Describe this."},
@@ -78,6 +79,7 @@ func TestUserTextOnlyTurnUnchanged(t *testing.T) {
// TestUserImagePlusTextTurn asserts a text block followed by one image
// source block carrying base64 of the RAW bytes.
func TestUserImagePlusTextTurn(t *testing.T) {
+ t.Parallel()
raw := []byte{0x89, 0x50, 0x4e, 0x47, 0x01, 0x02}
body := captureRequestBody(t, zeroruntime.CompletionRequest{
Messages: []zeroruntime.Message{
@@ -112,6 +114,7 @@ func TestUserImagePlusTextTurn(t *testing.T) {
// TestUserImageOnlyTurnEmits asserts an image-only user turn (empty Content)
// still produces a user message with a single image block.
func TestUserImageOnlyTurnEmits(t *testing.T) {
+ t.Parallel()
raw := []byte{0xff, 0xd8, 0xff, 0xe0}
body := captureRequestBody(t, zeroruntime.CompletionRequest{
Messages: []zeroruntime.Message{
diff --git a/internal/providers/anthropic/provider_test.go b/internal/providers/anthropic/provider_test.go
index d35d3ee41..48c1c3ddb 100644
--- a/internal/providers/anthropic/provider_test.go
+++ b/internal/providers/anthropic/provider_test.go
@@ -9,10 +9,16 @@ import (
"strings"
"testing"
+ "github.com/Gitlawb/zero/internal/providers/providerio"
"github.com/Gitlawb/zero/internal/zeroruntime"
)
+func init() {
+ providerio.ShrinkBackoffForTest()
+}
+
func TestStreamCompletionPostsMessagesRequest(t *testing.T) {
+ t.Parallel()
var gotPath string
var gotAPIKey string
var gotVersion string
@@ -123,6 +129,7 @@ func TestStreamCompletionPostsMessagesRequest(t *testing.T) {
}
func TestStreamCompletionAppliesCustomAuthAndHeaders(t *testing.T) {
+ t.Parallel()
var gotDefaultAuth string
var gotCustomAuth string
var gotTenant string
@@ -165,6 +172,7 @@ func TestStreamCompletionAppliesCustomAuthAndHeaders(t *testing.T) {
}
func TestStreamCompletionEmitsTextUsageAndDone(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "message_start", `{"type":"message_start","message":{"usage":{"input_tokens":25}}}`)
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}`)
@@ -186,6 +194,7 @@ func TestStreamCompletionEmitsTextUsageAndDone(t *testing.T) {
}
func TestStreamCompletionReportsCacheTokens(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "message_start", `{"type":"message_start","message":{"usage":{"input_tokens":10,"cache_read_input_tokens":200,"cache_creation_input_tokens":40}}}`)
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"hi"}}`)
@@ -217,6 +226,7 @@ func TestStreamCompletionReportsCacheTokens(t *testing.T) {
}
func TestStreamCompletionEnablesThinkingWhenEffortRequested(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -257,6 +267,7 @@ func TestStreamCompletionEnablesThinkingWhenEffortRequested(t *testing.T) {
}
func TestStreamCompletionOmitsThinkingWithoutEffort(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -287,6 +298,7 @@ func TestStreamCompletionOmitsThinkingWithoutEffort(t *testing.T) {
}
func TestStreamCompletionCapturesThinkingBlocksForReplay(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_start", `{"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":""}}`)
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"Let me think"}}`)
@@ -312,6 +324,7 @@ func TestStreamCompletionCapturesThinkingBlocksForReplay(t *testing.T) {
}
func TestStreamCompletionPreservesUnclosedThinkingBlockAtStreamEnd(t *testing.T) {
+ t.Parallel()
// The SSE ends after thinking_delta/signature_delta but BEFORE the thinking
// block's content_block_stop. The open buffer must still be finalized into the
// done event's ReasoningBlocks (via closeOpen), or the next Anthropic replay
@@ -339,6 +352,7 @@ func TestStreamCompletionPreservesUnclosedThinkingBlockAtStreamEnd(t *testing.T)
}
func TestAnthropicRequestReplaysThinkingBlocksFirst(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -392,6 +406,7 @@ func TestAnthropicRequestReplaysThinkingBlocksFirst(t *testing.T) {
}
func TestStreamCompletionEmitsToolUseBlocks(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_start", `{"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_1","name":"read_file","input":{}}}`)
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"path\":"}}`)
@@ -414,6 +429,7 @@ func TestStreamCompletionEmitsToolUseBlocks(t *testing.T) {
}
func TestStreamCompletionClosesOpenToolCallOnEOF(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "content_block_start", `{"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_1","name":"grep","input":{}}}`)
writeSSEEvent(w, "content_block_delta", `{"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"pattern\":\"Zero\"}"}}`)
@@ -429,6 +445,7 @@ func TestStreamCompletionClosesOpenToolCallOnEOF(t *testing.T) {
}
func TestStreamCompletionClassifiesHTTPErrorsAndRedactsToken(t *testing.T) {
+ t.Parallel()
cases := []struct {
name string
status int
@@ -464,6 +481,7 @@ func TestStreamCompletionClassifiesHTTPErrorsAndRedactsToken(t *testing.T) {
}
func TestStreamCompletionEmitsStreamErrorObject(t *testing.T) {
+ t.Parallel()
provider := newTestProviderWithKey(t, "sk-ant", func(w http.ResponseWriter, r *http.Request) {
writeSSEEvent(w, "error", `{"type":"error","error":{"message":"stream failed sk-ant","type":"overloaded_error"}}`)
})
@@ -481,6 +499,7 @@ func TestStreamCompletionEmitsStreamErrorObject(t *testing.T) {
}
func TestStreamCompletionRejectsMalformedHistoryBeforeDispatch(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("provider should not dispatch malformed history")
})
@@ -507,6 +526,7 @@ func TestStreamCompletionRejectsMalformedHistoryBeforeDispatch(t *testing.T) {
}
func TestNewRequiresModelAndPositiveMaxTokens(t *testing.T) {
+ t.Parallel()
if _, err := New(Options{}); err == nil {
t.Fatal("New without model returned nil error")
}
diff --git a/internal/providers/anthropic/stop_reason_test.go b/internal/providers/anthropic/stop_reason_test.go
index ecd887b2f..d881acba5 100644
--- a/internal/providers/anthropic/stop_reason_test.go
+++ b/internal/providers/anthropic/stop_reason_test.go
@@ -7,6 +7,7 @@ import (
)
func TestMapStopReasonRefusal(t *testing.T) {
+ t.Parallel()
if got := mapStopReason("refusal"); got != zeroruntime.FinishReasonContentFilter {
t.Errorf("refusal → %q, want content_filter (M4)", got)
}
diff --git a/internal/providers/factory_turn_session_test.go b/internal/providers/factory_turn_session_test.go
index 03b8a8dc7..050f20c33 100644
--- a/internal/providers/factory_turn_session_test.go
+++ b/internal/providers/factory_turn_session_test.go
@@ -14,6 +14,7 @@ import (
// wraps into the default TurnSessionProvider: construction succeeds, a session
// opens, and Compact reports unsupported (the default adapter contract).
func TestNewTurnSessionProviderForEveryKind(t *testing.T) {
+ t.Parallel()
kinds := []config.ProviderKind{
config.ProviderKindOpenAI,
config.ProviderKindOpenAICompatible,
@@ -65,6 +66,7 @@ func TestNewTurnSessionProviderForEveryKind(t *testing.T) {
// projects the model-registry entry (context limits, capability flags,
// reasoning efforts) into the flat ProviderCapabilities.
func TestNewTurnSessionProviderProjectsRegistryCapabilities(t *testing.T) {
+ t.Parallel()
registry, err := modelregistry.NewRegistry([]modelregistry.ModelEntry{{
ID: "pr7-caps-model",
DisplayName: "PR7 Capability Probe",
@@ -137,6 +139,7 @@ func TestNewTurnSessionProviderProjectsRegistryCapabilities(t *testing.T) {
// entry that enumerates no efforts of its own still reports the name-inferred
// effective tiers the /effort picker and run-time resolver advertise.
func TestNewTurnSessionProviderUsesEffectiveReasoningEfforts(t *testing.T) {
+ t.Parallel()
registry, err := modelregistry.NewRegistry([]modelregistry.ModelEntry{{
// A gpt-5-family id with NO ReasoningEfforts listed: the effective
// efforts come from name inference, differing from the raw entry.
diff --git a/internal/providers/gemini/done_test.go b/internal/providers/gemini/done_test.go
index bf19903fb..074e22576 100644
--- a/internal/providers/gemini/done_test.go
+++ b/internal/providers/gemini/done_test.go
@@ -10,6 +10,7 @@ import (
// emitDone must mark the shared state done so callers observe it through the
// pointer (a by-value receiver would make state.done a dead store).
func TestEmitDoneMarksStateDoneThroughPointer(t *testing.T) {
+ t.Parallel()
provider, err := New(Options{Model: "gemini-test"})
if err != nil {
t.Fatalf("New returned error: %v", err)
diff --git a/internal/providers/gemini/finish_reason_test.go b/internal/providers/gemini/finish_reason_test.go
index 088aefc88..5328bcbf2 100644
--- a/internal/providers/gemini/finish_reason_test.go
+++ b/internal/providers/gemini/finish_reason_test.go
@@ -12,6 +12,7 @@ import (
// MAX_TOKENS to length, and every other non-STOP reason surfaces its raw value
// (M3) so the turn is not mistaken for a clean completion.
func TestMapFinishReasonNonNormal(t *testing.T) {
+ t.Parallel()
for _, normal := range []string{"", "STOP", "FINISH_REASON_UNSPECIFIED"} {
if got := mapFinishReason(normal); got != "" {
t.Errorf("%q should be a normal stop (empty), got %q", normal, got)
@@ -35,6 +36,7 @@ func TestMapFinishReasonNonNormal(t *testing.T) {
// A candidate finishReason of MAX_TOKENS means the response was truncated at the
// output cap. The provider must surface it on the done event.
func TestStreamCompletionSurfacesMaxTokensFinishReason(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"role":"model","parts":[{"text":"cut"}]},"finishReason":"MAX_TOKENS"}]}`)
})
@@ -58,6 +60,7 @@ func TestStreamCompletionSurfacesMaxTokensFinishReason(t *testing.T) {
// A SAFETY finishReason maps to the runtime's content-filter reason.
func TestStreamCompletionSurfacesSafetyFinishReason(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"role":"model","parts":[{"text":""}]},"finishReason":"SAFETY"}]}`)
})
@@ -81,6 +84,7 @@ func TestStreamCompletionSurfacesSafetyFinishReason(t *testing.T) {
// M3 maps it to content_filter. This exercises that fix through the full
// SSE → done-event wiring, not just mapFinishReason in isolation.
func TestStreamCompletionSurfacesRecitationFinishReason(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"role":"model","parts":[{"text":""}]},"finishReason":"RECITATION"}]}`)
})
@@ -102,6 +106,7 @@ func TestStreamCompletionSurfacesRecitationFinishReason(t *testing.T) {
// A normal STOP finishReason must leave the done event's FinishReason empty.
func TestStreamCompletionNormalFinishReasonHasNoReason(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"role":"model","parts":[{"text":"ok"}]},"finishReason":"STOP"}]}`)
})
@@ -125,6 +130,7 @@ func TestStreamCompletionNormalFinishReasonHasNoReason(t *testing.T) {
// signal a dropped tool call (once) so the agent can ask the model to retry,
// rather than silently skipping it.
func TestStreamCompletionEmitsDroppedOnNamelessFunctionCallPart(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"role":"model","parts":[{"functionCall":{"name":"","args":{"a":1}}}]}}]}`)
})
@@ -149,6 +155,7 @@ func TestStreamCompletionEmitsDroppedOnNamelessFunctionCallPart(t *testing.T) {
// A nameless top-level functionCall must also be signalled as dropped.
func TestStreamCompletionEmitsDroppedOnNamelessTopLevelFunctionCall(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"functionCalls":[{"name":"","args":{"a":1}}]}`)
})
@@ -173,6 +180,7 @@ func TestStreamCompletionEmitsDroppedOnNamelessTopLevelFunctionCall(t *testing.T
// A well-formed functionCall must NOT emit a dropped signal.
func TestStreamCompletionDoesNotDropValidFunctionCall(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"role":"model","parts":[{"functionCall":{"name":"read_file","args":{"path":"x"}}}]}}]}`)
})
diff --git a/internal/providers/gemini/idle_test.go b/internal/providers/gemini/idle_test.go
index 2881022cc..9498eb975 100644
--- a/internal/providers/gemini/idle_test.go
+++ b/internal/providers/gemini/idle_test.go
@@ -14,6 +14,7 @@ import (
// A stalled-but-open Gemini upstream (sends one chunk, then hangs without
// closing) must abort on the idle timeout instead of blocking the agent forever.
func TestStreamCompletionIdleTimeoutAbortsStalledStream(t *testing.T) {
+ t.Parallel()
released := make(chan struct{})
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"parts":[{"text":"hi"}]}}]}`)
diff --git a/internal/providers/gemini/images_test.go b/internal/providers/gemini/images_test.go
index 678d16291..6c6d5a9a4 100644
--- a/internal/providers/gemini/images_test.go
+++ b/internal/providers/gemini/images_test.go
@@ -9,6 +9,7 @@ import (
)
func TestGeminiPartTextOnlySerializationOmitsInlineData(t *testing.T) {
+ t.Parallel()
part := geminiPart{Text: "hello"}
got, err := json.Marshal(part)
if err != nil {
@@ -20,6 +21,7 @@ func TestGeminiPartTextOnlySerializationOmitsInlineData(t *testing.T) {
}
func TestGeminiInlineDataSerialization(t *testing.T) {
+ t.Parallel()
part := geminiPart{InlineData: &geminiInlineData{MimeType: "image/png", Data: "QUJD"}}
got, err := json.Marshal(part)
if err != nil {
@@ -31,6 +33,7 @@ func TestGeminiInlineDataSerialization(t *testing.T) {
}
func TestMapMessagesTextOnlyUserUnchanged(t *testing.T) {
+ t.Parallel()
_, contents, err := mapMessages([]zeroruntime.Message{
{Role: zeroruntime.MessageRoleUser, Content: "Read the file."},
})
@@ -47,6 +50,7 @@ func TestMapMessagesTextOnlyUserUnchanged(t *testing.T) {
}
func TestMapMessagesImageAndTextUserTurn(t *testing.T) {
+ t.Parallel()
raw := []byte("ABC")
_, contents, err := mapMessages([]zeroruntime.Message{
{
@@ -80,6 +84,7 @@ func TestMapMessagesImageAndTextUserTurn(t *testing.T) {
}
func TestMapMessagesImageOnlyUserTurn(t *testing.T) {
+ t.Parallel()
_, contents, err := mapMessages([]zeroruntime.Message{
{
Role: zeroruntime.MessageRoleUser,
diff --git a/internal/providers/gemini/provider_test.go b/internal/providers/gemini/provider_test.go
index 7c83c7148..c407e8e41 100644
--- a/internal/providers/gemini/provider_test.go
+++ b/internal/providers/gemini/provider_test.go
@@ -14,6 +14,7 @@ import (
)
func TestStreamCompletionPostsGenerateContentRequest(t *testing.T) {
+ t.Parallel()
var gotPath string
var gotQuery string
var gotAPIKey string
@@ -118,6 +119,7 @@ func TestStreamCompletionPostsGenerateContentRequest(t *testing.T) {
}
func TestStreamCompletionEnablesThinkingWhenEffortRequested(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -151,6 +153,7 @@ func TestStreamCompletionEnablesThinkingWhenEffortRequested(t *testing.T) {
}
func TestStreamCompletionOmitsThinkingWithoutEffort(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -179,6 +182,7 @@ func TestStreamCompletionOmitsThinkingWithoutEffort(t *testing.T) {
}
func TestStreamCompletionCapturesThoughtSignatureAndSkipsThoughtText(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
// A thought-summary part (must not surface as answer text) followed by a
// functionCall part carrying its thoughtSignature.
@@ -201,6 +205,7 @@ func TestStreamCompletionCapturesThoughtSignatureAndSkipsThoughtText(t *testing.
}
func TestGeminiRequestReplaysThoughtSignature(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
@@ -238,6 +243,7 @@ func TestGeminiRequestReplaysThoughtSignature(t *testing.T) {
}
func TestStreamCompletionAppliesCustomAuthAndHeaders(t *testing.T) {
+ t.Parallel()
var gotDefaultAuth string
var gotCustomAuth string
var gotTenant string
@@ -280,6 +286,7 @@ func TestStreamCompletionAppliesCustomAuthAndHeaders(t *testing.T) {
}
func TestStreamCompletionEmitsTextUsageAndReasoningTokens(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"parts":[{"text":"Hello"}]}}]}`)
writeSSE(w, `{"candidates":[{"content":{"parts":[{"text":" Zero"}]}}],"usageMetadata":{"promptTokenCount":25,"candidatesTokenCount":15,"thoughtsTokenCount":3,"cachedContentTokenCount":7}}`)
@@ -298,6 +305,7 @@ func TestStreamCompletionEmitsTextUsageAndReasoningTokens(t *testing.T) {
}
func TestStreamCompletionEmitsCandidateFunctionCalls(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"candidates":[{"content":{"parts":[{"functionCall":{"id":"call_1","name":"read_file","args":{"path":"src/index.ts"}}},{"functionCall":{"id":"call_2","name":"grep","args":{"pattern":"Zero"}}}]}}]}`)
})
@@ -318,6 +326,7 @@ func TestStreamCompletionEmitsCandidateFunctionCalls(t *testing.T) {
}
func TestStreamCompletionEmitsTopLevelFunctionCalls(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"functionCalls":[{"id":"call_1","name":"read_file","args":{"path":"README.md"}}]}`)
})
@@ -335,6 +344,7 @@ func TestStreamCompletionEmitsTopLevelFunctionCalls(t *testing.T) {
}
func TestStreamCompletionUsesSyntheticToolIDsWhenMissing(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"functionCalls":[{"name":"grep","args":{"pattern":"Zero"}}]}`)
})
@@ -346,6 +356,7 @@ func TestStreamCompletionUsesSyntheticToolIDsWhenMissing(t *testing.T) {
}
func TestStreamCompletionClassifiesHTTPAndPromptBlockErrors(t *testing.T) {
+ t.Parallel()
authProvider := newTestProviderWithKey(t, "sk-google", func(w http.ResponseWriter, r *http.Request) {
http.Error(w, `{"error":{"message":"API key not valid"}}`, http.StatusUnauthorized)
})
@@ -373,6 +384,7 @@ func TestStreamCompletionClassifiesHTTPAndPromptBlockErrors(t *testing.T) {
// A 401 with an OAuth resolver is retried once with a force-refreshed token; the
// replayed request carries the refreshed bearer and succeeds.
func TestStreamCompletionRetries401WithRefreshedToken(t *testing.T) {
+ t.Parallel()
var attempts int
var secondAuth string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -422,6 +434,7 @@ func TestStreamCompletionRetries401WithRefreshedToken(t *testing.T) {
}
func TestStreamCompletionEmitsStreamErrorObject(t *testing.T) {
+ t.Parallel()
provider := newTestProviderWithKey(t, "sk-google", func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"error":{"code":429,"message":"stream failed sk-google","status":"RESOURCE_EXHAUSTED"}}`)
})
@@ -439,6 +452,7 @@ func TestStreamCompletionEmitsStreamErrorObject(t *testing.T) {
}
func TestStreamCompletionStopsOnMalformedStreamToolArgs(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"functionCalls":[{"id":"call_1","name":"grep","args":"raw"}]}`)
writeSSE(w, `{"candidates":[{"content":{"parts":[{"text":"should not emit"}]}}]}`)
@@ -457,6 +471,7 @@ func TestStreamCompletionStopsOnMalformedStreamToolArgs(t *testing.T) {
}
func TestStreamCompletionRejectsMalformedHistoryBeforeDispatch(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("provider should not dispatch malformed history")
})
@@ -483,6 +498,7 @@ func TestStreamCompletionRejectsMalformedHistoryBeforeDispatch(t *testing.T) {
}
func TestNewRequiresModelAndPositiveMaxTokens(t *testing.T) {
+ t.Parallel()
if _, err := New(Options{}); err == nil {
t.Fatal("New without model returned nil error")
}
@@ -562,6 +578,7 @@ func eventsOfType(events []zeroruntime.StreamEvent, eventType zeroruntime.Stream
// OpenAI-ism (additionalProperties, $schema, patternProperties) survives at any
// depth while legitimate fields (type/description/enum/required/default) stay.
func TestSanitizeGeminiSchemaStripsUnsupportedFields(t *testing.T) {
+ t.Parallel()
in := map[string]any{
"type": "object",
"additionalProperties": false,
@@ -634,6 +651,7 @@ func assertNoAdditionalProps(t *testing.T, node any, path string) {
// ("Unknown name additionalProperties"), which broke all tool-using exec calls
// against Google (issue #373).
func TestGeminiRequestOmitsAdditionalPropertiesInToolSchema(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(&gotBody); err != nil {
diff --git a/internal/providers/openai/codex_terminal_test.go b/internal/providers/openai/codex_terminal_test.go
index 645483a48..f84720e5d 100644
--- a/internal/providers/openai/codex_terminal_test.go
+++ b/internal/providers/openai/codex_terminal_test.go
@@ -10,6 +10,7 @@ import (
)
func TestToolCallKeyOutputIndexZero(t *testing.T) {
+ t.Parallel()
p := &CodexProvider{}
zero, two := 0, 2
// output_index 0 with no item_id must produce a key (it was dropped before M1).
@@ -148,6 +149,7 @@ func TestCodexPreservesCustomApplyPatchFunction(t *testing.T) {
}
func TestHandleTerminalResponseNilPayload(t *testing.T) {
+ t.Parallel()
p := &CodexProvider{}
// response.failed with no Response payload must emit an error, not a silent done.
@@ -180,6 +182,7 @@ func TestHandleTerminalResponseNilPayload(t *testing.T) {
}
func TestHandleTerminalResponseFailedPayloadWithoutError(t *testing.T) {
+ t.Parallel()
p := &CodexProvider{}
// A response.failed carrying a payload whose error object is null/omitted (the
diff --git a/internal/providers/openai/codex_test.go b/internal/providers/openai/codex_test.go
index 535993d56..2d61d4158 100644
--- a/internal/providers/openai/codex_test.go
+++ b/internal/providers/openai/codex_test.go
@@ -82,6 +82,7 @@ func drainCodexEvents(t *testing.T, stream <-chan zeroruntime.StreamEvent) {
}
func TestCodexProviderSetsExpectedHeaders(t *testing.T) {
+ t.Parallel()
var rec codexRequest
srv := newCodexTestServer(t, &rec)
defer srv.Close()
@@ -130,6 +131,7 @@ func TestCodexProviderSetsExpectedHeaders(t *testing.T) {
}
func TestCodexProviderUsesConfiguredBaseURL(t *testing.T) {
+ t.Parallel()
var rec codexRequest
// Run the test server on a custom path to confirm the request goes
// through {BaseURL}/responses, not a hard-coded host.
@@ -175,6 +177,7 @@ func TestCodexProviderUsesConfiguredBaseURL(t *testing.T) {
}
func TestCodexProviderDefaultsOriginator(t *testing.T) {
+ t.Parallel()
var rec codexRequest
srv := newCodexTestServer(t, &rec)
defer srv.Close()
@@ -204,6 +207,7 @@ func TestCodexProviderDefaultsOriginator(t *testing.T) {
}
func TestCodexProviderBrandsUserAgent(t *testing.T) {
+ t.Parallel()
var rec codexRequest
srv := newCodexTestServer(t, &rec)
defer srv.Close()
@@ -236,6 +240,7 @@ func TestCodexProviderBrandsUserAgent(t *testing.T) {
}
func TestCodexProviderAccountResolverIsUsedWhenAccountIDEmpty(t *testing.T) {
+ t.Parallel()
var rec codexRequest
srv := newCodexTestServer(t, &rec)
defer srv.Close()
@@ -272,6 +277,7 @@ func TestCodexProviderAccountResolverIsUsedWhenAccountIDEmpty(t *testing.T) {
}
func TestCodexProviderResolverIsConsultedOnEveryRequest(t *testing.T) {
+ t.Parallel()
// The factory wires the AccountResolver from the OAuth store so a refresh
// that updates the stored token's Account field takes effect on the next
// outgoing request — not just the first. This test asserts the resolver
@@ -354,6 +360,7 @@ func TestCodexProviderResolverIsConsultedOnEveryRequest(t *testing.T) {
}
func TestCodexProviderOmitsAccountIDWhenResolverSaysNo(t *testing.T) {
+ t.Parallel()
var rec codexRequest
srv := newCodexTestServer(t, &rec)
defer srv.Close()
@@ -384,6 +391,7 @@ func TestCodexProviderOmitsAccountIDWhenResolverSaysNo(t *testing.T) {
}
func TestCodexProviderSendsResponsesRequestShape(t *testing.T) {
+ t.Parallel()
// The Codex provider speaks the Responses API, not the chat-completions
// API. The request body must carry top-level `instructions`, `input` items
// (not `messages`), a `stream: true` flag, and `tools` (when the caller
@@ -455,6 +463,7 @@ func TestCodexProviderSendsResponsesRequestShape(t *testing.T) {
}
func TestCodexProviderForwardsReasoningEffort(t *testing.T) {
+ t.Parallel()
// A reasoning effort must reach the Responses backend nested under
// `reasoning.effort` (where the chat-completions `reasoning_effort` moved).
// Without this the user's chosen effort is silently dropped for Codex models.
@@ -493,6 +502,7 @@ func TestCodexProviderForwardsReasoningEffort(t *testing.T) {
}
func TestCodexProviderNormalizesServiceTier(t *testing.T) {
+ t.Parallel()
for _, test := range []struct {
name string
input string
@@ -536,6 +546,7 @@ func TestCodexProviderNormalizesServiceTier(t *testing.T) {
}
func TestCodexProviderStreamsReasoningSummaryDeltas(t *testing.T) {
+ t.Parallel()
// reasoning_summary_text deltas must surface as StreamEventReasoning (live
// "thinking"), in order, alongside the normal text output. Without this a long
// reasoning phase produces zero visible output and reads as a hang.
@@ -583,6 +594,7 @@ func TestCodexProviderStreamsReasoningSummaryDeltas(t *testing.T) {
}
func TestCodexProviderOmitsReasoningWhenUnset(t *testing.T) {
+ t.Parallel()
// No effort (and unsupported values) must omit the `reasoning` field entirely
// rather than send an empty object, which the backend would reject.
var rec codexRequest
@@ -611,6 +623,7 @@ func TestCodexProviderOmitsReasoningWhenUnset(t *testing.T) {
}
func TestCodexProviderRetriesHeadersAfter401(t *testing.T) {
+ t.Parallel()
var hits atomic.Int32
var rec1, rec2 codexRequest
mux := http.NewServeMux()
@@ -685,6 +698,7 @@ func TestCodexProviderRetriesHeadersAfter401(t *testing.T) {
}
func TestCodexProviderRequiresBaseURL(t *testing.T) {
+ t.Parallel()
// An empty baseURL falls back to the openai provider's default
// (https://api.openai.com/v1). The Codex provider is designed to be
// wired by the factory with the catalog's Codex baseURL, so the
@@ -704,6 +718,7 @@ func TestCodexProviderRequiresBaseURL(t *testing.T) {
}
func TestCodexProviderRejectsBadBaseURL(t *testing.T) {
+ t.Parallel()
_, err := NewCodexProvider(CodexOptions{
Options: Options{APIKey: "sk", Model: "gpt-5", BaseURL: "://not a url"},
AccountID: "acc-x",
@@ -717,6 +732,7 @@ func TestCodexProviderRejectsBadBaseURL(t *testing.T) {
}
func TestValidateAccount(t *testing.T) {
+ t.Parallel()
if err := ValidateAccount(""); err == nil {
t.Fatal("empty account id should be rejected")
}
@@ -729,9 +745,9 @@ func TestValidateAccount(t *testing.T) {
}
func TestCodexProviderStreamIdleTimeoutPropagates(t *testing.T) {
- // Sanity check: the wrapped openai provider's StreamIdleTimeout flows
- // through. The default is 90s; we override to a small value so a real
- // hang surfaces in the test.
+ // Serial: StreamIdleTimeout arms a real wall-clock idle timer. Under
+ // t.Parallel() the 50ms watchdog can fire before response.completed is
+ // consumed. This test only checks that the option is accepted.
var rec codexRequest
srv := newCodexTestServer(t, &rec)
defer srv.Close()
@@ -760,6 +776,7 @@ func TestCodexProviderStreamIdleTimeoutPropagates(t *testing.T) {
}
func TestCodexProviderParsesResponsesTextDeltas(t *testing.T) {
+ t.Parallel()
// The Codex backend streams text as a series of
// `response.output_text.delta` events. Each delta must surface as a
// runtime text event in order, and the terminal `response.completed`
@@ -818,6 +835,7 @@ func TestCodexProviderParsesResponsesTextDeltas(t *testing.T) {
}
func TestCodexProviderParsesResponsesToolCalls(t *testing.T) {
+ t.Parallel()
// The Codex backend streams function calls as three coordinated event
// types: `response.output_item.added` (carries the call id and name),
// `response.function_call_arguments.delta` (one or more events that
@@ -886,6 +904,7 @@ func TestCodexProviderParsesResponsesToolCalls(t *testing.T) {
}
func TestCodexProviderSendsAssistantToolCallsAsInputItems(t *testing.T) {
+ t.Parallel()
// When the runtime replays a prior assistant turn that issued a tool
// call, the Codex provider must serialize the turn as BOTH the
// assistant message (its text) AND a function_call item for the call.
@@ -957,6 +976,7 @@ func TestCodexProviderSendsAssistantToolCallsAsInputItems(t *testing.T) {
}
func TestCodexProviderEmitsErrorOnResponseErrorEvent(t *testing.T) {
+ t.Parallel()
// A `response.error` event from the Codex backend is the stream-level
// error signal. It must surface as a single StreamEventError and stop
// the scan so the runtime doesn't hang waiting for a completion.
@@ -995,6 +1015,7 @@ func TestCodexProviderEmitsErrorOnResponseErrorEvent(t *testing.T) {
}
func TestCodexProviderEmitsErrorOnMalformedStream(t *testing.T) {
+ t.Parallel()
// A non-JSON data payload (or a payload with a missing `type` field)
// must be reported as a stream error rather than silently dropped —
// otherwise the runtime would hang waiting for a completion event
@@ -1031,6 +1052,7 @@ func TestCodexProviderEmitsErrorOnMalformedStream(t *testing.T) {
}
func TestCodexProviderEmitsLengthFinishWhenStreamEndsWithoutCompletion(t *testing.T) {
+ t.Parallel()
// The Codex backend may close the SSE stream without emitting
// `response.completed` (e.g. an internal truncation). The wrapper
// must surface a StreamEventDone with FinishReasonLength so the
diff --git a/internal/providers/openai/provider_test.go b/internal/providers/openai/provider_test.go
index 8f1e817a0..a59e1a634 100644
--- a/internal/providers/openai/provider_test.go
+++ b/internal/providers/openai/provider_test.go
@@ -11,10 +11,16 @@ import (
"testing"
"time"
+ "github.com/Gitlawb/zero/internal/providers/providerio"
"github.com/Gitlawb/zero/internal/zeroruntime"
)
+func init() {
+ providerio.ShrinkBackoffForTest()
+}
+
func TestStreamCompletionPostsChatCompletionRequest(t *testing.T) {
+ t.Parallel()
var gotPath string
var gotAuth string
var gotUserAgent string
@@ -120,6 +126,7 @@ func TestStreamCompletionPostsChatCompletionRequest(t *testing.T) {
// "properties":null, because strict OpenAI-compatible servers (LM Studio)
// reject the null form.
func TestStreamCompletionSerializesTypedNilPropertiesAsEmptyObject(t *testing.T) {
+ t.Parallel()
var gotBody map[string]any
var gotRaw []byte
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -175,6 +182,7 @@ func TestStreamCompletionSerializesTypedNilPropertiesAsEmptyObject(t *testing.T)
}
func TestNewRequiresModelButNotAPIKey(t *testing.T) {
+ t.Parallel()
if _, err := New(Options{}); err == nil {
t.Fatal("New without model returned nil error")
}
@@ -184,6 +192,7 @@ func TestNewRequiresModelButNotAPIKey(t *testing.T) {
}
func TestStreamCompletionOmitsAuthAndToolsWhenEmpty(t *testing.T) {
+ t.Parallel()
var gotAuth string
var gotBody map[string]any
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -216,6 +225,7 @@ func TestStreamCompletionOmitsAuthAndToolsWhenEmpty(t *testing.T) {
}
func TestStreamCompletionAppliesCustomAuthAndHeaders(t *testing.T) {
+ t.Parallel()
var gotAuth string
var gotAltAuth string
var gotReferer string
@@ -258,6 +268,7 @@ func TestStreamCompletionAppliesCustomAuthAndHeaders(t *testing.T) {
}
func TestStreamCompletionEmitsTextUsageAndDone(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"content":"hello "}}]}`)
writeSSE(w, `{"choices":[{"delta":{"content":"zero"}}],"usage":{"prompt_tokens":12,"completion_tokens":5,"prompt_tokens_details":{"cached_tokens":3,"cache_write_tokens":2}}}`)
@@ -276,6 +287,7 @@ func TestStreamCompletionEmitsTextUsageAndDone(t *testing.T) {
}
func TestStreamCompletionEmitsReasoningContentDeltas(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"reasoning_content":"Thinking. "}}]}`)
writeSSE(w, `{"choices":[{"delta":{"reasoning_content":"Answering now."}}]}`)
@@ -296,6 +308,7 @@ func TestStreamCompletionEmitsReasoningContentDeltas(t *testing.T) {
}
func TestStreamCompletionEmitsReasoningAliasDeltas(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"reasoning":"Thinking. "}}]}`)
writeSSE(w, `{"choices":[{"delta":{"reasoning":"Answering now."}}]}`)
@@ -316,6 +329,7 @@ func TestStreamCompletionEmitsReasoningAliasDeltas(t *testing.T) {
}
func TestStreamCompletionPrefersReasoningContentOverAlias(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"reasoning_content":"standard","reasoning":"alias"}}]}`)
writeSSE(w, `[DONE]`)
@@ -329,6 +343,7 @@ func TestStreamCompletionPrefersReasoningContentOverAlias(t *testing.T) {
}
func TestStreamCompletionEmitsReasoningBeforeRegularContent(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"reasoning_content":"Thinking. ","content":"Answer."}}]}`)
writeSSE(w, `[DONE]`)
@@ -346,6 +361,7 @@ func TestStreamCompletionEmitsReasoningBeforeRegularContent(t *testing.T) {
}
func TestStreamCompletionPreservesLiteralThinkTagsByDefault(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"content":"show literal markup"}}]}`)
writeSSE(w, `[DONE]`)
@@ -359,6 +375,7 @@ func TestStreamCompletionPreservesLiteralThinkTagsByDefault(t *testing.T) {
}
func TestStreamCompletionSplitsInlineThinkTagsFromContent(t *testing.T) {
+ t.Parallel()
provider := newTestProviderWithThinkTags(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"content":"private reasoningpublic answer"}}]}`)
writeSSE(w, `[DONE]`)
@@ -373,6 +390,7 @@ func TestStreamCompletionSplitsInlineThinkTagsFromContent(t *testing.T) {
}
func TestStreamCompletionSplitsInlineThinkTagsAcrossChunks(t *testing.T) {
+ t.Parallel()
provider := newTestProviderWithThinkTags(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"content":"reason"}}]}`)
@@ -393,6 +411,7 @@ func TestStreamCompletionSplitsInlineThinkTagsAcrossChunks(t *testing.T) {
}
func TestStreamCompletionBuffersToolArgsUntilIDAndNameArrive(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"path\":"}}]}}]}`)
writeSSE(w, `{"choices":[{"delta":{"tool_calls":[{"index":0,"id":"call_1","function":{"name":"read_file","arguments":"\"README.md\"}"}}]},"finish_reason":"tool_calls"}]}`)
@@ -418,6 +437,7 @@ func TestStreamCompletionBuffersToolArgsUntilIDAndNameArrive(t *testing.T) {
}
func TestStreamCompletionTracksMultipleToolCallsByIndex(t *testing.T) {
+ t.Parallel()
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"query\":"}},{"index":0,"id":"call_a","function":{"name":"read_file","arguments":"{\"path\":\"a\"}"}}]}}]}`)
writeSSE(w, `{"choices":[{"delta":{"tool_calls":[{"index":1,"id":"call_b","function":{"name":"grep","arguments":"\"zero\"}"}}]},"finish_reason":"tool_calls"}]}`)
@@ -440,6 +460,7 @@ func TestStreamCompletionTracksMultipleToolCallsByIndex(t *testing.T) {
}
func TestStreamCompletionClassifiesHTTPErrorsAndRedactsToken(t *testing.T) {
+ t.Parallel()
cases := []struct {
name string
status int
@@ -480,6 +501,7 @@ func TestStreamCompletionClassifiesHTTPErrorsAndRedactsToken(t *testing.T) {
}
func TestStreamCompletionHumanizesUpstreamUnreachableGatewayError(t *testing.T) {
+ t.Parallel()
// A local Ollama daemon serving a "-cloud" model answers on localhost but
// returns HTTP 502 with an opaque proxied transport error when it cannot reach
// its cloud backend. The adapter must surface a clear connectivity message
@@ -507,6 +529,7 @@ func TestStreamCompletionHumanizesUpstreamUnreachableGatewayError(t *testing.T)
}
func TestStreamCompletionEmitsStreamErrorObject(t *testing.T) {
+ t.Parallel()
provider := newTestProviderWithKey(t, "sk-secret", func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"error":{"message":"stream failed sk-secret","type":"server_error"}}`)
})
@@ -524,6 +547,7 @@ func TestStreamCompletionEmitsStreamErrorObject(t *testing.T) {
}
func TestStreamCompletionClassifiesStreamErrorCode(t *testing.T) {
+ t.Parallel()
// The error arrives inside a 200 OK SSE payload's "code" field, not the
// HTTP status, so this exercises openAIStreamErrorStatusByCode directly:
// both the numeric-string codes some providers send and the semantic
@@ -575,6 +599,7 @@ func TestStreamCompletionEmitsErrorForMalformedJSON(t *testing.T) {
}
func TestStreamCompletionEmitsErrorWhenContextCancels(t *testing.T) {
+ t.Parallel()
requestStarted := make(chan struct{})
release := make(chan struct{})
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
@@ -605,6 +630,7 @@ func TestStreamCompletionEmitsErrorWhenContextCancels(t *testing.T) {
// caller timeout, NOT humanized into an "upstream unreachable" outage (the host
// is reachable; the caller's clock ran out).
func TestStreamCompletionContextDeadlineNotHumanizedAsUpstream(t *testing.T) {
+ t.Parallel()
release := make(chan struct{})
defer close(release)
provider := newTestProvider(t, func(w http.ResponseWriter, r *http.Request) {
@@ -631,6 +657,7 @@ func TestStreamCompletionContextDeadlineNotHumanizedAsUpstream(t *testing.T) {
}
func TestStreamCompletionFlushesBufferedContentWhenContextCancels(t *testing.T) {
+ t.Parallel()
release := make(chan struct{})
provider := newTestProviderWithThinkTags(t, func(w http.ResponseWriter, r *http.Request) {
writeSSE(w, `{"choices":[{"delta":{"content":"visible