Files
zzet--gortex/internal/mcp/tools_coding_crlf_test.go
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

161 lines
5.5 KiB
Go

package mcp
import (
"os"
"path/filepath"
"testing"
mcplib "github.com/mark3labs/mcp-go/mcp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// writeCRLFGoFixture writes a CRLF-terminated Go file into the test repo,
// indexes it, and returns its absolute path. The file defines CrlfTarget
// (with a doc comment) followed by a sentinel function whose bytes must
// survive any edit to CrlfTarget untouched.
func writeCRLFGoFixture(t *testing.T, srv *Server, dir string) string {
t.Helper()
src := "package main\r\n" +
"\r\n" +
"// CrlfTarget exercises CRLF-file symbol editing.\r\n" +
"func CrlfTarget() {\r\n" +
"\ta := 1\r\n" +
"\tb := 2\r\n" +
"\t_ = a\r\n" +
"\t_ = b\r\n" +
"}\r\n" +
"\r\n" +
"func crlfSentinel() {\r\n" +
"\tc := 3\r\n" +
"\t_ = c\r\n" +
"}\r\n"
path := filepath.Join(dir, "crlf.go")
require.NoError(t, os.WriteFile(path, []byte(src), 0o644))
require.NoError(t, srv.indexer.IndexFile(path))
return path
}
func TestEditSymbol_CRLFFileLFOldSource(t *testing.T) {
srv, dir := setupTestServer(t)
path := writeCRLFGoFixture(t, srv, dir)
result := callTool(t, srv, "edit_symbol", map[string]any{
"id": "crlf.go::CrlfTarget",
"old_source": "\ta := 1\n\tb := 2",
"new_source": "\ta := 10\n\tb := 20",
})
require.False(t, result.IsError, "LF old_source must match the CRLF file: %v", result.Content)
resp := decodeFileOpsResult(t, result)
assert.Equal(t, "applied", resp["status"])
assert.Equal(t, true, resp["eol_normalized"])
got, err := os.ReadFile(path)
require.NoError(t, err)
assert.Contains(t, string(got), "\ta := 10\r\n\tb := 20\r\n",
"new_source must be written with CRLF endings")
assert.Contains(t, string(got), "func crlfSentinel() {\r\n\tc := 3\r\n",
"bytes after the edited symbol must be untouched — offset arithmetic")
assert.Contains(t, string(got), "// CrlfTarget exercises CRLF-file symbol editing.\r\n",
"bytes before the edited symbol must be untouched")
assertUniformCRLF(t, string(got))
}
func TestEditSymbol_CRLFExactMatchStillPreferred(t *testing.T) {
srv, dir := setupTestServer(t)
path := writeCRLFGoFixture(t, srv, dir)
result := callTool(t, srv, "edit_symbol", map[string]any{
"id": "crlf.go::CrlfTarget",
"old_source": "\ta := 1\r\n\tb := 2",
"new_source": "\ta := 10\r\n\tb := 20",
})
require.False(t, result.IsError, "%v", result.Content)
resp := decodeFileOpsResult(t, result)
assert.Equal(t, "applied", resp["status"])
assert.Nil(t, resp["eol_normalized"], "byte-exact match must not report eol_normalized")
got, err := os.ReadFile(path)
require.NoError(t, err)
assert.Contains(t, string(got), "\ta := 10\r\n\tb := 20\r\n")
assertUniformCRLF(t, string(got))
}
func TestEditSymbol_CRLFUniquenessStillEnforced(t *testing.T) {
srv, dir := setupTestServer(t)
writeCRLFGoFixture(t, srv, dir)
result := callTool(t, srv, "edit_symbol", map[string]any{
"id": "crlf.go::CrlfTarget",
"old_source": "\t_ = ",
"new_source": "\t_, _ = 0, ",
})
require.True(t, result.IsError, "ambiguous fragment within the symbol must be rejected")
text := result.Content[0].(mcplib.TextContent).Text
assert.Contains(t, text, "appears multiple times")
}
func TestEditSymbol_CRLFIdenticalAfterNormalizationRejected(t *testing.T) {
srv, dir := setupTestServer(t)
path := writeCRLFGoFixture(t, srv, dir)
before, err := os.ReadFile(path)
require.NoError(t, err)
result := callTool(t, srv, "edit_symbol", map[string]any{
"id": "crlf.go::CrlfTarget",
"old_source": "\ta := 1\n\tb := 2",
"new_source": "\ta := 1\r\n\tb := 2",
})
require.True(t, result.IsError, "a no-op after EOL adaptation must be rejected")
text := result.Content[0].(mcplib.TextContent).Text
assert.Contains(t, text, "identical after line-ending normalization")
after, err := os.ReadFile(path)
require.NoError(t, err)
assert.Equal(t, string(before), string(after), "file must be untouched")
}
func TestEditSymbol_CRLFDocCommentIncludedInFragment(t *testing.T) {
srv, dir := setupTestServer(t)
path := writeCRLFGoFixture(t, srv, dir)
// Agents often paste the doc comment along with the signature — the
// doc-comment expansion path must stay EOL-tolerant too.
result := callTool(t, srv, "edit_symbol", map[string]any{
"id": "crlf.go::CrlfTarget",
"old_source": "// CrlfTarget exercises CRLF-file symbol editing.\nfunc CrlfTarget() {",
"new_source": "// CrlfTarget exercises CRLF-file symbol editing (edited).\nfunc CrlfTarget() {",
})
require.False(t, result.IsError, "%v", result.Content)
resp := decodeFileOpsResult(t, result)
assert.Equal(t, "applied", resp["status"])
got, err := os.ReadFile(path)
require.NoError(t, err)
assert.Contains(t, string(got),
"// CrlfTarget exercises CRLF-file symbol editing (edited).\r\nfunc CrlfTarget() {\r\n")
assertUniformCRLF(t, string(got))
}
func TestEditSymbol_CRLFDryRunReportsNormalized(t *testing.T) {
srv, dir := setupTestServer(t)
path := writeCRLFGoFixture(t, srv, dir)
before, err := os.ReadFile(path)
require.NoError(t, err)
result := callTool(t, srv, "edit_symbol", map[string]any{
"id": "crlf.go::CrlfTarget",
"old_source": "\ta := 1\n\tb := 2",
"new_source": "\ta := 10\n\tb := 20",
"dry_run": true,
})
require.False(t, result.IsError, "%v", result.Content)
resp := decodeFileOpsResult(t, result)
assert.Equal(t, "would_apply", resp["status"])
assert.Equal(t, true, resp["eol_normalized"])
after, err := os.ReadFile(path)
require.NoError(t, err)
assert.Equal(t, string(before), string(after), "dry_run must not write")
}