mirror of
https://github.com/bluekeyes/go-gitdiff
synced 2026-06-08 13:18:30 +00:00
9b0fc30459
After considering fragment parsing, it made sense to change the invariant estabilished in the previous commit. Specifically, parser functions now assume they are call on the first line of their object and return with the parser on the first line after their object. This means code can call parse function immediately after each other without advancing the parser in between. It's possible this will change back later on... there seem to be annoying edge cases with either choice, but I think making the functions consistent is important.
202 lines
4.0 KiB
Go
202 lines
4.0 KiB
Go
package gitdiff
|
|
|
|
import (
|
|
"bufio"
|
|
"io"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestLineOperations(t *testing.T) {
|
|
const content = "the first line\nthe second line\nthe third line\n"
|
|
|
|
newParser := func() *parser {
|
|
return &parser{r: bufio.NewReader(strings.NewReader(content))}
|
|
}
|
|
|
|
t.Run("read", func(t *testing.T) {
|
|
p := newParser()
|
|
|
|
if err := p.Next(); err != nil {
|
|
t.Fatalf("error advancing parser: %v", err)
|
|
}
|
|
|
|
line := p.Line(0)
|
|
if line != "the first line\n" {
|
|
t.Fatalf("incorrect first line: %s", line)
|
|
}
|
|
|
|
if err := p.Next(); err != nil {
|
|
t.Fatalf("error advancing parser: %v", err)
|
|
}
|
|
|
|
line = p.Line(0)
|
|
if line != "the second line\n" {
|
|
t.Fatalf("incorrect second line: %s", line)
|
|
}
|
|
|
|
if err := p.Next(); err != nil {
|
|
t.Fatalf("error advancing parser: %v", err)
|
|
}
|
|
|
|
line = p.Line(0)
|
|
if line != "the third line\n" {
|
|
t.Fatalf("incorrect third line: %s", line)
|
|
}
|
|
|
|
if err := p.Next(); err != io.EOF {
|
|
t.Fatalf("expected EOF, but got: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("peek", func(t *testing.T) {
|
|
p := newParser()
|
|
|
|
if err := p.Next(); err != nil {
|
|
t.Fatalf("error advancing parser: %v", err)
|
|
}
|
|
|
|
line := p.Line(1)
|
|
if line != "the second line\n" {
|
|
t.Fatalf("incorrect peek line: %s", line)
|
|
}
|
|
|
|
if err := p.Next(); err != nil {
|
|
t.Fatalf("error advancing parser: %v", err)
|
|
}
|
|
|
|
line = p.Line(0)
|
|
if line != "the second line\n" {
|
|
t.Fatalf("incorrect line: %s", line)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestParserAdvancment(t *testing.T) {
|
|
tests := map[string]struct {
|
|
Input string
|
|
Parse func(p *parser) error
|
|
EndLine string
|
|
}{
|
|
"ParseGitFileHeader": {
|
|
Input: `diff --git a/dir/file.txt b/dir/file.txt
|
|
index 9540595..30e6333 100644
|
|
--- a/dir/file.txt
|
|
+++ b/dir/file.txt
|
|
@@ -1,2 +1,3 @@
|
|
context line
|
|
`,
|
|
Parse: func(p *parser) error {
|
|
_, err := p.ParseGitFileHeader()
|
|
return err
|
|
},
|
|
EndLine: "@@ -1,2 +1,3 @@\n",
|
|
},
|
|
"ParseTraditionalFileHeader": {
|
|
Input: `--- dir/file.txt
|
|
+++ dir/file.txt
|
|
@@ -1,2 +1,3 @@
|
|
context line
|
|
`,
|
|
Parse: func(p *parser) error {
|
|
_, err := p.ParseTraditionalFileHeader()
|
|
return err
|
|
},
|
|
EndLine: "@@ -1,2 +1,3 @@\n",
|
|
},
|
|
"ParseFragmentHeader": {
|
|
Input: `@@ -1,2 +1,3 @@
|
|
context line
|
|
`,
|
|
Parse: func(p *parser) error {
|
|
_, err := p.ParseFragmentHeader()
|
|
return err
|
|
},
|
|
EndLine: "context line\n",
|
|
},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
p := &parser{r: bufio.NewReader(strings.NewReader(test.Input))}
|
|
p.Next()
|
|
|
|
if err := test.Parse(p); err != nil {
|
|
t.Fatalf("unexpected error while parsing: %v", err)
|
|
}
|
|
|
|
if test.EndLine != p.Line(0) {
|
|
t.Errorf("incorrect position after parsing\nexpected: %q\nactual: %q", test.EndLine, p.Line(0))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseFragmentHeader(t *testing.T) {
|
|
tests := map[string]struct {
|
|
Input string
|
|
Output *Fragment
|
|
Err bool
|
|
}{
|
|
"shortest": {
|
|
Input: "@@ -0,0 +1 @@\n",
|
|
Output: &Fragment{
|
|
OldPosition: 0,
|
|
OldLines: 0,
|
|
NewPosition: 1,
|
|
NewLines: 1,
|
|
},
|
|
},
|
|
"standard": {
|
|
Input: "@@ -21,5 +28,9 @@\n",
|
|
Output: &Fragment{
|
|
OldPosition: 21,
|
|
OldLines: 5,
|
|
NewPosition: 28,
|
|
NewLines: 9,
|
|
},
|
|
},
|
|
"trailingComment": {
|
|
Input: "@@ -21,5 +28,9 @@ func test(n int) {\n",
|
|
Output: &Fragment{
|
|
Comment: "func test(n int) {",
|
|
OldPosition: 21,
|
|
OldLines: 5,
|
|
NewPosition: 28,
|
|
NewLines: 9,
|
|
},
|
|
},
|
|
"incomplete": {
|
|
Input: "@@ -12,3 +2\n",
|
|
Err: true,
|
|
},
|
|
"badNumbers": {
|
|
Input: "@@ -1a,2b +3c,4d @@\n",
|
|
Err: true,
|
|
},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
p := &parser{r: bufio.NewReader(strings.NewReader(test.Input))}
|
|
p.Next()
|
|
|
|
frag, err := p.ParseFragmentHeader()
|
|
if test.Err {
|
|
if err == nil {
|
|
t.Fatalf("expected error parsing header, but got nil")
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Fatalf("error parsing header: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(test.Output, frag) {
|
|
t.Fatalf("incorrect fragment\nexpected: %+v\nactual: %+v", test.Output, frag)
|
|
}
|
|
})
|
|
}
|
|
}
|