MCPcopy Index your code
hub / github.com/coder/coder / TestFuzzyReplace_EndingNormalization

Function TestFuzzyReplace_EndingNormalization

agent/agentfiles/files_test.go:2084–2224  ·  view source on GitHub ↗

TestFuzzyReplace_EndingNormalization pins the line-ending rule. Rule: every spliced line gets the file's dominant ending, except when the caller signaled intent by making search and replace disagree on internal endings (both non-empty, different). Intent requires pass 1 to byte-match the file's end

(t *testing.T)

Source from the content-addressed store, hash-verified

2082// ending, so a match covering the file's last line does not
2083// materialize a newline the file never had.
2084func TestFuzzyReplace_EndingNormalization(t *testing.T) {
2085 t.Parallel()
2086
2087 tmpdir := os.TempDir()
2088 logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
2089
2090 type edit struct {
2091 search, replace string
2092 replaceAll bool
2093 }
2094 tests := []struct {
2095 name string
2096 content string
2097 edits []edit
2098 expected string
2099 }{
2100 // CRLF file, LF search, LF replace with expansion.
2101 // Internal endings agree (both LF), rule fires, every
2102 // spliced line becomes CRLF.
2103 {
2104 name: "CRLFFile_LFSearchReplace_Expansion",
2105 content: "line1\r\nline2\r\nline3\r\n",
2106 edits: []edit{{search: "line1\nline2\n", replace: "line1\nINSERTED\nline2\n"}},
2107 expected: "line1\r\nINSERTED\r\nline2\r\nline3\r\n",
2108 },
2109 // CRLF file with no trailing newline, LF search/replace
2110 // with expansion that covers the file's last line. Interior
2111 // spliced lines become CRLF; final spliced line preserves
2112 // the file's no-EOL property.
2113 {
2114 name: "CRLFFileNoEOL_LFSearchReplace_ExpansionAtEOF",
2115 content: "alpha\r\nbeta\r\ngamma",
2116 edits: []edit{{search: "gamma", replace: "gamma\ndelta\nepsilon"}},
2117 expected: "alpha\r\nbeta\r\ngamma\r\ndelta\r\nepsilon",
2118 },
2119 // CRLF Go file with no final newline; LLM sends LF
2120 // search/replace that expands the function body. This is
2121 // the motivating real-world case for the rule.
2122 {
2123 name: "CRLFFileNoEOL_LFCallerExpandsFunctionBody",
2124 content: "package main\r\n\r\nfunc main() {\r\n\tprintln(\"hi\")\r\n}",
2125 edits: []edit{{search: "\tprintln(\"hi\")\n}", replace: "\tprintln(\"hi\")\n\tprintln(\"bye\")\n\treturn\n}"}},
2126 expected: "package main\r\n\r\nfunc main() {\r\n\tprintln(\"hi\")\r\n\tprintln(\"bye\")\r\n\treturn\r\n}",
2127 },
2128 // LF file, CRLF search/replace (caller sent CRLF, file is
2129 // LF). Internal endings agree (both CRLF). Rule fires, the
2130 // file's LF wins.
2131 {
2132 name: "LFFile_CRLFSearchReplace_FileLFWins",
2133 content: "one\ntwo\nthree\n",
2134 edits: []edit{{search: "one\r\ntwo\r\n", replace: "ONE\r\nTWO\r\n"}},
2135 expected: "ONE\nTWO\nthree\n",
2136 },
2137 // Caller got endings right: CRLF in search, replace, and file.
2138 // Pins that normalization doesn't regress this happy path.
2139 {
2140 name: "CRLFFile_CRLFSearchReplace_SanityPreserved",
2141 content: "a\r\nb\r\nc\r\n",

Callers

nothing calls this directly

Calls 11

RoutesMethod · 0.95
NewAPIFunction · 0.92
ContextFunction · 0.92
EncodeMethod · 0.80
TempDirMethod · 0.65
RunMethod · 0.65
WriteFileMethod · 0.65
ReadFileMethod · 0.65
ServeHTTPMethod · 0.45
EqualMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected