Files
bluekeyes-go-gitdiff/gitdiff/parser_test.go
T
Billy Keyes 9b0fc30459 Document and enforce parser invariants
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.
2019-03-27 23:10:47 -07:00

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)
}
})
}
}