Skip to content

Commit 4617960

Browse files
authored
Merge pull request #2 from trufflesecurity/533-optimize-parse
Fix tests and add Parse benchmark
2 parents bef745d + d60e122 commit 4617960

File tree

2 files changed

+115
-2
lines changed

2 files changed

+115
-2
lines changed

gitdiff/apply_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,14 @@ func (at applyTest) run(t *testing.T, apply func(io.Writer, *Applier, *File) err
234234

235235
cmd := exec.Command("echo", "hello")
236236

237-
files, err := Parse(cmd, io.NopCloser(bytes.NewReader(patch)))
237+
fileChan, err := Parse(cmd, io.NopCloser(bytes.NewReader(patch)))
238238
if err != nil {
239239
t.Fatalf("failed to parse patch file: %v", err)
240240
}
241+
var files []*File
242+
for file := range fileChan {
243+
files = append(files, file)
244+
}
241245
if len(files) != 1 {
242246
t.Fatalf("patch should contain exactly one file, but it has %d", len(files))
243247
}

gitdiff/parser_test.go

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ import (
44
"bytes"
55
"encoding/binary"
66
"encoding/json"
7+
"fmt"
78
"io"
89
"os"
910
"os/exec"
1011
"reflect"
12+
"strings"
1113
"testing"
14+
"time"
1215
)
1316

1417
func TestLineOperations(t *testing.T) {
@@ -395,6 +398,16 @@ Date: Tue Apr 2 22:55:40 2019 -0700
395398
InputFile: "testdata/one_file.patch",
396399
Output: []*File{
397400
{
401+
PatchHeader: &PatchHeader{
402+
SHA: "5d9790fec7d95aa223f3d20936340bf55ff3dcbe",
403+
Author: &PatchIdentity{
404+
Name: "Morton Haypenny",
405+
Email: "mhaypenny@example.com",
406+
},
407+
AuthorDate: asTime("2019-04-02T22:55:40-07:00"),
408+
Title: "A file with multiple fragments.",
409+
Body: "The content is arbitrary.",
410+
},
398411
OldName: "dir/file1.txt",
399412
NewName: "dir/file1.txt",
400413
OldMode: os.FileMode(0100644),
@@ -409,6 +422,16 @@ Date: Tue Apr 2 22:55:40 2019 -0700
409422
InputFile: "testdata/two_files.patch",
410423
Output: []*File{
411424
{
425+
PatchHeader: &PatchHeader{
426+
SHA: "5d9790fec7d95aa223f3d20936340bf55ff3dcbe",
427+
Author: &PatchIdentity{
428+
Name: "Morton Haypenny",
429+
Email: "mhaypenny@example.com",
430+
},
431+
AuthorDate: asTime("2019-04-02T22:55:40-07:00"),
432+
Title: "A file with multiple fragments.",
433+
Body: "The content is arbitrary.",
434+
},
412435
OldName: "dir/file1.txt",
413436
NewName: "dir/file1.txt",
414437
OldMode: os.FileMode(0100644),
@@ -417,6 +440,16 @@ Date: Tue Apr 2 22:55:40 2019 -0700
417440
TextFragments: textFragments,
418441
},
419442
{
443+
PatchHeader: &PatchHeader{
444+
SHA: "5d9790fec7d95aa223f3d20936340bf55ff3dcbe",
445+
Author: &PatchIdentity{
446+
Name: "Morton Haypenny",
447+
Email: "mhaypenny@example.com",
448+
},
449+
AuthorDate: asTime("2019-04-02T22:55:40-07:00"),
450+
Title: "A file with multiple fragments.",
451+
Body: "The content is arbitrary.",
452+
},
420453
OldName: "dir/file2.txt",
421454
NewName: "dir/file2.txt",
422455
OldMode: os.FileMode(0100644),
@@ -431,6 +464,15 @@ Date: Tue Apr 2 22:55:40 2019 -0700
431464
InputFile: "testdata/new_binary_file.patch",
432465
Output: []*File{
433466
{
467+
PatchHeader: &PatchHeader{
468+
SHA: "5d9790fec7d95aa223f3d20936340bf55ff3dcbe",
469+
Author: &PatchIdentity{
470+
Name: "Morton Haypenny",
471+
Email: "mhaypenny@example.com",
472+
},
473+
AuthorDate: asTime("2019-04-02T22:55:40-07:00"),
474+
Title: "A binary file with the first 10 fibonacci numbers.",
475+
},
434476
OldName: "",
435477
NewName: "dir/ten.bin",
436478
NewMode: os.FileMode(0100644),
@@ -463,7 +505,7 @@ Date: Tue Apr 2 22:55:40 2019 -0700
463505

464506
cmd := exec.Command("echo", "hello")
465507

466-
files, err := Parse(cmd, f)
508+
fileChan, err := Parse(cmd, f)
467509
if test.Err {
468510
if err == nil || err == io.EOF {
469511
t.Fatalf("expected error parsing patch, but got %v", err)
@@ -473,6 +515,10 @@ Date: Tue Apr 2 22:55:40 2019 -0700
473515
if err != nil {
474516
t.Fatalf("unexpected error parsing patch: %v", err)
475517
}
518+
var files []*File
519+
for file := range fileChan {
520+
files = append(files, file)
521+
}
476522

477523
if len(test.Output) != len(files) {
478524
t.Fatalf("incorrect number of parsed files: expected %d, actual %d", len(test.Output), len(files))
@@ -488,10 +534,73 @@ Date: Tue Apr 2 22:55:40 2019 -0700
488534
}
489535
}
490536

537+
func BenchmarkParse(b *testing.B) {
538+
var inputDiff string
539+
{
540+
builder := strings.Builder{}
541+
builder.WriteString(`commit 5d9790fec7d95aa223f3d20936340bf55ff3dcbe
542+
Author: Morton Haypenny <mhaypenny@example.com>
543+
Date: Tue Apr 2 22:55:40 2019 -0700
544+
545+
A file with multiple fragments.
546+
547+
The content is arbitrary.
548+
549+
`)
550+
fileDiff := func(i int) string {
551+
return fmt.Sprintf(`diff --git a/dir/file%[1]d.txt b/dir/file%[1]d.txt
552+
index ebe9fa54..fe103e1d 100644
553+
--- a/dir/file%[1]d.txt
554+
+++ b/dir/file%[1]d.txt
555+
@@ -3,6 +3,8 @@ fragment 1
556+
context line
557+
-old line 1
558+
-old line 2
559+
context line
560+
+new line 1
561+
+new line 2
562+
+new line 3
563+
context line
564+
-old line 3
565+
+new line 4
566+
+new line 5
567+
@@ -31,2 +33,2 @@ fragment 2
568+
context line
569+
-old line 4
570+
+new line 6
571+
`, i)
572+
}
573+
for i := 0; i < 1000; i++ {
574+
_, err := builder.WriteString(fileDiff(i))
575+
if err != nil {
576+
panic(err)
577+
}
578+
}
579+
inputDiff = builder.String()
580+
}
581+
for i := 0; i < b.N; i++ {
582+
reader := io.NopCloser(strings.NewReader(inputDiff))
583+
ch, err := Parse(&exec.Cmd{}, reader)
584+
if err != nil {
585+
panic(err)
586+
}
587+
for range ch {
588+
}
589+
}
590+
}
591+
491592
func newTestParser(input string, init bool) *parser {
492593
p := newParser(bytes.NewBufferString(input))
493594
if init {
494595
_ = p.Next()
495596
}
496597
return p
497598
}
599+
600+
func asTime(s string) time.Time {
601+
t, err := time.Parse(time.RFC3339, s)
602+
if err != nil {
603+
panic(err)
604+
}
605+
return t
606+
}

0 commit comments

Comments
 (0)