Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

81 lines
2.9 KiB
Go

package mcp
import (
"sort"
"strings"
"testing"
"pgregory.net/rapid"
)
// TestFindEOLMatches_Property generates haystacks with randomly mixed
// CRLF/LF terminators, derives a needle from a random slice of the
// normalized haystack (so a tolerant match must exist), re-terminates it
// with a random EOL flavor, and checks the matcher's core invariants:
//
// 1. at least one match is found;
// 2. every span's bytes normalize to the normalized needle (the span
// covers exactly the on-disk text the caller asked for, CRs included);
// 3. spans are in-bounds, sorted, and non-overlapping;
// 4. replacing every span with the needle itself is a normalized no-op
// (splice offsets land on real bytes, terminators adapt per region).
func TestFindEOLMatches_Property(t *testing.T) {
rapid.Check(t, func(rt *rapid.T) {
nLines := rapid.IntRange(1, 8).Draw(rt, "nLines")
var hayB strings.Builder
for i := 0; i < nLines; i++ {
// Line content occasionally carries a lone CR — always followed
// by a letter so it stays lone (a trailing bare CR would fuse
// with an LF terminator into CRLF, and a needle derived from
// the once-normalized haystack would then correctly NOT match
// the \r\r\n bytes). normalizeCRLF must pass lone CRs through
// and the span/splice invariants must still hold around them.
hayB.WriteString(rapid.StringMatching(`[a-c]{0,3}(\r[a-c]{1,2})?`).Draw(rt, "line"))
hayB.WriteString(rapid.SampledFrom([]string{"\n", "\r\n"}).Draw(rt, "eol"))
}
hay := hayB.String()
normHay, _ := normalizeCRLF(hay)
start := rapid.IntRange(0, len(normHay)-1).Draw(rt, "start")
end := rapid.IntRange(start+1, len(normHay)).Draw(rt, "end")
needleNorm := normHay[start:end]
needle := needleNorm
if rapid.Bool().Draw(rt, "crlfNeedle") {
needle = strings.ReplaceAll(needleNorm, "\n", "\r\n")
}
m := findEOLMatches(hay, needle)
if m.count == 0 {
rt.Fatalf("needle %q derived from hay %q must match", needle, hay)
}
if len(m.spans) != m.count {
rt.Fatalf("count %d != len(spans) %d", m.count, len(m.spans))
}
prevEnd := 0
for i, sp := range m.spans {
if sp.start < 0 || sp.end > len(hay) || sp.start >= sp.end {
rt.Fatalf("span %d out of bounds: %+v (hay len %d)", i, sp, len(hay))
}
if sp.start < prevEnd {
rt.Fatalf("span %d overlaps previous (start %d < prev end %d)", i, sp.start, prevEnd)
}
prevEnd = sp.end
gotNorm, _ := normalizeCRLF(hay[sp.start:sp.end])
if gotNorm != needleNorm {
rt.Fatalf("span %d bytes %q normalize to %q, want %q",
i, hay[sp.start:sp.end], gotNorm, needleNorm)
}
}
if !sort.SliceIsSorted(m.spans, func(i, j int) bool { return m.spans[i].start < m.spans[j].start }) {
rt.Fatalf("spans not sorted: %+v", m.spans)
}
out := spliceSpansEOL(hay, m.spans, needleNorm, -1)
outNorm, _ := normalizeCRLF(out)
if outNorm != normHay {
rt.Fatalf("identity replacement changed normalized content:\nhay %q\nout %q", hay, out)
}
})
}