123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 | package diff
import (
"strings"
"testing"
)
func TestUnifiedRoundTrip(t *testing.T) {
a := "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\n"
b := "a\nB\nc\nd\ne\nf\ng\nh\nI\nj\nk\n"
u := Unified("f", a, b, 2)
if !strings.Contains(u, "-b\n+B\n") || strings.Count(u, "@@ ") != 2 {
t.Fatalf("unexpected diff:\n%s", u)
}
got, err := Apply(a, u)
if err != nil {
t.Fatal(err)
}
if got != b {
t.Errorf("Apply = %q, want %q", got, b)
}
if Unified("f", a, a, 3) != "" {
t.Error("diff of equal texts")
}
if add, del := Stat(a, b); add != 3 || del != 2 {
t.Errorf("Stat = +%d -%d", add, del)
}
}
func TestApplyIgnoresWrongLineNumbers(t *testing.T) {
text := "func a() {\n\treturn 1\n}\n\nfunc b() {\n\treturn 2\n}\n"
patch := `--- x.go
+++ x.go
@@ -40,3 +40,3 @@
func b() {
- return 2
+ return 3
}
`
got, err := Apply(text, patch)
if err != nil {
t.Fatal(err)
}
if !strings.Contains(got, "return 3") || !strings.Contains(got, "return 1") {
t.Errorf("got %q", got)
}
}
func TestApplyErrors(t *testing.T) {
text := "x\ny\nx\ny\n"
if _, err := Apply(text, "@@\n x\n-y\n+z\n"); err == nil || !strings.Contains(err.Error(), "2 places") {
t.Errorf("ambiguous hunk: %v", err)
}
if _, err := Apply(text, "@@\n q\n-y\n+z\n"); err == nil || !strings.Contains(err.Error(), "not found") {
t.Errorf("missing hunk: %v", err)
}
if _, err := Apply(text, "no hunks here"); err == nil {
t.Error("garbage applied")
}
}
func TestApplyAmbiguousIgnoresHint(t *testing.T) {
// The header points at the second match, but a wrong number would
// look the same, so the hunk is refused rather than placed by it.
text := "x\ny\nx\ny\n"
_, err := Apply(text, "@@ -3,2 +3,2 @@\n x\n-y\n+z\n")
if err == nil || !strings.Contains(err.Error(), "2 places (line 1, line 3)") {
t.Errorf("ambiguous hunk: %v", err)
}
// Hunks are applied in order, so only matches after the earlier
// hunks count.
got, err := Apply("a\n"+text, "@@\n-a\n+b\n x\n y\n@@\n x\n-y\n+z\n")
if err != nil || got != "b\nx\ny\nx\nz\n" {
t.Errorf("unique after the first hunk: %q, %v", got, err)
}
// After an earlier hunk, the lines are named as the model read them.
_, err = Apply("q\n"+text, "@@\n-q\n+a\n+b\n@@\n x\n-y\n+z\n")
if err == nil || !strings.Contains(err.Error(), "(line 2, line 4)") {
t.Errorf("ambiguous after a hunk: %v", err)
}
}
func TestApplyAdditionNeedsContext(t *testing.T) {
// A header that names the right line still does not place the lines:
// a wrong one would look the same.
_, err := Apply("a\nb\n", "@@ -1,0 +2 @@\n+x\n")
if err == nil || !strings.Contains(err.Error(), "without any context") {
t.Errorf("addition without context: %v", err)
}
}
func TestApplyNewFile(t *testing.T) {
got, err := Apply("", "--- /dev/null\n+++ new.txt\n@@ -0,0 +1,2 @@\n+one\n+two\n")
if err != nil || got != "one\ntwo\n" {
t.Errorf("got %q, %v", got, err)
}
}
func TestApplyLooseWhitespace(t *testing.T) {
got, err := Apply("a \nb\n", "@@\n a\n-b\n+c\n")
if err != nil || got != "a \nc\n" {
t.Errorf("got %q, %v", got, err)
}
}
|