docgov saves content hashes through the new leaf module so it no longer imports docrevision. Existing docrevision exports stay as thin wrappers. Co-authored-by: Cursor <cursoragent@cursor.com>
79 lines
2.6 KiB
Go
79 lines
2.6 KiB
Go
package docrevision_test
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
|
||
"chat-agent-system/internal/doccontent"
|
||
"chat-agent-system/internal/docrevision"
|
||
)
|
||
|
||
func TestCanonicalizeMarkdown_PreservesHardBreakDoubleSpaces(t *testing.T) {
|
||
raw := "第一行 \n第二行 \n普通行\n"
|
||
got := docrevision.CanonicalizeMarkdown(raw)
|
||
if !strings.Contains(got, "第一行 \n") || !strings.Contains(got, "第二行 \n") {
|
||
t.Fatalf("hard-break double spaces must be kept: %q", got)
|
||
}
|
||
if strings.Count(got, " \n") != 2 {
|
||
t.Fatalf("want 2 hard-breaks, got %q", got)
|
||
}
|
||
if got != raw {
|
||
t.Fatalf("already-canonical hard-break markdown must be identity: got %q", got)
|
||
}
|
||
}
|
||
|
||
func TestCanonicalizeMarkdown_OnlyNormalizesLF_NFC_TrailingNewline(t *testing.T) {
|
||
in := "a\r\n b \t\n"
|
||
out := docrevision.CanonicalizeMarkdown(in)
|
||
if out != "a\n b \t\n" {
|
||
t.Fatalf("must keep trailing spaces/tabs and only normalize CRLF: got %q", out)
|
||
}
|
||
}
|
||
|
||
func TestLegacyDestructiveCanonicalize_TrimsTrailingSpaces(t *testing.T) {
|
||
raw := "第一行 \n第二行 \n"
|
||
legacy := docrevision.LegacyDestructiveCanonicalizeMarkdown(raw)
|
||
if strings.Contains(legacy, " \n") {
|
||
t.Fatalf("legacy destructive canonicalizer must trim hard-breaks: %q", legacy)
|
||
}
|
||
if legacy != "第一行\n第二行\n" {
|
||
t.Fatalf("got %q", legacy)
|
||
}
|
||
if docrevision.SHA256Hex(legacy) == docrevision.SHA256Hex(docrevision.CanonicalizeMarkdown(raw)) {
|
||
t.Fatal("legacy and semantic-preserving hashes must differ for hard-break docs")
|
||
}
|
||
}
|
||
|
||
func TestCanonicalizeMarkdown_Project143HardBreakGolden(t *testing.T) {
|
||
// 5 lines with Markdown hard-break (two trailing spaces) — project 143 shape.
|
||
var b strings.Builder
|
||
for i := 0; i < 5; i++ {
|
||
b.WriteString("条目")
|
||
b.WriteByte('0' + byte(i))
|
||
b.WriteString(" \n")
|
||
}
|
||
b.WriteString("结尾段落。\n")
|
||
raw := b.String()
|
||
canon := docrevision.CanonicalizeMarkdown(raw)
|
||
if canon != raw {
|
||
t.Fatalf("project143-shaped hard-breaks must survive: got %q", canon)
|
||
}
|
||
legacy := docrevision.LegacyDestructiveCanonicalizeMarkdown(raw)
|
||
if len(raw)-len(legacy) != 10 {
|
||
t.Fatalf("legacy must drop exactly 10 bytes (5×2 spaces), raw=%d legacy=%d", len(raw), len(legacy))
|
||
}
|
||
}
|
||
|
||
func TestCanonicalizeWrappersMatchDoccontent(t *testing.T) {
|
||
raw := "第一行 \r\n第二行 \n"
|
||
if docrevision.CanonicalizeMarkdown(raw) != doccontent.CanonicalizeMarkdown(raw) {
|
||
t.Fatal("CanonicalizeMarkdown wrapper drifted")
|
||
}
|
||
if docrevision.LegacyDestructiveCanonicalizeMarkdown(raw) != doccontent.LegacyDestructiveCanonicalizeMarkdown(raw) {
|
||
t.Fatal("legacy wrapper drifted")
|
||
}
|
||
if docrevision.SHA256Hex(raw) != doccontent.SHA256Hex(raw) {
|
||
t.Fatal("SHA256Hex wrapper drifted")
|
||
}
|
||
}
|