Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion cmd/verifyexamples/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"strings"
"unicode/utf8"

"github.com/microsoft/agent-framework-go/agent"
)
Expand Down Expand Up @@ -139,5 +140,11 @@ func truncate(text string, maxLength int) string {
if len(text) <= maxLength {
return text
}
return text[:maxLength] + "... (truncated)"
// Back off to a rune boundary so truncation never splits a multi-byte rune
// (examples print °C, emoji, etc.) and emits invalid UTF-8 into logs/CSV.
Comment on lines +143 to +144
end := maxLength
for end > 0 && !utf8.RuneStart(text[end]) {
end--
}
return text[:end] + "... (truncated)"
}
17 changes: 17 additions & 0 deletions cmd/verifyexamples/verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ package main

import (
"context"
"strings"
"testing"
"unicode/utf8"
)

func TestVerifyDeterministicOutput(t *testing.T) {
Expand Down Expand Up @@ -33,3 +35,18 @@ func TestVerifyRequiresAIAgentForSemanticChecks(t *testing.T) {
t.Fatalf("Failures = %#v, want one", result.Failures)
}
}

func TestTruncateDoesNotSplitRunes(t *testing.T) {
// "°" is two bytes (0xC2 0xB0); truncating at byte 1 must not split it.
got := truncate("a°cdef", 2)
Comment on lines +40 to +41
if !utf8.ValidString(got) {
t.Fatalf("truncate produced invalid UTF-8: %q", got)
}
if !strings.HasPrefix(got, "a") || strings.ContainsRune(got, '�') {
t.Fatalf("truncate = %q, want a clean rune-boundary cut", got)
}
// Short input is returned unchanged.
if truncate("ok", 10) != "ok" {
t.Fatalf("short input was modified")
}
}
Loading