test: testify table-driven coverage for low-coverage branches

Lifts all 14 functions the operator flagged as <75% (measured at ed2119c)
to >=75%, using table-driven tests (require for fatals, assert for checks):

- limits.go: failPolicyGet (50.0% -> 100.0%)
- provider_gemini.go: httpClient (0.0% -> 100.0%)
- redis_store.go: get (71.4% -> 78.6%)
- resp.go: dialTimeoutFor, respDeadlineExceededErr.{Error,Timeout,Temporary},
  ensureConnLocked, getBatch (66.7-30.0% -> 91.3-100.0%)
- routes_media.go: resolveMediaRequest (50.0% -> 100.0%)
- routes_unified.go: unifiedCostMicros (66.7% -> 100.0%)
- translate_anthropic.go: isTruthy, toFloat64 (50.0/33.3% -> 100.0%)
- translate_gemini.go: geminiToolConfigFromOpenAI (66.7% -> 100.0%)

resp_test.go adds a hand-rolled fakeConn (net.Conn with injectable
Write/SetDeadline errors) to reach two respClient error branches a real
TCP connection cannot be coaxed into deterministically.

Total coverage: 90.7% -> 92.4% (no regression; report has the full
per-file table). Zero production-code changes. Existing tests untouched:
every diff is a pure addition of new test functions and their imports.

Gates: go test -count=1 (pass), -race (pass, 5x incl. an isolated
baseline-vs-branch comparison after one flaky run implicated pre-existing
registry_test.go timing tests this task never touched), gofmt/vet (clean),
golangci-lint incl. gosec and fieldalignment (0 issues), make yaegi-check
(OK), make integration (pass, untouched-green).
This commit is contained in:
2026-08-20 21:33:08 +01:00
parent f7d9208bde
commit aee3908bc4
8 changed files with 530 additions and 0 deletions
+59
View File
@@ -9,6 +9,8 @@ import (
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
// geminiGoldenTestdataDir is where every fixture this file walks lives.
@@ -508,3 +510,60 @@ func TestGeminiEmbeddingInputTexts_RejectsNonStringArrayEntry(t *testing.T) {
t.Fatalf("err = %v (%T), want *translateError", err, err)
}
}
// TestGeminiToolConfigFromOpenAI covers every tool_choice shape the request
// mapping table lists: the three recognized string modes, a function-name
// object, and the two "no mapping" cases (an unrecognized string, and an
// object without a valid function.name) that must return nil so the caller
// omits toolConfig entirely rather than sending a malformed one.
func TestGeminiToolConfigFromOpenAI(t *testing.T) {
cases := []struct {
tc any
want map[string]any
name string
}{
{
name: "none",
tc: "none",
want: map[string]any{"functionCallingConfig": map[string]any{"mode": "NONE"}},
},
{
name: "auto",
tc: "auto",
want: map[string]any{"functionCallingConfig": map[string]any{"mode": "AUTO"}},
},
{
name: "required",
tc: "required",
want: map[string]any{"functionCallingConfig": map[string]any{"mode": "ANY"}},
},
{
name: "function object names the allowed function",
tc: map[string]any{"type": "function", "function": map[string]any{"name": "get_weather"}},
want: map[string]any{"functionCallingConfig": map[string]any{
"mode": "ANY",
"allowedFunctionNames": []any{"get_weather"},
}},
},
{
name: "unrecognized string has no mapping",
tc: "bogus",
want: nil,
},
{
name: "object without a function.name has no mapping",
tc: map[string]any{"type": "function"},
want: nil,
},
{
name: "an unrecognized type has no mapping",
tc: 42,
want: nil,
},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
assert.Equal(t, c.want, geminiToolConfigFromOpenAI(c.tc))
})
}
}