Skip to content

Commit 9fc14fd

Browse files
committed
Add tests for file-level application
Also refactor the apply tests to use a common type now that there are three variants that do almost the same thing for each test.
1 parent 19ec1a2 commit 9fc14fd

10 files changed

+544
-63
lines changed

gitdiff/apply_test.go

+67-63
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,8 @@ func TestApplierInvariants(t *testing.T) {
7373
})
7474
}
7575

76-
func TestTextFragmentApplyStrict(t *testing.T) {
77-
tests := map[string]struct {
78-
Files applyFiles
79-
Err error
80-
}{
76+
func TestApplyTextFragment(t *testing.T) {
77+
tests := map[string]applyTest{
8178
"createFile": {Files: getApplyFiles("text_fragment_new")},
8279
"deleteFile": {Files: getApplyFiles("text_fragment_delete_all")},
8380

@@ -131,43 +128,18 @@ func TestTextFragmentApplyStrict(t *testing.T) {
131128

132129
for name, test := range tests {
133130
t.Run(name, func(t *testing.T) {
134-
src, patch, out := test.Files.Load(t)
135-
136-
files, _, err := Parse(bytes.NewReader(patch))
137-
if err != nil {
138-
t.Fatalf("failed to parse patch file: %v", err)
139-
}
140-
if len(files) != 1 {
141-
t.Fatalf("patch should contain exactly one file, but it has %d", len(files))
142-
}
143-
if len(files[0].TextFragments) != 1 {
144-
t.Fatalf("patch should contain exactly one fragment, but it has %d", len(files[0].TextFragments))
145-
}
146-
147-
applier := NewApplier(bytes.NewReader(src))
148-
149-
var dst bytes.Buffer
150-
err = applier.ApplyTextFragment(&dst, files[0].TextFragments[0])
151-
if test.Err != nil {
152-
checkApplyError(t, test.Err, err)
153-
return
154-
}
155-
if err != nil {
156-
t.Fatalf("unexpected error applying fragment: %v", err)
157-
}
158-
159-
if !bytes.Equal(out, dst.Bytes()) {
160-
t.Errorf("incorrect result after apply\nexpected:\n%s\nactual:\n%s", out, dst.Bytes())
161-
}
131+
test.run(t, func(w io.Writer, applier *Applier, file *File) error {
132+
if len(file.TextFragments) != 1 {
133+
t.Fatalf("patch should contain exactly one fragment, but it has %d", len(file.TextFragments))
134+
}
135+
return applier.ApplyTextFragment(w, file.TextFragments[0])
136+
})
162137
})
163138
}
164139
}
165140

166-
func TestBinaryFragmentApply(t *testing.T) {
167-
tests := map[string]struct {
168-
Files applyFiles
169-
Err interface{}
170-
}{
141+
func TestApplyBinaryFragment(t *testing.T) {
142+
tests := map[string]applyTest{
171143
"literalCreate": {Files: getApplyFiles("bin_fragment_literal_create")},
172144
"literalModify": {Files: getApplyFiles("bin_fragment_literal_modify")},
173145
"deltaModify": {Files: getApplyFiles("bin_fragment_delta_modify")},
@@ -205,41 +177,73 @@ func TestBinaryFragmentApply(t *testing.T) {
205177

206178
for name, test := range tests {
207179
t.Run(name, func(t *testing.T) {
208-
src, patch, out := test.Files.Load(t)
180+
test.run(t, func(w io.Writer, applier *Applier, file *File) error {
181+
return applier.ApplyBinaryFragment(w, file.BinaryFragment)
182+
})
183+
})
184+
}
185+
}
186+
187+
func TestApplyFile(t *testing.T) {
188+
tests := map[string]applyTest{
189+
"textModify": {Files: getApplyFiles("text_file_modify")},
190+
"binaryModify": {Files: getApplyFiles("bin_file_modify")},
191+
"modeChange": {Files: getApplyFiles("file_mode_change")},
192+
}
193+
194+
for name, test := range tests {
195+
t.Run(name, func(t *testing.T) {
196+
test.run(t, func(w io.Writer, applier *Applier, file *File) error {
197+
return applier.ApplyFile(w, file)
198+
})
199+
})
200+
}
201+
}
202+
203+
type applyTest struct {
204+
Files applyFiles
205+
Err interface{}
206+
}
207+
208+
func (at applyTest) run(t *testing.T, apply func(io.Writer, *Applier, *File) error) {
209+
src, patch, out := at.Files.Load(t)
209210

210-
files, _, err := Parse(bytes.NewReader(patch))
211-
if err != nil {
212-
t.Fatalf("failed to parse patch file: %v", err)
213-
}
214-
if len(files) != 1 {
215-
t.Fatalf("patch should contain exactly one file, but it has %d", len(files))
216-
}
211+
files, _, err := Parse(bytes.NewReader(patch))
212+
if err != nil {
213+
t.Fatalf("failed to parse patch file: %v", err)
214+
}
215+
if len(files) != 1 {
216+
t.Fatalf("patch should contain exactly one file, but it has %d", len(files))
217+
}
217218

218-
applier := NewApplier(bytes.NewReader(src))
219+
applier := NewApplier(bytes.NewReader(src))
219220

220-
var dst bytes.Buffer
221-
err = applier.ApplyBinaryFragment(&dst, files[0].BinaryFragment)
222-
if test.Err != nil {
223-
checkApplyError(t, test.Err, err)
224-
return
225-
}
226-
if err != nil {
227-
t.Fatalf("unexpected error applying fragment: %v", err)
228-
}
221+
var dst bytes.Buffer
222+
err = apply(&dst, applier, files[0])
223+
if at.Err != nil {
224+
at.assertError(t, err)
225+
return
226+
}
227+
if err != nil {
228+
var aerr *ApplyError
229+
if errors.As(err, &aerr) {
230+
t.Fatalf("unexpected error applying: at %d: fragment %d at %d: %v", aerr.Line, aerr.Fragment, aerr.FragmentLine, err)
231+
} else {
232+
t.Fatalf("unexpected error applying: %v", err)
233+
}
234+
}
229235

230-
if !bytes.Equal(out, dst.Bytes()) {
231-
t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes())
232-
}
233-
})
236+
if !bytes.Equal(out, dst.Bytes()) {
237+
t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes())
234238
}
235239
}
236240

237-
func checkApplyError(t *testing.T, terr interface{}, err error) {
241+
func (at applyTest) assertError(t *testing.T, err error) {
238242
if err == nil {
239243
t.Fatalf("expected error applying fragment, but got nil")
240244
}
241245

242-
switch terr := terr.(type) {
246+
switch terr := at.Err.(type) {
243247
case string:
244248
if !strings.Contains(err.Error(), terr) {
245249
t.Fatalf("incorrect apply error: %q does not contain %q", err.Error(), terr)
@@ -249,7 +253,7 @@ func checkApplyError(t *testing.T, terr interface{}, err error) {
249253
t.Fatalf("incorrect apply error: expected: %T (%v), actual: %T (%v)", terr, terr, err, err)
250254
}
251255
default:
252-
t.Fatalf("unsupported error type: %T", terr)
256+
t.Fatalf("unsupported expected error type: %T", terr)
253257
}
254258
}
255259

1.06 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
diff --git a/gitdiff/testdata/apply/bin_file_modify.src b/gitdiff/testdata/apply/bin_file_modify.src
2+
GIT binary patch
3+
delta 172
4+
zcmV;d08{^f2)qc8AP{I3VQ>J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo
5+
zWu(4bg|8QwzZ|1e*rL4P#)`Fen<n~ik=E?$qG6?hzJ6$u{l5W#?uwHb0q6w)00000
6+
zlLZ3%0RfW%1N%UMJ{~Z~0@X${&1Kk#98tb3==a{J7A;`O`v&<T@514_mvMTz72b#n
7+
atf$#NLoPbNe?RPFJVt1aCFGoQbiKD!OHgJ2
8+
9+
delta 112
10+
zcmV-$0FVE?2!IHXAP~DY<7&llQfwqYA%tL<sR@xVtUMD;+4ZG>XTQ5=J2y;^BfB}4
11+
zWkisH791|vOVl5e-@^VLX0s~Ky_UyN!3;CgPr>Edj0j+0gOSwSsFsr$0q6zUJph<q
12+
SlLZ3%0XmZb1N#I__7UCuR5Dxu
13+
1 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
echo "this file is executable"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
diff --git a/gitdiff/testdata/apply/file_mode_change.src b/gitdiff/testdata/apply/file_mode_change.src
2+
old mode 100644
3+
new mode 100755
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
echo "this file is executable"
+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
the first line is different
2+
this is line 2
3+
this is line 3
4+
this is line 4
5+
this is line 5
6+
this is line 6
7+
this is line 7
8+
this is line 8
9+
this is line 9
10+
this is line 10
11+
this is line 11
12+
this is line 12
13+
this is line 13
14+
this is line 14
15+
this is line 15
16+
this is line 16
17+
this is line 17
18+
this is line 18
19+
this is line 19
20+
this line offsets all the line numbers!
21+
this is line 20
22+
this is line 21
23+
until here, now we're back on track!
24+
this is line 24
25+
this is line 25
26+
this is line 26
27+
this is line 27
28+
this is line 28
29+
this is line 29
30+
this is line 30
31+
this is line 31
32+
this is line 32
33+
this is line 33
34+
this is line 34
35+
this is line 35
36+
this is line 36
37+
this is line 37
38+
this is line 38
39+
this is line 39
40+
this is line 40
41+
this is line 41
42+
this is line 42
43+
this is line 43
44+
this is line 44
45+
this is line 45
46+
this is line 46
47+
this is line 47
48+
this is line 48
49+
this is line 49
50+
this is line 50
51+
this is line 51
52+
this is line 52
53+
this is line 53
54+
this is line 54
55+
this is line 55
56+
once upon a time, a line
57+
in a text
58+
file
59+
changed
60+
this is line 60
61+
this is line 61
62+
this is line 62
63+
this is line 63
64+
this is line 64
65+
this is line 65
66+
this is line 66
67+
this is line 67
68+
this is line 68
69+
this is line 69
70+
this is line 70
71+
this is line 71
72+
this is line 72
73+
this is line 73
74+
this is line 74
75+
this is line 75
76+
this is line 76
77+
this is line 77
78+
this is line 78
79+
this is line 79
80+
this is line 80
81+
this is line 81
82+
this is line 82
83+
this is line 83
84+
this is line 84
85+
this is line 85
86+
this is line 86
87+
this is line 87
88+
this is line 88
89+
this is line 89
90+
this is line 90
91+
this is line 91
92+
this is line 92
93+
this is line 93
94+
this is line 94
95+
this is line 95
96+
this is line 96
97+
this is line 97
98+
this is line 98
99+
this is line 99
100+
this is line 100
101+
this is line 101
102+
this is line 102
103+
this is line 103
104+
this is line 104
105+
this is line 105
106+
this is line 106
107+
this is line 107
108+
this is line 108
109+
this is line 109
110+
this is line 110
111+
this is line 111
112+
this is line 112
113+
this is line 113
114+
this is line 114
115+
this is line 115
116+
this is line 116
117+
this is line 117
118+
this is line 118
119+
this is line 119
120+
this is line 120
121+
this is line 121
122+
this is line 122
123+
this is line 123
124+
this is line 124
125+
this is line 125
126+
this is line 126
127+
this is line 127
128+
this is line 128
129+
this is line 129
130+
this is line 130
131+
this is line 131
132+
this is line 132
133+
this line was bad and has been removed
134+
this line was REDACTED and has been REDACTED
135+
this is line 135
136+
this is line 136
137+
this is line 137
138+
this is line 138
139+
this is line 139
140+
this is line 140
141+
this is line 141
142+
this is line 142
143+
this is line 143
144+
this is line 144
145+
this is line 145
146+
this is line 146
147+
this is line 147
148+
this is line 148
149+
this is line 149
150+
this is line 150
151+
this is line 151
152+
this is line 152
153+
this is line 153
154+
this is line 154
155+
this is line 155
156+
this is line 156
157+
this is line 157
158+
this is line 158
159+
this is line 159
160+
this is line 160
161+
this is line 161
162+
this is line 162
163+
this is line 163
164+
the number on the remaining lines is 5 ahead of their actual position in the file
165+
this is line 170
166+
this is line 171
167+
this is line 172
168+
this is line 173
169+
this is line 174
170+
this is line 175
171+
this is line 176
172+
this is line 177
173+
this is line 178
174+
this is line 179
175+
this is line 180
176+
this is line 181
177+
this is line 182
178+
this is line 183
179+
this is line 184
180+
this is line 185
181+
this is line 186
182+
this is line 187
183+
this is line 188
184+
this is line 189
185+
this is line 190
186+
this is line 191
187+
this is line 192
188+
this is line 193
189+
this is line 194
190+
this is line 195
191+
this is line 196
192+
this is line 197
193+
this is line 198
194+
this is line 199
195+
this is line 200

0 commit comments

Comments
 (0)