From 17a46c27704e07428fd07bdc576b0e7c4966ca1a Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 29 May 2026 18:37:52 +0800 Subject: [PATCH] test: add service header util tests - Add resolveWireCasing tests - Add setHeaderRaw/addHeaderRaw/getHeaderRaw tests - Add sortHeadersByWireOrder tests --- internal/service/header_util_test.go | 187 ++++++++++++++------------- 1 file changed, 95 insertions(+), 92 deletions(-) diff --git a/internal/service/header_util_test.go b/internal/service/header_util_test.go index 9fa20cb..5bc1a54 100644 --- a/internal/service/header_util_test.go +++ b/internal/service/header_util_test.go @@ -3,112 +3,115 @@ package service import ( "net/http" "testing" -) -// ============================================================================= -// Header Utility Functions Tests -// ============================================================================= + "github.com/stretchr/testify/require" +) func TestResolveWireCasing(t *testing.T) { tests := []struct { - name string - key string - expected string + name string + key string + want string }{ - {"lowercase key", "content-type", "Content-Type"}, - {"already canonical", "Content-Type", "Content-Type"}, - {"unknown key", "x-custom-header", "x-custom-header"}, - {"anthropic-beta", "anthropic-beta", "anthropic-beta"}, + {"accept", "Accept", "Accept"}, + {"user-agent", "User-Agent", "User-Agent"}, + {"x-stainless-retry-count", "X-Stainless-Retry-Count", "X-Stainless-Retry-Count"}, + {"anthropic-version", "anthropic-version", "anthropic-version"}, + {"unknown-header", "Unknown-Header", "Unknown-Header"}, + {"mixed-case", "Mixed-Case", "Mixed-Case"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := resolveWireCasing(tt.key) - // The expected result depends on the headerWireCasing map - // We just verify the function doesn't panic and returns a string - if result == "" && tt.key != "" { - t.Errorf("resolveWireCasing(%q) returned empty string", tt.key) - } + got := resolveWireCasing(tt.key) + require.Equal(t, tt.want, got) + }) + } +} + +func TestSetHeaderRaw(t *testing.T) { + h := make(http.Header) + + // Test setting header with wire casing + setHeaderRaw(h, "Accept", "application/json") + require.Equal(t, "application/json", h.Get("Accept")) + + // Test setting header that needs wire casing resolution + // Note: setHeaderRaw stores with the exact key provided + setHeaderRaw(h, "accept", "text/html") + // The header is stored under "accept" (lowercase), not "Accept" + require.Equal(t, "text/html", h["accept"][0]) + + // Test overwriting existing header + setHeaderRaw(h, "User-Agent", "TestAgent") + setHeaderRaw(h, "user-agent", "NewAgent") + require.Equal(t, "NewAgent", h["user-agent"][0]) +} + +func TestAddHeaderRaw(t *testing.T) { + h := make(http.Header) + + // Add first value + addHeaderRaw(h, "X-Custom", "value1") + require.Equal(t, []string{"value1"}, h["X-Custom"]) + + // Add second value + addHeaderRaw(h, "X-Custom", "value2") + require.Equal(t, []string{"value1", "value2"}, h["X-Custom"]) +} + +func TestGetHeaderRaw(t *testing.T) { + h := make(http.Header) + h.Set("Accept", "application/json") + h.Set("anthropic-version", "2023-06-01") + + tests := []struct { + name string + key string + want string + }{ + {"exact_match", "Accept", "application/json"}, + {"canonical_lookup", "accept", "application/json"}, + {"wire_casing_lookup", "Accept", "application/json"}, + {"lowercase_header", "anthropic-version", "2023-06-01"}, + {"not_exist", "Not-Exist", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getHeaderRaw(h, tt.key) + require.Equal(t, tt.want, got) }) } } func TestSortHeadersByWireOrder(t *testing.T) { - t.Run("sort headers in wire order", func(t *testing.T) { - h := make(http.Header) - h.Set("Content-Type", "application/json") - h.Set("X-Custom-Header", "value") - h.Set("Authorization", "Bearer token") - - result := sortHeadersByWireOrder(h) - if len(result) != 3 { - t.Errorf("Expected 3 headers, got %d", len(result)) - } - }) - - t.Run("empty headers", func(t *testing.T) { - h := make(http.Header) - result := sortHeadersByWireOrder(h) - if len(result) != 0 { - t.Errorf("Expected 0 headers, got %d", len(result)) - } - }) + h := make(http.Header) + h.Set("Z-Last", "last") + h.Set("Accept", "application/json") + h.Set("anthropic-version", "2023-06-01") + h.Set("User-Agent", "Test") + + sorted := sortHeadersByWireOrder(h) + + // Check that wire-ordered headers come first + // Note: h.Set() uses canonical key, so "anthropic-version" becomes "Anthropic-Version" + require.Contains(t, sorted, "Accept") + require.Contains(t, sorted, "User-Agent") + require.Contains(t, sorted, "Anthropic-Version") + require.Contains(t, sorted, "Z-Last") + + // Z-Last should be at the end (not in wire order) + require.Equal(t, "Z-Last", sorted[len(sorted)-1]) } -func TestSetHeaderRaw(t *testing.T) { - t.Run("set header", func(t *testing.T) { - h := make(http.Header) - setHeaderRaw(h, "X-Custom-Header", "value1") - if h.Get("X-Custom-Header") != "value1" { - t.Errorf("Expected 'value1', got %q", h.Get("X-Custom-Header")) - } - }) - - t.Run("overwrite header", func(t *testing.T) { - h := make(http.Header) - setHeaderRaw(h, "X-Test", "value1") - setHeaderRaw(h, "X-Test", "value2") - if h.Get("X-Test") != "value2" { - t.Errorf("Expected 'value2', got %q", h.Get("X-Test")) - } - }) -} - -func TestAddHeaderRaw(t *testing.T) { - t.Run("add single header", func(t *testing.T) { - h := make(http.Header) - addHeaderRaw(h, "X-Add-Header", "value1") - if h.Get("X-Add-Header") != "value1" { - t.Errorf("Expected 'value1', got %q", h.Get("X-Add-Header")) - } - }) - - t.Run("add multiple values", func(t *testing.T) { - h := make(http.Header) - addHeaderRaw(h, "X-Multi", "value1") - addHeaderRaw(h, "X-Multi", "value2") - values := h.Values("X-Multi") - if len(values) != 2 { - t.Errorf("Expected 2 values, got %d", len(values)) - } - }) -} - -func TestGetHeaderRaw(t *testing.T) { - t.Run("get existing header", func(t *testing.T) { - h := make(http.Header) - h.Set("X-Get-Test", "testvalue") - result := getHeaderRaw(h, "X-Get-Test") - if result != "testvalue" { - t.Errorf("Expected 'testvalue', got %q", result) - } - }) - - t.Run("get non-existent header", func(t *testing.T) { - h := make(http.Header) - result := getHeaderRaw(h, "X-Nonexistent") - if result != "" { - t.Errorf("Expected empty string, got %q", result) - } - }) +func TestHeaderWireOrderSet(t *testing.T) { + // Verify headerWireOrderSet is initialized correctly + require.NotNil(t, headerWireOrderSet) + require.Greater(t, len(headerWireOrderSet), 0) + + // Check some expected keys exist + require.Contains(t, headerWireOrderSet, "accept") + require.Contains(t, headerWireOrderSet, "user-agent") + require.Contains(t, headerWireOrderSet, "anthropic-version") }