+52
-13
gitdiff/apply_test.go
+52
-13
gitdiff/apply_test.go
···
6
6
"io"
7
7
"io/ioutil"
8
8
"path/filepath"
9
+
"strings"
9
10
"testing"
10
11
)
11
12
···
85
86
var dst bytes.Buffer
86
87
err = frag.ApplyStrict(&dst, NewLineReader(bytes.NewReader(src), 0))
87
88
if test.Err != nil {
88
-
if err == nil {
89
-
t.Fatalf("expected error applying fragment, but got nil")
90
-
}
91
-
if !errors.Is(err, test.Err) {
92
-
t.Fatalf("incorrect apply error: expected: %T (%v), actual: %T (%v)", test.Err, test.Err, err, err)
93
-
}
89
+
checkApplyError(t, test.Err, err)
94
90
return
95
91
}
96
92
if err != nil {
···
107
103
func TestBinaryFragmentApply(t *testing.T) {
108
104
tests := map[string]struct {
109
105
Files applyFiles
110
-
Err error
106
+
Err interface{}
111
107
}{
112
108
"literalCreate": {Files: getApplyFiles("bin_fragment_literal_create")},
113
109
"literalModify": {Files: getApplyFiles("bin_fragment_literal_modify")},
114
110
"deltaModify": {Files: getApplyFiles("bin_fragment_delta_modify")},
115
111
"deltaModifyLarge": {Files: getApplyFiles("bin_fragment_delta_modify_large")},
112
+
113
+
"errorIncompleteAdd": {
114
+
Files: applyFiles{
115
+
Src: "bin_fragment_delta_error.src",
116
+
Patch: "bin_fragment_delta_error_incomplete_add.patch",
117
+
},
118
+
Err: "incomplete add",
119
+
},
120
+
"errorIncompleteCopy": {
121
+
Files: applyFiles{
122
+
Src: "bin_fragment_delta_error.src",
123
+
Patch: "bin_fragment_delta_error_incomplete_copy.patch",
124
+
},
125
+
Err: "incomplete copy",
126
+
},
127
+
"errorSrcSize": {
128
+
Files: applyFiles{
129
+
Src: "bin_fragment_delta_error.src",
130
+
Patch: "bin_fragment_delta_error_src_size.patch",
131
+
},
132
+
Err: &Conflict{},
133
+
},
134
+
"errorDstSize": {
135
+
Files: applyFiles{
136
+
Src: "bin_fragment_delta_error.src",
137
+
Patch: "bin_fragment_delta_error_dst_size.patch",
138
+
},
139
+
Err: "insufficient or extra data",
140
+
},
116
141
}
117
142
118
143
for name, test := range tests {
···
135
160
var dst bytes.Buffer
136
161
err = frag.Apply(&dst, bytes.NewReader(src))
137
162
if test.Err != nil {
138
-
if err == nil {
139
-
t.Fatalf("expected error applying fragment, but got nil")
140
-
}
141
-
if !errors.Is(err, test.Err) {
142
-
t.Fatalf("incorrect apply error: expected: %T (%v), actual: %T (%v)", test.Err, test.Err, err, err)
143
-
}
163
+
checkApplyError(t, test.Err, err)
144
164
return
145
165
}
146
166
if err != nil {
···
151
171
t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes())
152
172
}
153
173
})
174
+
}
175
+
}
176
+
177
+
func checkApplyError(t *testing.T, terr interface{}, err error) {
178
+
if err == nil {
179
+
t.Fatalf("expected error applying fragment, but got nil")
180
+
}
181
+
182
+
switch terr := terr.(type) {
183
+
case string:
184
+
if !strings.Contains(err.Error(), terr) {
185
+
t.Fatalf("incorrect apply error: %q does not contain %q", err.Error(), terr)
186
+
}
187
+
case error:
188
+
if !errors.Is(err, terr) {
189
+
t.Fatalf("incorrect apply error: expected: %T (%v), actual: %T (%v)", terr, terr, err, err)
190
+
}
191
+
default:
192
+
t.Fatalf("unsupported error type: %T", terr)
154
193
}
155
194
}
156
195
+124
gitdiff/testdata/apply/bin.go
+124
gitdiff/testdata/apply/bin.go
···
1
+
//+build ignore
2
+
3
+
// bin.go is a helper CLI to manipulate binary diff data for testing purposes.
4
+
// It can decode patches generated by git using the standard parsing functions
5
+
// or it can encode binary data back into the format expected by Git. It
6
+
// operates on stdin writes results (possibly binary) to stdout.
7
+
8
+
package main
9
+
10
+
import (
11
+
"bytes"
12
+
"compress/zlib"
13
+
"encoding/binary"
14
+
"flag"
15
+
"io/ioutil"
16
+
"log"
17
+
"os"
18
+
"strings"
19
+
20
+
"github.com/bluekeyes/go-gitdiff/gitdiff"
21
+
)
22
+
23
+
var (
24
+
b85Powers = []uint32{52200625, 614125, 7225, 85, 1}
25
+
b85Alpha = []byte(
26
+
"0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "!#$%&()*+-;<=>?@^_`{|}~",
27
+
)
28
+
)
29
+
30
+
var mode string
31
+
32
+
func base85Encode(data []byte) []byte {
33
+
chunks, remaining := len(data)/4, len(data)%4
34
+
if remaining > 0 {
35
+
data = append(data, make([]byte, 4-remaining)...)
36
+
chunks++
37
+
}
38
+
39
+
var n int
40
+
out := make([]byte, 5*chunks)
41
+
42
+
for i := 0; i < len(data); i += 4 {
43
+
v := binary.BigEndian.Uint32(data[i : i+4])
44
+
for j := 0; j < 5; j++ {
45
+
p := v / b85Powers[j]
46
+
out[n+j] = b85Alpha[p]
47
+
v -= b85Powers[j] * p
48
+
}
49
+
n += 5
50
+
}
51
+
52
+
return out
53
+
}
54
+
55
+
func compress(data []byte) ([]byte, error) {
56
+
var b bytes.Buffer
57
+
w := zlib.NewWriter(&b)
58
+
59
+
if _, err := w.Write(data); err != nil {
60
+
return nil, err
61
+
}
62
+
if err := w.Close(); err != nil {
63
+
return nil, err
64
+
}
65
+
66
+
return b.Bytes(), nil
67
+
}
68
+
69
+
func wrap(data []byte) string {
70
+
var s strings.Builder
71
+
for i := 0; i < len(data); i += 52 {
72
+
c := 52
73
+
if c > len(data)-i {
74
+
c = len(data) - i
75
+
}
76
+
b := (c / 5) * 4
77
+
78
+
if b <= 26 {
79
+
s.WriteByte(byte('A' + b - 1))
80
+
} else {
81
+
s.WriteByte(byte('a' + b - 27))
82
+
}
83
+
s.Write(data[i : i+c])
84
+
s.WriteByte('\n')
85
+
}
86
+
return s.String()
87
+
}
88
+
89
+
func init() {
90
+
flag.StringVar(&mode, "mode", "parse", "operation mode, one of 'parse' or 'encode'")
91
+
}
92
+
93
+
func main() {
94
+
flag.Parse()
95
+
96
+
switch mode {
97
+
case "parse":
98
+
files, _, err := gitdiff.Parse(os.Stdin)
99
+
if err != nil {
100
+
log.Fatalf("failed to parse file: %v", err)
101
+
}
102
+
if len(files) != 1 {
103
+
log.Fatalf("patch contains more than one file: %d", len(files))
104
+
}
105
+
if files[0].BinaryFragment == nil {
106
+
log.Fatalf("patch file does not contain a binary fragment")
107
+
}
108
+
os.Stdout.Write(files[0].BinaryFragment.Data)
109
+
110
+
case "encode":
111
+
data, err := ioutil.ReadAll(os.Stdin)
112
+
if err != nil {
113
+
log.Fatalf("failed to read input: %v", err)
114
+
}
115
+
data, err = compress(data)
116
+
if err != nil {
117
+
log.Fatalf("failed to compress data: %v", err)
118
+
}
119
+
os.Stdout.WriteString(wrap(base85Encode(data)))
120
+
121
+
default:
122
+
log.Fatalf("unknown mode: %s", mode)
123
+
}
124
+
}
gitdiff/testdata/apply/bin_fragment_delta_error.src
gitdiff/testdata/apply/bin_fragment_delta_error.src
This is a binary file and will not be displayed.
+5
gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch
+5
gitdiff/testdata/apply/bin_fragment_delta_error_dst_size.patch
+5
gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch
+5
gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_add.patch
+5
gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch
+5
gitdiff/testdata/apply/bin_fragment_delta_error_incomplete_copy.patch